From cf11cbdb307cb86624e9288134106caaec8b754c Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Fri, 24 Feb 2006 04:48:15 +0000 Subject: [PATCH] Directory restructuring to make it easier to version projects that don't build zdoom.exe. SVN r4 (trunk) --- FLAC/FLAC++/decoder.h | 354 + FLAC/FLAC++/export.h | 47 + FLAC/FLAC.dsp | 327 + FLAC/FLAC.vcproj | 276 + FLAC/FLAC/assert.h | 45 + FLAC/FLAC/export.h | 47 + FLAC/FLAC/format.h | 812 ++ FLAC/FLAC/ordinals.h | 74 + FLAC/FLAC/stream_decoder.h | 873 ++ FLAC/Makefile.mgw | 75 + FLAC/ReadMe.txt | 6 + FLAC/bitbuffer.c | 2530 +++++ FLAC/bitmath.c | 136 + FLAC/cpu.c | 117 + FLAC/crc.c | 149 + FLAC/fixed.c | 231 + FLAC/format.c | 403 + FLAC/ia32/cpu_asm.nasm | 100 + FLAC/ia32/fixed_asm.nasm | 306 + FLAC/ia32/lpc_asm.nasm | 1503 +++ FLAC/ia32/nasm.h | 75 + FLAC/lpc.c | 423 + FLAC/memory.c | 169 + FLAC/private/bitbuffer.h | 159 + FLAC/private/bitmath.h | 41 + FLAC/private/cpu.h | 87 + FLAC/private/crc.h | 57 + FLAC/private/fixed.h | 91 + FLAC/private/format.h | 44 + FLAC/private/lpc.h | 185 + FLAC/private/memory.h | 49 + FLAC/protected/stream_decoder.h | 51 + FLAC/stream_decoder.c | 2112 ++++ FLAC/stream_decoder_pp.cpp | 222 + Makefile | 6 + Makefile.am | 1 + Makefile.mgw | 44 + Makefile.mingw | 434 + bootstrap | 10 + cbuild.c | 2194 +++++ ccdv-win32.c | 610 ++ configure.ac | 176 + default.cbd | 224 + docs/BUILDLIC.TXT | 71 + docs/README.Carmack | 283 + docs/README.asm | 283 + docs/README.gl | 149 + docs/classes.txt | 303 + docs/colors.txt | 756 ++ docs/commands.txt | 1742 ++++ docs/console.css | 162 + docs/console.html | 3587 +++++++ docs/console.txt | 390 + docs/console2.html | 464 + docs/doomlic.txt | 112 + docs/foo.txt | 227 + docs/history.txt | 534 + docs/notes.txt | 22 + docs/rh-log.txt | 11792 +++++++++++++++++++++++ docs/thingdef_doc.txt | 597 ++ docs/zdoom.txt | 1134 +++ src/Makefile.am | 321 + src/a.nas | 302 + src/actor.h | 789 ++ src/am_map.cpp | 2202 +++++ src/am_map.h | 44 + src/announcer.h | 52 + src/autosegs.h | 103 + src/autostart.cpp | 138 + src/autozend.cpp | 80 + src/b_bot.cpp | 110 + src/b_bot.h | 162 + src/b_func.cpp | 586 ++ src/b_game.cpp | 642 ++ src/b_move.cpp | 379 + src/b_think.cpp | 409 + src/basicinlines.h | 237 + src/bbannouncer.cpp | 369 + src/blocks.nas | 1044 ++ src/c_bind.cpp | 727 ++ src/c_bind.h | 58 + src/c_cmds.cpp | 672 ++ src/c_console.cpp | 1937 ++++ src/c_console.h | 82 + src/c_cvars.cpp | 1585 +++ src/c_cvars.h | 386 + src/c_dispatch.cpp | 1282 +++ src/c_dispatch.h | 157 + src/c_expr.cpp | 811 ++ src/cmdlib.cpp | 339 + src/cmdlib.h | 54 + src/colormatcher.cpp | 305 + src/colormatcher.h | 80 + src/configfile.cpp | 451 + src/configfile.h | 113 + src/ct_chat.cpp | 493 + src/d_dehacked.cpp | 2651 +++++ src/d_dehacked.h | 40 + src/d_dehackedactions.h | 108 + src/d_event.h | 105 + src/d_gui.h | 105 + src/d_main.cpp | 2356 +++++ src/d_main.h | 86 + src/d_net.cpp | 2319 +++++ src/d_net.h | 130 + src/d_netinf.h | 109 + src/d_netinfo.cpp | 772 ++ src/d_player.h | 293 + src/d_protocol.cpp | 409 + src/d_protocol.h | 207 + src/d_textur.h | 51 + src/d_ticcmd.h | 50 + src/decallib.cpp | 1396 +++ src/decallib.h | 125 + src/decorations.cpp | 1079 +++ src/dobject.cpp | 722 ++ src/dobject.err | 31 + src/dobject.h | 350 + src/doomdata.h | 358 + src/doomdef.cpp | 29 + src/doomdef.h | 310 + src/doomerrors.h | 85 + src/doomstat.cpp | 70 + src/doomstat.h | 313 + src/doomtype.h | 183 + src/dscript.h | 26 + src/dsectoreffect.cpp | 310 + src/dsectoreffect.h | 71 + src/dthinker.cpp | 405 + src/dthinker.h | 116 + src/empty.cpp | 34 + src/errors.h | 0 src/f_finale.cpp | 1326 +++ src/f_finale.h | 49 + src/f_wipe.cpp | 430 + src/f_wipe.h | 48 + src/farchive.cpp | 1422 +++ src/farchive.h | 291 + src/files.cpp | 164 + src/files.h | 135 + src/g_doom/a_arachnotron.cpp | 167 + src/g_doom/a_archvile.cpp | 415 + src/g_doom/a_bossbrain.cpp | 381 + src/g_doom/a_bruiser.cpp | 252 + src/g_doom/a_cacodemon.cpp | 182 + src/g_doom/a_cyberdemon.cpp | 101 + src/g_doom/a_demon.cpp | 188 + src/g_doom/a_doomarmor.cpp | 102 + src/g_doom/a_doomartifacts.cpp | 304 + src/g_doom/a_doomdecorations.cpp | 403 + src/g_doom/a_doomglobal.h | 101 + src/g_doom/a_doomhealth.cpp | 94 + src/g_doom/a_doomimp.cpp | 202 + src/g_doom/a_doomkeys.cpp | 233 + src/g_doom/a_doommisc.cpp | 150 + src/g_doom/a_doomplayer.cpp | 251 + src/g_doom/a_doomweaps.cpp | 1403 +++ src/g_doom/a_fatso.cpp | 296 + src/g_doom/a_keen.cpp | 82 + src/g_doom/a_lostsoul.cpp | 168 + src/g_doom/a_painelemental.cpp | 223 + src/g_doom/a_possessed.cpp | 598 ++ src/g_doom/a_revenant.cpp | 300 + src/g_doom/a_scriptedmarine.cpp | 981 ++ src/g_doom/a_spidermaster.cpp | 114 + src/g_doom/doom_sbar.cpp | 1051 ++ src/g_game.cpp | 2521 +++++ src/g_game.h | 89 + src/g_heretic/a_beast.cpp | 221 + src/g_heretic/a_chicken.cpp | 543 ++ src/g_heretic/a_clink.cpp | 109 + src/g_heretic/a_dsparil.cpp | 746 ++ src/g_heretic/a_hereticambience.cpp | 393 + src/g_heretic/a_hereticarmor.cpp | 58 + src/g_heretic/a_hereticartifacts.cpp | 165 + src/g_heretic/a_hereticdecorations.cpp | 147 + src/g_heretic/a_hereticglobal.h | 55 + src/g_heretic/a_hereticimp.cpp | 385 + src/g_heretic/a_hereticimp.cpp.bak | 392 + src/g_heretic/a_heretickeys.cpp | 242 + src/g_heretic/a_hereticmisc.cpp | 567 ++ src/g_heretic/a_hereticplayer.cpp | 283 + src/g_heretic/a_hereticweaps.cpp | 3329 +++++++ src/g_heretic/a_ironlich.cpp | 432 + src/g_heretic/a_knight.cpp | 247 + src/g_heretic/a_mummy.cpp | 309 + src/g_heretic/a_snake.cpp | 206 + src/g_heretic/a_wizard.cpp | 208 + src/g_heretic/heretic_sbar.cpp | 770 ++ src/g_hexen/a_bats.cpp | 157 + src/g_hexen/a_bishop.cpp | 450 + src/g_hexen/a_blastradius.cpp | 214 + src/g_hexen/a_boostarmor.cpp | 88 + src/g_hexen/a_centaur.cpp | 339 + src/g_hexen/a_clericboss.cpp | 139 + src/g_hexen/a_clericflame.cpp | 480 + src/g_hexen/a_clericholy.cpp | 912 ++ src/g_hexen/a_clericmace.cpp | 122 + src/g_hexen/a_clericplayer.cpp | 206 + src/g_hexen/a_clericstaff.cpp | 333 + src/g_hexen/a_demons.cpp | 658 ++ src/g_hexen/a_dragon.cpp | 469 + src/g_hexen/a_ettin.cpp | 184 + src/g_hexen/a_fighteraxe.cpp | 473 + src/g_hexen/a_fighterboss.cpp | 121 + src/g_hexen/a_fighterhammer.cpp | 289 + src/g_hexen/a_fighterplayer.cpp | 419 + src/g_hexen/a_fighterquietus.cpp | 396 + src/g_hexen/a_firedemon.cpp | 536 ++ src/g_hexen/a_flame.cpp | 183 + src/g_hexen/a_flechette.cpp | 567 ++ src/g_hexen/a_fog.cpp | 215 + src/g_hexen/a_healingradius.cpp | 76 + src/g_hexen/a_heresiarch.cpp | 1386 +++ src/g_hexen/a_hexenarmor.cpp | 111 + src/g_hexen/a_hexendecorations.cpp | 625 ++ src/g_hexen/a_hexenglobal.h | 152 + src/g_hexen/a_hexenkeys.cpp | 45 + src/g_hexen/a_hexenspecialdecs.cpp | 1339 +++ src/g_hexen/a_iceguy.cpp | 404 + src/g_hexen/a_korax.cpp | 708 ++ src/g_hexen/a_mageboss.cpp | 135 + src/g_hexen/a_magecone.cpp | 279 + src/g_hexen/a_magelightning.cpp | 586 ++ src/g_hexen/a_mageplayer.cpp | 213 + src/g_hexen/a_magestaff.cpp | 541 ++ src/g_hexen/a_magewand.cpp | 206 + src/g_hexen/a_mana.cpp | 216 + src/g_hexen/a_pig.cpp | 406 + src/g_hexen/a_puzzleitems.cpp | 523 + src/g_hexen/a_scriptprojectiles.cpp | 187 + src/g_hexen/a_serpent.cpp | 722 ++ src/g_hexen/a_speedboots.cpp | 40 + src/g_hexen/a_spike.cpp | 319 + src/g_hexen/a_summon.cpp | 169 + src/g_hexen/a_teleportother.cpp | 317 + src/g_hexen/a_weaponpieces.cpp | 188 + src/g_hexen/a_wraith.cpp | 556 ++ src/g_hexen/hexen_sbar.cpp | 1163 +++ src/g_level.cpp | 2697 ++++++ src/g_level.h | 321 + src/g_raven/a_artiegg.cpp | 476 + src/g_raven/a_artitele.cpp | 94 + src/g_raven/a_minotaur.cpp | 975 ++ src/g_raven/a_ravenambient.cpp | 86 + src/g_raven/a_ravenartifacts.cpp | 168 + src/g_raven/a_ravenhealth.cpp | 31 + src/g_raven/ravenshared.h | 38 + src/g_shared/a_action.cpp | 571 ++ src/g_shared/a_action.h | 26 + src/g_shared/a_artifacts.cpp | 1041 ++ src/g_shared/a_artifacts.h | 186 + src/g_shared/a_bridge.cpp | 218 + src/g_shared/a_camera.cpp | 216 + src/g_shared/a_debris.cpp | 298 + src/g_shared/a_decals.cpp | 769 ++ src/g_shared/a_flashfader.cpp | 70 + src/g_shared/a_fountain.cpp | 88 + src/g_shared/a_hatetarget.cpp | 93 + src/g_shared/a_keys.cpp | 499 + src/g_shared/a_keys.h | 48 + src/g_shared/a_lightning.cpp | 201 + src/g_shared/a_lightning.h | 32 + src/g_shared/a_movingcamera.cpp | 688 ++ src/g_shared/a_pickups.cpp | 2045 ++++ src/g_shared/a_pickups.h | 408 + src/g_shared/a_pickups.h.bak | 361 + src/g_shared/a_quake.cpp | 114 + src/g_shared/a_secrettrigger.cpp | 79 + src/g_shared/a_sectoraction.cpp | 302 + src/g_shared/a_sharedglobal.h | 188 + src/g_shared/a_sharedmisc.cpp | 151 + src/g_shared/a_skies.cpp | 223 + src/g_shared/a_soundenvironment.cpp | 74 + src/g_shared/a_spark.cpp | 63 + src/g_shared/a_splashes.cpp | 229 + src/g_shared/a_waterzone.cpp | 55 + src/g_shared/a_weaponpiece.cpp | 169 + src/g_shared/a_weaponpiece.h | 17 + src/g_shared/a_weapons.cpp | 1009 ++ src/g_shared/hudmessages.cpp | 760 ++ src/g_shared/sbar.h | 258 + src/g_shared/shared_sbar.cpp | 1630 ++++ src/g_strife/a_acolyte.cpp | 427 + src/g_strife/a_alienspectres.cpp | 588 ++ src/g_strife/a_beggars.cpp | 161 + src/g_strife/a_coin.cpp | 215 + src/g_strife/a_crusader.cpp | 252 + src/g_strife/a_entityboss.cpp | 388 + src/g_strife/a_inquisitor.cpp | 297 + src/g_strife/a_loremaster.cpp | 210 + src/g_strife/a_macil.cpp | 182 + src/g_strife/a_merchants.cpp | 227 + src/g_strife/a_oracle.cpp | 87 + src/g_strife/a_peasant.cpp | 427 + src/g_strife/a_programmer.cpp | 297 + src/g_strife/a_questitems.cpp | 449 + src/g_strife/a_ratbuddy.cpp | 53 + src/g_strife/a_reaver.cpp | 146 + src/g_strife/a_rebels.cpp | 324 + src/g_strife/a_sentinel.cpp | 194 + src/g_strife/a_spectral.cpp | 303 + src/g_strife/a_stalker.cpp | 194 + src/g_strife/a_strifeammo.cpp | 304 + src/g_strife/a_strifearmor.cpp | 69 + src/g_strife/a_strifebishop.cpp | 212 + src/g_strife/a_strifeglobal.h | 201 + src/g_strife/a_strifeitems.cpp | 1028 ++ src/g_strife/a_strifekeys.cpp | 980 ++ src/g_strife/a_strifeplayer.cpp | 140 + src/g_strife/a_strifestuff.cpp | 3003 ++++++ src/g_strife/a_strifeweapons.cpp | 2468 +++++ src/g_strife/a_strifeweaps.h | 71 + src/g_strife/a_templar.cpp | 142 + src/g_strife/a_thingstoblowup.cpp | 284 + src/g_strife/a_zombie.cpp | 90 + src/g_strife/strife_sbar.cpp | 842 ++ src/gameconfigfile.cpp | 757 ++ src/gameconfigfile.h | 74 + src/gccinlines.h | 355 + src/gi.cpp | 401 + src/gi.h | 120 + src/gstrings.h | 51 + src/hu_scores.cpp | 269 + src/hu_stuff.h | 51 + src/i_cd.h | 91 + src/i_movie.h | 52 + src/i_video.h | 55 + src/info.cpp | 433 + src/info.h | 423 + src/infodefaults.cpp | 373 + src/infomacros.h | 326 + src/lists.h | 143 + src/lumpconfigfile.cpp | 86 + src/lumpconfigfile.h | 62 + src/m_alloc.cpp | 70 + src/m_alloc.h | 58 + src/m_argv.cpp | 198 + src/m_argv.h | 76 + src/m_bbox.cpp | 58 + src/m_bbox.h | 59 + src/m_cheat.cpp | 649 ++ src/m_cheat.h | 36 + src/m_crc32.h | 52 + src/m_fixed.cpp | 66 + src/m_fixed.h | 137 + src/m_menu.cpp | 3196 ++++++ src/m_menu.h | 227 + src/m_misc.cpp | 617 ++ src/m_misc.h | 48 + src/m_options.cpp | 2971 ++++++ src/m_png.cpp | 916 ++ src/m_png.h | 108 + src/m_random.cpp | 253 + src/m_random.h | 102 + src/m_swap.h | 127 + src/misc.nas | 537 ++ src/mscinlines.h | 360 + src/mus2midi.cpp | 274 + src/mus2midi.h | 78 + src/name.cpp | 53 + src/name.h | 122 + src/nodebuild.cpp | 1098 +++ src/nodebuild.h | 187 + src/nodebuild_events.cpp | 427 + src/nodebuild_extract.cpp | 266 + src/nodebuild_gl.cpp | 398 + src/nodebuild_utility.cpp | 536 ++ src/oplsynth/deftypes.h | 28 + src/oplsynth/fmopl.cpp | 1877 ++++ src/oplsynth/fmopl.h | 47 + src/oplsynth/mlkernel.cpp | 123 + src/oplsynth/mlopl.cpp | 425 + src/oplsynth/mlopl_io.cpp | 308 + src/oplsynth/muslib.h | 190 + src/oplsynth/opl_mus_player.cpp | 605 ++ src/oplsynth/opl_mus_player.h | 40 + src/p_acs.cpp | 4763 +++++++++ src/p_acs.h | 650 ++ src/p_buildmap.cpp | 804 ++ src/p_ceiling.cpp | 509 + src/p_conversation.cpp | 1059 ++ src/p_conversation.h | 65 + src/p_doors.cpp | 851 ++ src/p_effect.cpp | 567 ++ src/p_effect.h | 64 + src/p_enemy.cpp | 2357 +++++ src/p_enemy.h | 63 + src/p_floor.cpp | 1201 +++ src/p_interaction.cpp | 1373 +++ src/p_lights.cpp | 718 ++ src/p_lnspec.cpp | 2791 ++++++ src/p_lnspec.h | 429 + src/p_local.h | 491 + src/p_map.cpp | 4588 +++++++++ src/p_maputl.cpp | 1250 +++ src/p_mobj.cpp | 4512 +++++++++ src/p_pillar.cpp | 203 + src/p_plats.cpp | 418 + src/p_pspr.cpp | 819 ++ src/p_pspr.h | 108 + src/p_saveg.cpp | 297 + src/p_saveg.h | 51 + src/p_sectors.cpp | 658 ++ src/p_setup.cpp | 3325 +++++++ src/p_setup.h | 38 + src/p_sight.cpp | 566 ++ src/p_spec.cpp | 2376 +++++ src/p_spec.h | 927 ++ src/p_switch.cpp | 678 ++ src/p_teleport.cpp | 753 ++ src/p_terrain.cpp | 718 ++ src/p_terrain.h | 82 + src/p_things.cpp | 372 + src/p_tick.cpp | 92 + src/p_tick.h | 35 + src/p_trace.cpp | 397 + src/p_trace.h | 84 + src/p_user.cpp | 1474 +++ src/p_writemap.cpp | 263 + src/p_xlat.cpp | 484 + src/po_man.cpp | 1598 +++ src/r_bsp.cpp | 1180 +++ src/r_bsp.h | 82 + src/r_data.cpp | 3299 +++++++ src/r_data.h | 306 + src/r_defs.h | 847 ++ src/r_draw.cpp | 1969 ++++ src/r_draw.h | 270 + src/r_drawt.cpp | 1128 +++ src/r_local.h | 46 + src/r_main.cpp | 2012 ++++ src/r_main.h | 255 + src/r_plane.cpp | 1670 ++++ src/r_plane.h | 115 + src/r_polymost.cpp | 1592 +++ src/r_polymost.h | 57 + src/r_segs.cpp | 2150 +++++ src/r_segs.h | 49 + src/r_sky.cpp | 123 + src/r_sky.h | 42 + src/r_state.h | 116 + src/r_things.cpp | 2247 +++++ src/r_things.h | 106 + src/s_advsound.cpp | 1588 +++ src/s_environment.cpp | 577 ++ src/s_playlist.cpp | 196 + src/s_playlist.h | 62 + src/s_sndseq.cpp | 942 ++ src/s_sndseq.h | 101 + src/s_sound.cpp | 1862 ++++ src/s_sound.h | 273 + src/sc_man.cpp | 719 ++ src/sc_man.h | 38 + src/sdl/crashcatcher.c | 394 + src/sdl/dikeys.h | 155 + src/sdl/hardware.cpp | 234 + src/sdl/hardware.h | 93 + src/sdl/i_cd.cpp | 154 + src/sdl/i_input.cpp | 434 + src/sdl/i_input.h | 19 + src/sdl/i_main.cpp | 198 + src/sdl/i_movie.cpp | 7 + src/sdl/i_net.cpp | 838 ++ src/sdl/i_net.h | 30 + src/sdl/i_system.cpp | 445 + src/sdl/i_system.h | 229 + src/sdl/i_video.h | 69 + src/sdl/sdlvideo.cpp | 505 + src/sdl/sdlvideo.h | 23 + src/skins.cpp | 125 + src/skins.h | 4 + src/sound/altsound.cpp | 1370 +++ src/sound/altsound.h | 100 + src/sound/altsoundmixer.cpp | 151 + src/sound/fmodsound.cpp | 1251 +++ src/sound/fmodsound.h | 78 + src/sound/i_music.cpp | 441 + src/sound/i_music.h | 76 + src/sound/i_musicinterns.h | 350 + src/sound/i_sound.cpp | 341 + src/sound/i_sound.h | 129 + src/sound/music_cd.cpp | 115 + src/sound/music_flac.cpp | 312 + src/sound/music_midi_midiout.cpp | 737 ++ src/sound/music_midi_stream.cpp | 201 + src/sound/music_midi_timidity.cpp | 693 ++ src/sound/music_mod.cpp | 91 + src/sound/music_mus_midiout.cpp | 387 + src/sound/music_mus_opl.cpp | 85 + src/sound/music_spc.cpp | 263 + src/sound/music_stream.cpp | 82 + src/sound/sample_flac.cpp | 300 + src/sound/sample_flac.h | 32 + src/st_stuff.cpp | 421 + src/st_stuff.h | 39 + src/statnums.h | 56 + src/stats.cpp | 146 + src/stats.h | 118 + src/stringtable.cpp | 403 + src/stringtable.h | 77 + src/tables.cpp | 42 + src/tables.h | 123 + src/tagitem.h | 0 src/tarray.h | 294 + src/tempfiles.cpp | 57 + src/tempfiles.h | 59 + src/templates.h | 202 + src/thingdef.cpp | 3370 +++++++ src/thingdef_codeptr.cpp | 1450 +++ src/thingdef_specials.gperf | 177 + src/thingdef_specials.h | 626 ++ src/tmap.nas | 1500 +++ src/tmap2.nas | 621 ++ src/tmap3.nas | 327 + src/v_collection.cpp | 90 + src/v_collection.h | 57 + src/v_draw.cpp | 665 ++ src/v_font.cpp | 1342 +++ src/v_font.h | 145 + src/v_palette.cpp | 766 ++ src/v_palette.h | 114 + src/v_pfx.cpp | 566 ++ src/v_pfx.h | 86 + src/v_text.cpp | 422 + src/v_text.h | 71 + src/v_video.cpp | 973 ++ src/v_video.h | 310 + src/vectors.cpp | 253 + src/vectors.h | 43 + src/version.h | 55 + src/w_wad.cpp | 1462 +++ src/w_wad.h | 199 + src/weightedlist.h | 148 + src/wi_stuff.cpp | 2075 ++++ src/wi_stuff.h | 84 + src/win32/afxres.h | 808 ++ src/win32/boing1.ico | Bin 0 -> 766 bytes src/win32/boing2.ico | Bin 0 -> 766 bytes src/win32/boing3.ico | Bin 0 -> 766 bytes src/win32/boing4.ico | Bin 0 -> 766 bytes src/win32/boing5.ico | Bin 0 -> 766 bytes src/win32/boing6.ico | Bin 0 -> 766 bytes src/win32/boing7.ico | Bin 0 -> 766 bytes src/win32/boing8.ico | Bin 0 -> 766 bytes src/win32/cursor1.cur | Bin 0 -> 326 bytes src/win32/deadguy.bmp | Bin 0 -> 2626 bytes src/win32/eaxedit.cpp | 1370 +++ src/win32/gccseh.h | 31 + src/win32/hardware.cpp | 246 + src/win32/hardware.h | 93 + src/win32/helperthread.cpp | 295 + src/win32/helperthread.h | 85 + src/win32/i_cd.cpp | 789 ++ src/win32/i_crash.cpp | 2827 ++++++ src/win32/i_input.cpp | 2004 ++++ src/win32/i_input.h | 57 + src/win32/i_main.cpp | 674 ++ src/win32/i_movie.cpp | 523 + src/win32/i_net.cpp | 838 ++ src/win32/i_net.h | 30 + src/win32/i_system.cpp | 688 ++ src/win32/i_system.h | 238 + src/win32/icon1.ico | Bin 0 -> 8478 bytes src/win32/resource.h | 157 + src/win32/win32iface.h | 184 + src/win32/win32video.cpp | 1721 ++++ src/win32/winres.h | 50 + src/win32/zdoom.RES | Bin 0 -> 13600 bytes src/win32/zdoom.exe.manifest | 23 + src/win32/zdoom.rc | 543 ++ src/zstrformat.cpp | 606 ++ src/zstring.cpp | 849 ++ src/zstring.h | 250 + src/zstringpool.cpp | 435 + strifehelp.acs | 411 + thingdef_specials.gperf | 171 + tools/dehsupp/Makefile.mgw | 27 + tools/dehsupp/dehsupp.vcproj | 130 + tools/dehsupp/parse.tab.c | 2182 +++++ tools/dehsupp/parse.y | 1029 ++ tools/lemon/Makefile.mgw | 23 + tools/lemon/lemon.c | 4587 +++++++++ tools/lemon/lemon.html | 861 ++ tools/lemon/lemon.vcproj | 168 + tools/lemon/lempar.c | 687 ++ tools/makewad/Makefile.mgw | 23 + tools/makewad/makewad.c | 274 + tools/makewad/makewad.vcproj | 120 + tools/re2c/Makefile.am | 47 + tools/re2c/Makefile.in | 472 + tools/re2c/Makefile.mgw | 31 + tools/re2c/README | 165 + tools/re2c/README.in | 165 + tools/re2c/aclocal.m4 | 157 + tools/re2c/actions.cc | 568 ++ tools/re2c/basics.h | 63 + tools/re2c/code.cc | 964 ++ tools/re2c/config.h.in | 118 + tools/re2c/configure | 7415 ++++++++++++++ tools/re2c/configure.in | 59 + tools/re2c/configwin.h | 118 + tools/re2c/dfa.cc | 226 + tools/re2c/dfa.h | 174 + tools/re2c/doc/loplas.ps | Bin 0 -> 190090 bytes tools/re2c/doc/sample.bib | 48 + tools/re2c/examples/basemmap.c | 26 + tools/re2c/examples/c.re | 272 + tools/re2c/examples/cmmap.re | 267 + tools/re2c/examples/cnokw.re | 239 + tools/re2c/examples/cunroll.re | 258 + tools/re2c/examples/modula.re | 202 + tools/re2c/examples/rexx/README | 1 + tools/re2c/examples/rexx/rexx.l | 319 + tools/re2c/examples/rexx/scanio.c | 41 + tools/re2c/examples/sample.re | 7 + tools/re2c/examples/simple.re | 13 + tools/re2c/globals.h | 18 + tools/re2c/ins.h | 41 + tools/re2c/install-sh | 251 + tools/re2c/main.cc | 149 + tools/re2c/makerpm.in | 45 + tools/re2c/mbo_getopt.cc | 142 + tools/re2c/mbo_getopt.h | 16 + tools/re2c/missing | 198 + tools/re2c/mkinstalldirs | 40 + tools/re2c/parser.cc | 1433 +++ tools/re2c/parser.h | 23 + tools/re2c/parser.y | 211 + tools/re2c/re.h | 206 + tools/re2c/re2c.1 | 601 ++ tools/re2c/re2c.1.in | 601 ++ tools/re2c/re2c.spec.in | 51 + tools/re2c/re2c.vcproj | 199 + tools/re2c/scanner.cc | 639 ++ tools/re2c/scanner.h | 34 + tools/re2c/scanner.re | 201 + tools/re2c/stamp-h.in | 0 tools/re2c/substr.cc | 37 + tools/re2c/substr.h | 46 + tools/re2c/test.c | 162 + tools/re2c/test.re | 6 + tools/re2c/token.h | 19 + tools/re2c/translate.cc | 62 + tools/re2c/y.tab.h | 69 + tools/xlatcc/Makefile.mgw | 30 + tools/xlatcc/gen.c | 272 + tools/xlatcc/xlat-parse.tab.c | 2169 +++++ tools/xlatcc/xlat-parse.y | 850 ++ tools/xlatcc/xlat.h | 59 + tools/xlatcc/xlatcc.vcproj | 149 + wadsrc/Makefile | 31 + wadsrc/Makefile.mgw | 22 + wadsrc/Makefile2 | 14 + wadsrc/animated.lmp | Bin 0 -> 1450 bytes wadsrc/animdefs.txt | 291 + wadsrc/artibox.png | Bin 0 -> 770 bytes wadsrc/badpatch.lmp | Bin 0 -> 546 bytes wadsrc/clerface.lmp | Bin 0 -> 260 bytes wadsrc/confont.lmp | Bin 0 -> 10239 bytes wadsrc/dbigfont.lmp | Bin 0 -> 6671 bytes wadsrc/decals/bal7scr1.png | Bin 0 -> 647 bytes wadsrc/decals/bal7scr2.png | Bin 0 -> 665 bytes wadsrc/decals/bfglite1.png | Bin 0 -> 1112 bytes wadsrc/decals/bfglite2.png | Bin 0 -> 1020 bytes wadsrc/decals/bfgscrc1.png | Bin 0 -> 2264 bytes wadsrc/decals/bfgscrc2.png | Bin 0 -> 2681 bytes wadsrc/decals/blast1.png | Bin 0 -> 2227 bytes wadsrc/decals/bsmear1.png | Bin 0 -> 1008 bytes wadsrc/decals/bsmear2.png | Bin 0 -> 1067 bytes wadsrc/decals/bsplat1.png | Bin 0 -> 630 bytes wadsrc/decals/bsplat2.png | Bin 0 -> 821 bytes wadsrc/decals/bsplat3.png | Bin 0 -> 365 bytes wadsrc/decals/bsplat4.png | Bin 0 -> 378 bytes wadsrc/decals/bsplat5.png | Bin 0 -> 406 bytes wadsrc/decals/bsplat6.png | Bin 0 -> 616 bytes wadsrc/decals/bsplat7.png | Bin 0 -> 243 bytes wadsrc/decals/cbalscr1.png | Bin 0 -> 647 bytes wadsrc/decals/cbalscr2.png | Bin 0 -> 665 bytes wadsrc/decals/cbowmark.png | Bin 0 -> 1689 bytes wadsrc/decals/chip1.png | Bin 0 -> 150 bytes wadsrc/decals/chip2.png | Bin 0 -> 137 bytes wadsrc/decals/chip3.png | Bin 0 -> 140 bytes wadsrc/decals/chip4.png | Bin 0 -> 133 bytes wadsrc/decals/chip5.png | Bin 0 -> 142 bytes wadsrc/decals/decaldef.txt | 1055 ++ wadsrc/decals/plasma1.png | Bin 0 -> 1217 bytes wadsrc/decals/plasma2.png | Bin 0 -> 1446 bytes wadsrc/decals/scorch1.png | Bin 0 -> 3608 bytes wadsrc/dehsupp.lmp | Bin 0 -> 9571 bytes wadsrc/dehsupp.txt | 809 ++ wadsrc/doomx.lmp | Bin 0 -> 2849 bytes wadsrc/dsempty.lmp | Bin 0 -> 12 bytes wadsrc/fiteface.lmp | Bin 0 -> 296 bytes wadsrc/fonta164.lmp | Bin 0 -> 168 bytes wadsrc/fonta165.lmp | Bin 0 -> 165 bytes wadsrc/fonta182.lmp | Bin 0 -> 171 bytes wadsrc/fonta188.lmp | Bin 0 -> 173 bytes wadsrc/fonta191.lmp | Bin 0 -> 163 bytes wadsrc/fonta60.lmp | Bin 0 -> 92 bytes wadsrc/fonta61.lmp | Bin 0 -> 92 bytes wadsrc/fonta62.lmp | Bin 0 -> 28 bytes wadsrc/fonta63.lmp | Bin 0 -> 92 bytes wadsrc/foo | Bin 0 -> 329 bytes wadsrc/hamoback.png | Bin 0 -> 832 bytes wadsrc/hereticx.lmp | Bin 0 -> 2849 bytes wadsrc/icebreak.flac | Bin 0 -> 13169 bytes wadsrc/iceca0.png | Bin 0 -> 217 bytes wadsrc/icecb0.png | Bin 0 -> 197 bytes wadsrc/icecc0.png | Bin 0 -> 165 bytes wadsrc/icecd0.png | Bin 0 -> 123 bytes wadsrc/icedeath.flac | Bin 0 -> 9652 bytes wadsrc/invgeml1.lmp | Bin 0 -> 165 bytes wadsrc/invgeml2.lmp | Bin 0 -> 156 bytes wadsrc/invgemr1.lmp | Bin 0 -> 172 bytes wadsrc/invgemr2.lmp | Bin 0 -> 168 bytes wadsrc/languages/english-us.txt | 991 ++ wadsrc/languages/french.txt | 376 + wadsrc/languages/italian.txt | 886 ++ wadsrc/mageface.lmp | Bin 0 -> 330 bytes wadsrc/mapinfo/doom1.txt | 437 + wadsrc/mapinfo/doom2.txt | 359 + wadsrc/mapinfo/heretic.txt | 398 + wadsrc/mapinfo/hexen.txt | 34 + wadsrc/mapinfo/plutonia.txt | 360 + wadsrc/mapinfo/strife.txt | 236 + wadsrc/mapinfo/tnt.txt | 360 + wadsrc/noflat.png | Bin 0 -> 103 bytes wadsrc/quake.flac | Bin 0 -> 6453 bytes wadsrc/railgunfire.flac | Bin 0 -> 15431 bytes wadsrc/sbigfont.lmp | Bin 0 -> 7546 bytes wadsrc/secret.flac | Bin 0 -> 14333 bytes wadsrc/selectbo.png | Bin 0 -> 183 bytes wadsrc/sndeax.txt | 1861 ++++ wadsrc/sndinfo.txt | 1252 +++ wadsrc/sndseq.txt | 131 + wadsrc/spaldoom.lmp | Bin 0 -> 768 bytes wadsrc/spalhtic.lmp | Bin 0 -> 768 bytes wadsrc/spark1.flac | Bin 0 -> 1555 bytes wadsrc/spark2.flac | Bin 0 -> 5574 bytes wadsrc/spark3.flac | Bin 0 -> 2128 bytes wadsrc/stcfn196.lmp | Bin 0 -> 142 bytes wadsrc/stcfn197.lmp | Bin 0 -> 127 bytes wadsrc/stcfn214.lmp | Bin 0 -> 135 bytes wadsrc/stcfn220.lmp | Bin 0 -> 130 bytes wadsrc/stcfn223.lmp | Bin 0 -> 136 bytes wadsrc/stfbany.lmp | Bin 0 -> 1408 bytes wadsrc/stkeys6.lmp | Bin 0 -> 104 bytes wadsrc/stkeys7.lmp | Bin 0 -> 104 bytes wadsrc/stkeys8.lmp | Bin 0 -> 104 bytes wadsrc/stpbany.lmp | Bin 0 -> 1478 bytes wadsrc/strfhelp.o | Bin 0 -> 3184 bytes wadsrc/strifex.lmp | Bin 0 -> 1649 bytes wadsrc/terrain.txt | 145 + wadsrc/tlgl.png | Bin 0 -> 159 bytes wadsrc/tnt1a0.png | Bin 0 -> 13 bytes wadsrc/unkna0.png | Bin 0 -> 223 bytes wadsrc/wadmake | 122 + wadsrc/wadsrc.vcproj | 227 + wadsrc/x11r6rgb.txt | 757 ++ wadsrc/xhairb1.imgz | Bin 0 -> 90 bytes wadsrc/xhairb2.png | Bin 0 -> 136 bytes wadsrc/xhairb3.imgz | Bin 0 -> 116 bytes wadsrc/xhairb4.imgz | Bin 0 -> 82 bytes wadsrc/xhairb5.imgz | Bin 0 -> 50 bytes wadsrc/xhairb6.imgz | Bin 0 -> 72 bytes wadsrc/xhairb7.imgz | Bin 0 -> 33 bytes wadsrc/xhairs1.imgz | Bin 0 -> 49 bytes wadsrc/xhairs2.imgz | Bin 0 -> 72 bytes wadsrc/xhairs3.imgz | Bin 0 -> 49 bytes wadsrc/xhairs4.imgz | Bin 0 -> 49 bytes wadsrc/xhairs5.imgz | Bin 0 -> 33 bytes wadsrc/xhairs6.imgz | Bin 0 -> 48 bytes wadsrc/xhairs7.imgz | Bin 0 -> 25 bytes wadsrc/xlat/defines.i | 112 + wadsrc/xlat/doom.x | Bin 0 -> 2849 bytes wadsrc/xlat/doomxlat.txt | 537 ++ wadsrc/xlat/heretic.x | Bin 0 -> 2849 bytes wadsrc/xlat/hereticxlat.txt | 11 + wadsrc/xlat/specials.i | 190 + wadsrc/xlat/strife.x | Bin 0 -> 1649 bytes wadsrc/xlat/strifexlat.txt | 325 + wadsrc/zdoom.lst | 176 + zdoom.sln | 90 + zdoom.vcproj | 4666 +++++++++ zlib/ChangeLog | 855 ++ zlib/FAQ | 339 + zlib/INDEX | 51 + zlib/Makefile | 154 + zlib/Makefile.in | 154 + zlib/Makefile.mgw | 84 + zlib/README | 125 + zlib/adler32.c | 149 + zlib/algorithm.txt | 209 + zlib/compress.c | 79 + zlib/configure | 459 + zlib/crc32.c | 423 + zlib/crc32.h | 441 + zlib/deflate.c | 1736 ++++ zlib/deflate.h | 331 + zlib/example.c | 565 ++ zlib/gzio.c | 1026 ++ zlib/infback.c | 623 ++ zlib/inffast.c | 318 + zlib/inffast.h | 11 + zlib/inffixed.h | 94 + zlib/inflate.c | 1368 +++ zlib/inflate.h | 115 + zlib/inftrees.c | 329 + zlib/inftrees.h | 55 + zlib/minigzip.c | 322 + zlib/trees.c | 1219 +++ zlib/trees.h | 128 + zlib/uncompr.c | 61 + zlib/zconf.h | 332 + zlib/zconf.in.h | 332 + zlib/zlib.3 | 159 + zlib/zlib.h | 1357 +++ zlib/zlib.vcproj | 197 + zlib/zutil.c | 318 + zlib/zutil.h | 269 + 821 files changed, 355953 insertions(+) create mode 100644 FLAC/FLAC++/decoder.h create mode 100644 FLAC/FLAC++/export.h create mode 100644 FLAC/FLAC.dsp create mode 100644 FLAC/FLAC.vcproj create mode 100644 FLAC/FLAC/assert.h create mode 100644 FLAC/FLAC/export.h create mode 100644 FLAC/FLAC/format.h create mode 100644 FLAC/FLAC/ordinals.h create mode 100644 FLAC/FLAC/stream_decoder.h create mode 100644 FLAC/Makefile.mgw create mode 100644 FLAC/ReadMe.txt create mode 100644 FLAC/bitbuffer.c create mode 100644 FLAC/bitmath.c create mode 100644 FLAC/cpu.c create mode 100644 FLAC/crc.c create mode 100644 FLAC/fixed.c create mode 100644 FLAC/format.c create mode 100644 FLAC/ia32/cpu_asm.nasm create mode 100644 FLAC/ia32/fixed_asm.nasm create mode 100644 FLAC/ia32/lpc_asm.nasm create mode 100644 FLAC/ia32/nasm.h create mode 100644 FLAC/lpc.c create mode 100644 FLAC/memory.c create mode 100644 FLAC/private/bitbuffer.h create mode 100644 FLAC/private/bitmath.h create mode 100644 FLAC/private/cpu.h create mode 100644 FLAC/private/crc.h create mode 100644 FLAC/private/fixed.h create mode 100644 FLAC/private/format.h create mode 100644 FLAC/private/lpc.h create mode 100644 FLAC/private/memory.h create mode 100644 FLAC/protected/stream_decoder.h create mode 100644 FLAC/stream_decoder.c create mode 100644 FLAC/stream_decoder_pp.cpp create mode 100644 Makefile create mode 100644 Makefile.am create mode 100644 Makefile.mgw create mode 100644 Makefile.mingw create mode 100644 bootstrap create mode 100644 cbuild.c create mode 100644 ccdv-win32.c create mode 100644 configure.ac create mode 100644 default.cbd create mode 100644 docs/BUILDLIC.TXT create mode 100644 docs/README.Carmack create mode 100644 docs/README.asm create mode 100644 docs/README.gl create mode 100644 docs/classes.txt create mode 100644 docs/colors.txt create mode 100644 docs/commands.txt create mode 100644 docs/console.css create mode 100644 docs/console.html create mode 100644 docs/console.txt create mode 100644 docs/console2.html create mode 100644 docs/doomlic.txt create mode 100644 docs/foo.txt create mode 100644 docs/history.txt create mode 100644 docs/notes.txt create mode 100644 docs/rh-log.txt create mode 100644 docs/thingdef_doc.txt create mode 100644 docs/zdoom.txt create mode 100644 src/Makefile.am create mode 100644 src/a.nas create mode 100644 src/actor.h create mode 100644 src/am_map.cpp create mode 100644 src/am_map.h create mode 100644 src/announcer.h create mode 100644 src/autosegs.h create mode 100644 src/autostart.cpp create mode 100644 src/autozend.cpp create mode 100644 src/b_bot.cpp create mode 100644 src/b_bot.h create mode 100644 src/b_func.cpp create mode 100644 src/b_game.cpp create mode 100644 src/b_move.cpp create mode 100644 src/b_think.cpp create mode 100644 src/basicinlines.h create mode 100644 src/bbannouncer.cpp create mode 100644 src/blocks.nas create mode 100644 src/c_bind.cpp create mode 100644 src/c_bind.h create mode 100644 src/c_cmds.cpp create mode 100644 src/c_console.cpp create mode 100644 src/c_console.h create mode 100644 src/c_cvars.cpp create mode 100644 src/c_cvars.h create mode 100644 src/c_dispatch.cpp create mode 100644 src/c_dispatch.h create mode 100644 src/c_expr.cpp create mode 100644 src/cmdlib.cpp create mode 100644 src/cmdlib.h create mode 100644 src/colormatcher.cpp create mode 100644 src/colormatcher.h create mode 100644 src/configfile.cpp create mode 100644 src/configfile.h create mode 100644 src/ct_chat.cpp create mode 100644 src/d_dehacked.cpp create mode 100644 src/d_dehacked.h create mode 100644 src/d_dehackedactions.h create mode 100644 src/d_event.h create mode 100644 src/d_gui.h create mode 100644 src/d_main.cpp create mode 100644 src/d_main.h create mode 100644 src/d_net.cpp create mode 100644 src/d_net.h create mode 100644 src/d_netinf.h create mode 100644 src/d_netinfo.cpp create mode 100644 src/d_player.h create mode 100644 src/d_protocol.cpp create mode 100644 src/d_protocol.h create mode 100644 src/d_textur.h create mode 100644 src/d_ticcmd.h create mode 100644 src/decallib.cpp create mode 100644 src/decallib.h create mode 100644 src/decorations.cpp create mode 100644 src/dobject.cpp create mode 100644 src/dobject.err create mode 100644 src/dobject.h create mode 100644 src/doomdata.h create mode 100644 src/doomdef.cpp create mode 100644 src/doomdef.h create mode 100644 src/doomerrors.h create mode 100644 src/doomstat.cpp create mode 100644 src/doomstat.h create mode 100644 src/doomtype.h create mode 100644 src/dscript.h create mode 100644 src/dsectoreffect.cpp create mode 100644 src/dsectoreffect.h create mode 100644 src/dthinker.cpp create mode 100644 src/dthinker.h create mode 100644 src/empty.cpp create mode 100644 src/errors.h create mode 100644 src/f_finale.cpp create mode 100644 src/f_finale.h create mode 100644 src/f_wipe.cpp create mode 100644 src/f_wipe.h create mode 100644 src/farchive.cpp create mode 100644 src/farchive.h create mode 100644 src/files.cpp create mode 100644 src/files.h create mode 100644 src/g_doom/a_arachnotron.cpp create mode 100644 src/g_doom/a_archvile.cpp create mode 100644 src/g_doom/a_bossbrain.cpp create mode 100644 src/g_doom/a_bruiser.cpp create mode 100644 src/g_doom/a_cacodemon.cpp create mode 100644 src/g_doom/a_cyberdemon.cpp create mode 100644 src/g_doom/a_demon.cpp create mode 100644 src/g_doom/a_doomarmor.cpp create mode 100644 src/g_doom/a_doomartifacts.cpp create mode 100644 src/g_doom/a_doomdecorations.cpp create mode 100644 src/g_doom/a_doomglobal.h create mode 100644 src/g_doom/a_doomhealth.cpp create mode 100644 src/g_doom/a_doomimp.cpp create mode 100644 src/g_doom/a_doomkeys.cpp create mode 100644 src/g_doom/a_doommisc.cpp create mode 100644 src/g_doom/a_doomplayer.cpp create mode 100644 src/g_doom/a_doomweaps.cpp create mode 100644 src/g_doom/a_fatso.cpp create mode 100644 src/g_doom/a_keen.cpp create mode 100644 src/g_doom/a_lostsoul.cpp create mode 100644 src/g_doom/a_painelemental.cpp create mode 100644 src/g_doom/a_possessed.cpp create mode 100644 src/g_doom/a_revenant.cpp create mode 100644 src/g_doom/a_scriptedmarine.cpp create mode 100644 src/g_doom/a_spidermaster.cpp create mode 100644 src/g_doom/doom_sbar.cpp create mode 100644 src/g_game.cpp create mode 100644 src/g_game.h create mode 100644 src/g_heretic/a_beast.cpp create mode 100644 src/g_heretic/a_chicken.cpp create mode 100644 src/g_heretic/a_clink.cpp create mode 100644 src/g_heretic/a_dsparil.cpp create mode 100644 src/g_heretic/a_hereticambience.cpp create mode 100644 src/g_heretic/a_hereticarmor.cpp create mode 100644 src/g_heretic/a_hereticartifacts.cpp create mode 100644 src/g_heretic/a_hereticdecorations.cpp create mode 100644 src/g_heretic/a_hereticglobal.h create mode 100644 src/g_heretic/a_hereticimp.cpp create mode 100644 src/g_heretic/a_hereticimp.cpp.bak create mode 100644 src/g_heretic/a_heretickeys.cpp create mode 100644 src/g_heretic/a_hereticmisc.cpp create mode 100644 src/g_heretic/a_hereticplayer.cpp create mode 100644 src/g_heretic/a_hereticweaps.cpp create mode 100644 src/g_heretic/a_ironlich.cpp create mode 100644 src/g_heretic/a_knight.cpp create mode 100644 src/g_heretic/a_mummy.cpp create mode 100644 src/g_heretic/a_snake.cpp create mode 100644 src/g_heretic/a_wizard.cpp create mode 100644 src/g_heretic/heretic_sbar.cpp create mode 100644 src/g_hexen/a_bats.cpp create mode 100644 src/g_hexen/a_bishop.cpp create mode 100644 src/g_hexen/a_blastradius.cpp create mode 100644 src/g_hexen/a_boostarmor.cpp create mode 100644 src/g_hexen/a_centaur.cpp create mode 100644 src/g_hexen/a_clericboss.cpp create mode 100644 src/g_hexen/a_clericflame.cpp create mode 100644 src/g_hexen/a_clericholy.cpp create mode 100644 src/g_hexen/a_clericmace.cpp create mode 100644 src/g_hexen/a_clericplayer.cpp create mode 100644 src/g_hexen/a_clericstaff.cpp create mode 100644 src/g_hexen/a_demons.cpp create mode 100644 src/g_hexen/a_dragon.cpp create mode 100644 src/g_hexen/a_ettin.cpp create mode 100644 src/g_hexen/a_fighteraxe.cpp create mode 100644 src/g_hexen/a_fighterboss.cpp create mode 100644 src/g_hexen/a_fighterhammer.cpp create mode 100644 src/g_hexen/a_fighterplayer.cpp create mode 100644 src/g_hexen/a_fighterquietus.cpp create mode 100644 src/g_hexen/a_firedemon.cpp create mode 100644 src/g_hexen/a_flame.cpp create mode 100644 src/g_hexen/a_flechette.cpp create mode 100644 src/g_hexen/a_fog.cpp create mode 100644 src/g_hexen/a_healingradius.cpp create mode 100644 src/g_hexen/a_heresiarch.cpp create mode 100644 src/g_hexen/a_hexenarmor.cpp create mode 100644 src/g_hexen/a_hexendecorations.cpp create mode 100644 src/g_hexen/a_hexenglobal.h create mode 100644 src/g_hexen/a_hexenkeys.cpp create mode 100644 src/g_hexen/a_hexenspecialdecs.cpp create mode 100644 src/g_hexen/a_iceguy.cpp create mode 100644 src/g_hexen/a_korax.cpp create mode 100644 src/g_hexen/a_mageboss.cpp create mode 100644 src/g_hexen/a_magecone.cpp create mode 100644 src/g_hexen/a_magelightning.cpp create mode 100644 src/g_hexen/a_mageplayer.cpp create mode 100644 src/g_hexen/a_magestaff.cpp create mode 100644 src/g_hexen/a_magewand.cpp create mode 100644 src/g_hexen/a_mana.cpp create mode 100644 src/g_hexen/a_pig.cpp create mode 100644 src/g_hexen/a_puzzleitems.cpp create mode 100644 src/g_hexen/a_scriptprojectiles.cpp create mode 100644 src/g_hexen/a_serpent.cpp create mode 100644 src/g_hexen/a_speedboots.cpp create mode 100644 src/g_hexen/a_spike.cpp create mode 100644 src/g_hexen/a_summon.cpp create mode 100644 src/g_hexen/a_teleportother.cpp create mode 100644 src/g_hexen/a_weaponpieces.cpp create mode 100644 src/g_hexen/a_wraith.cpp create mode 100644 src/g_hexen/hexen_sbar.cpp create mode 100644 src/g_level.cpp create mode 100644 src/g_level.h create mode 100644 src/g_raven/a_artiegg.cpp create mode 100644 src/g_raven/a_artitele.cpp create mode 100644 src/g_raven/a_minotaur.cpp create mode 100644 src/g_raven/a_ravenambient.cpp create mode 100644 src/g_raven/a_ravenartifacts.cpp create mode 100644 src/g_raven/a_ravenhealth.cpp create mode 100644 src/g_raven/ravenshared.h create mode 100644 src/g_shared/a_action.cpp create mode 100644 src/g_shared/a_action.h create mode 100644 src/g_shared/a_artifacts.cpp create mode 100644 src/g_shared/a_artifacts.h create mode 100644 src/g_shared/a_bridge.cpp create mode 100644 src/g_shared/a_camera.cpp create mode 100644 src/g_shared/a_debris.cpp create mode 100644 src/g_shared/a_decals.cpp create mode 100644 src/g_shared/a_flashfader.cpp create mode 100644 src/g_shared/a_fountain.cpp create mode 100644 src/g_shared/a_hatetarget.cpp create mode 100644 src/g_shared/a_keys.cpp create mode 100644 src/g_shared/a_keys.h create mode 100644 src/g_shared/a_lightning.cpp create mode 100644 src/g_shared/a_lightning.h create mode 100644 src/g_shared/a_movingcamera.cpp create mode 100644 src/g_shared/a_pickups.cpp create mode 100644 src/g_shared/a_pickups.h create mode 100644 src/g_shared/a_pickups.h.bak create mode 100644 src/g_shared/a_quake.cpp create mode 100644 src/g_shared/a_secrettrigger.cpp create mode 100644 src/g_shared/a_sectoraction.cpp create mode 100644 src/g_shared/a_sharedglobal.h create mode 100644 src/g_shared/a_sharedmisc.cpp create mode 100644 src/g_shared/a_skies.cpp create mode 100644 src/g_shared/a_soundenvironment.cpp create mode 100644 src/g_shared/a_spark.cpp create mode 100644 src/g_shared/a_splashes.cpp create mode 100644 src/g_shared/a_waterzone.cpp create mode 100644 src/g_shared/a_weaponpiece.cpp create mode 100644 src/g_shared/a_weaponpiece.h create mode 100644 src/g_shared/a_weapons.cpp create mode 100644 src/g_shared/hudmessages.cpp create mode 100644 src/g_shared/sbar.h create mode 100644 src/g_shared/shared_sbar.cpp create mode 100644 src/g_strife/a_acolyte.cpp create mode 100644 src/g_strife/a_alienspectres.cpp create mode 100644 src/g_strife/a_beggars.cpp create mode 100644 src/g_strife/a_coin.cpp create mode 100644 src/g_strife/a_crusader.cpp create mode 100644 src/g_strife/a_entityboss.cpp create mode 100644 src/g_strife/a_inquisitor.cpp create mode 100644 src/g_strife/a_loremaster.cpp create mode 100644 src/g_strife/a_macil.cpp create mode 100644 src/g_strife/a_merchants.cpp create mode 100644 src/g_strife/a_oracle.cpp create mode 100644 src/g_strife/a_peasant.cpp create mode 100644 src/g_strife/a_programmer.cpp create mode 100644 src/g_strife/a_questitems.cpp create mode 100644 src/g_strife/a_ratbuddy.cpp create mode 100644 src/g_strife/a_reaver.cpp create mode 100644 src/g_strife/a_rebels.cpp create mode 100644 src/g_strife/a_sentinel.cpp create mode 100644 src/g_strife/a_spectral.cpp create mode 100644 src/g_strife/a_stalker.cpp create mode 100644 src/g_strife/a_strifeammo.cpp create mode 100644 src/g_strife/a_strifearmor.cpp create mode 100644 src/g_strife/a_strifebishop.cpp create mode 100644 src/g_strife/a_strifeglobal.h create mode 100644 src/g_strife/a_strifeitems.cpp create mode 100644 src/g_strife/a_strifekeys.cpp create mode 100644 src/g_strife/a_strifeplayer.cpp create mode 100644 src/g_strife/a_strifestuff.cpp create mode 100644 src/g_strife/a_strifeweapons.cpp create mode 100644 src/g_strife/a_strifeweaps.h create mode 100644 src/g_strife/a_templar.cpp create mode 100644 src/g_strife/a_thingstoblowup.cpp create mode 100644 src/g_strife/a_zombie.cpp create mode 100644 src/g_strife/strife_sbar.cpp create mode 100644 src/gameconfigfile.cpp create mode 100644 src/gameconfigfile.h create mode 100644 src/gccinlines.h create mode 100644 src/gi.cpp create mode 100644 src/gi.h create mode 100644 src/gstrings.h create mode 100644 src/hu_scores.cpp create mode 100644 src/hu_stuff.h create mode 100644 src/i_cd.h create mode 100644 src/i_movie.h create mode 100644 src/i_video.h create mode 100644 src/info.cpp create mode 100644 src/info.h create mode 100644 src/infodefaults.cpp create mode 100644 src/infomacros.h create mode 100644 src/lists.h create mode 100644 src/lumpconfigfile.cpp create mode 100644 src/lumpconfigfile.h create mode 100644 src/m_alloc.cpp create mode 100644 src/m_alloc.h create mode 100644 src/m_argv.cpp create mode 100644 src/m_argv.h create mode 100644 src/m_bbox.cpp create mode 100644 src/m_bbox.h create mode 100644 src/m_cheat.cpp create mode 100644 src/m_cheat.h create mode 100644 src/m_crc32.h create mode 100644 src/m_fixed.cpp create mode 100644 src/m_fixed.h create mode 100644 src/m_menu.cpp create mode 100644 src/m_menu.h create mode 100644 src/m_misc.cpp create mode 100644 src/m_misc.h create mode 100644 src/m_options.cpp create mode 100644 src/m_png.cpp create mode 100644 src/m_png.h create mode 100644 src/m_random.cpp create mode 100644 src/m_random.h create mode 100644 src/m_swap.h create mode 100644 src/misc.nas create mode 100644 src/mscinlines.h create mode 100644 src/mus2midi.cpp create mode 100644 src/mus2midi.h create mode 100644 src/name.cpp create mode 100644 src/name.h create mode 100644 src/nodebuild.cpp create mode 100644 src/nodebuild.h create mode 100644 src/nodebuild_events.cpp create mode 100644 src/nodebuild_extract.cpp create mode 100644 src/nodebuild_gl.cpp create mode 100644 src/nodebuild_utility.cpp create mode 100644 src/oplsynth/deftypes.h create mode 100644 src/oplsynth/fmopl.cpp create mode 100644 src/oplsynth/fmopl.h create mode 100644 src/oplsynth/mlkernel.cpp create mode 100644 src/oplsynth/mlopl.cpp create mode 100644 src/oplsynth/mlopl_io.cpp create mode 100644 src/oplsynth/muslib.h create mode 100644 src/oplsynth/opl_mus_player.cpp create mode 100644 src/oplsynth/opl_mus_player.h create mode 100644 src/p_acs.cpp create mode 100644 src/p_acs.h create mode 100644 src/p_buildmap.cpp create mode 100644 src/p_ceiling.cpp create mode 100644 src/p_conversation.cpp create mode 100644 src/p_conversation.h create mode 100644 src/p_doors.cpp create mode 100644 src/p_effect.cpp create mode 100644 src/p_effect.h create mode 100644 src/p_enemy.cpp create mode 100644 src/p_enemy.h create mode 100644 src/p_floor.cpp create mode 100644 src/p_interaction.cpp create mode 100644 src/p_lights.cpp create mode 100644 src/p_lnspec.cpp create mode 100644 src/p_lnspec.h create mode 100644 src/p_local.h create mode 100644 src/p_map.cpp create mode 100644 src/p_maputl.cpp create mode 100644 src/p_mobj.cpp create mode 100644 src/p_pillar.cpp create mode 100644 src/p_plats.cpp create mode 100644 src/p_pspr.cpp create mode 100644 src/p_pspr.h create mode 100644 src/p_saveg.cpp create mode 100644 src/p_saveg.h create mode 100644 src/p_sectors.cpp create mode 100644 src/p_setup.cpp create mode 100644 src/p_setup.h create mode 100644 src/p_sight.cpp create mode 100644 src/p_spec.cpp create mode 100644 src/p_spec.h create mode 100644 src/p_switch.cpp create mode 100644 src/p_teleport.cpp create mode 100644 src/p_terrain.cpp create mode 100644 src/p_terrain.h create mode 100644 src/p_things.cpp create mode 100644 src/p_tick.cpp create mode 100644 src/p_tick.h create mode 100644 src/p_trace.cpp create mode 100644 src/p_trace.h create mode 100644 src/p_user.cpp create mode 100644 src/p_writemap.cpp create mode 100644 src/p_xlat.cpp create mode 100644 src/po_man.cpp create mode 100644 src/r_bsp.cpp create mode 100644 src/r_bsp.h create mode 100644 src/r_data.cpp create mode 100644 src/r_data.h create mode 100644 src/r_defs.h create mode 100644 src/r_draw.cpp create mode 100644 src/r_draw.h create mode 100644 src/r_drawt.cpp create mode 100644 src/r_local.h create mode 100644 src/r_main.cpp create mode 100644 src/r_main.h create mode 100644 src/r_plane.cpp create mode 100644 src/r_plane.h create mode 100644 src/r_polymost.cpp create mode 100644 src/r_polymost.h create mode 100644 src/r_segs.cpp create mode 100644 src/r_segs.h create mode 100644 src/r_sky.cpp create mode 100644 src/r_sky.h create mode 100644 src/r_state.h create mode 100644 src/r_things.cpp create mode 100644 src/r_things.h create mode 100644 src/s_advsound.cpp create mode 100644 src/s_environment.cpp create mode 100644 src/s_playlist.cpp create mode 100644 src/s_playlist.h create mode 100644 src/s_sndseq.cpp create mode 100644 src/s_sndseq.h create mode 100644 src/s_sound.cpp create mode 100644 src/s_sound.h create mode 100644 src/sc_man.cpp create mode 100644 src/sc_man.h create mode 100644 src/sdl/crashcatcher.c create mode 100644 src/sdl/dikeys.h create mode 100644 src/sdl/hardware.cpp create mode 100644 src/sdl/hardware.h create mode 100644 src/sdl/i_cd.cpp create mode 100644 src/sdl/i_input.cpp create mode 100644 src/sdl/i_input.h create mode 100644 src/sdl/i_main.cpp create mode 100644 src/sdl/i_movie.cpp create mode 100644 src/sdl/i_net.cpp create mode 100644 src/sdl/i_net.h create mode 100644 src/sdl/i_system.cpp create mode 100644 src/sdl/i_system.h create mode 100644 src/sdl/i_video.h create mode 100644 src/sdl/sdlvideo.cpp create mode 100644 src/sdl/sdlvideo.h create mode 100644 src/skins.cpp create mode 100644 src/skins.h create mode 100644 src/sound/altsound.cpp create mode 100644 src/sound/altsound.h create mode 100644 src/sound/altsoundmixer.cpp create mode 100644 src/sound/fmodsound.cpp create mode 100644 src/sound/fmodsound.h create mode 100644 src/sound/i_music.cpp create mode 100644 src/sound/i_music.h create mode 100644 src/sound/i_musicinterns.h create mode 100644 src/sound/i_sound.cpp create mode 100644 src/sound/i_sound.h create mode 100644 src/sound/music_cd.cpp create mode 100644 src/sound/music_flac.cpp create mode 100644 src/sound/music_midi_midiout.cpp create mode 100644 src/sound/music_midi_stream.cpp create mode 100644 src/sound/music_midi_timidity.cpp create mode 100644 src/sound/music_mod.cpp create mode 100644 src/sound/music_mus_midiout.cpp create mode 100644 src/sound/music_mus_opl.cpp create mode 100644 src/sound/music_spc.cpp create mode 100644 src/sound/music_stream.cpp create mode 100644 src/sound/sample_flac.cpp create mode 100644 src/sound/sample_flac.h create mode 100644 src/st_stuff.cpp create mode 100644 src/st_stuff.h create mode 100644 src/statnums.h create mode 100644 src/stats.cpp create mode 100644 src/stats.h create mode 100644 src/stringtable.cpp create mode 100644 src/stringtable.h create mode 100644 src/tables.cpp create mode 100644 src/tables.h create mode 100644 src/tagitem.h create mode 100644 src/tarray.h create mode 100644 src/tempfiles.cpp create mode 100644 src/tempfiles.h create mode 100644 src/templates.h create mode 100644 src/thingdef.cpp create mode 100644 src/thingdef_codeptr.cpp create mode 100644 src/thingdef_specials.gperf create mode 100644 src/thingdef_specials.h create mode 100644 src/tmap.nas create mode 100644 src/tmap2.nas create mode 100644 src/tmap3.nas create mode 100644 src/v_collection.cpp create mode 100644 src/v_collection.h create mode 100644 src/v_draw.cpp create mode 100644 src/v_font.cpp create mode 100644 src/v_font.h create mode 100644 src/v_palette.cpp create mode 100644 src/v_palette.h create mode 100644 src/v_pfx.cpp create mode 100644 src/v_pfx.h create mode 100644 src/v_text.cpp create mode 100644 src/v_text.h create mode 100644 src/v_video.cpp create mode 100644 src/v_video.h create mode 100644 src/vectors.cpp create mode 100644 src/vectors.h create mode 100644 src/version.h create mode 100644 src/w_wad.cpp create mode 100644 src/w_wad.h create mode 100644 src/weightedlist.h create mode 100644 src/wi_stuff.cpp create mode 100644 src/wi_stuff.h create mode 100644 src/win32/afxres.h create mode 100644 src/win32/boing1.ico create mode 100644 src/win32/boing2.ico create mode 100644 src/win32/boing3.ico create mode 100644 src/win32/boing4.ico create mode 100644 src/win32/boing5.ico create mode 100644 src/win32/boing6.ico create mode 100644 src/win32/boing7.ico create mode 100644 src/win32/boing8.ico create mode 100644 src/win32/cursor1.cur create mode 100644 src/win32/deadguy.bmp create mode 100644 src/win32/eaxedit.cpp create mode 100644 src/win32/gccseh.h create mode 100644 src/win32/hardware.cpp create mode 100644 src/win32/hardware.h create mode 100644 src/win32/helperthread.cpp create mode 100644 src/win32/helperthread.h create mode 100644 src/win32/i_cd.cpp create mode 100644 src/win32/i_crash.cpp create mode 100644 src/win32/i_input.cpp create mode 100644 src/win32/i_input.h create mode 100644 src/win32/i_main.cpp create mode 100644 src/win32/i_movie.cpp create mode 100644 src/win32/i_net.cpp create mode 100644 src/win32/i_net.h create mode 100644 src/win32/i_system.cpp create mode 100644 src/win32/i_system.h create mode 100644 src/win32/icon1.ico create mode 100644 src/win32/resource.h create mode 100644 src/win32/win32iface.h create mode 100644 src/win32/win32video.cpp create mode 100644 src/win32/winres.h create mode 100644 src/win32/zdoom.RES create mode 100644 src/win32/zdoom.exe.manifest create mode 100644 src/win32/zdoom.rc create mode 100644 src/zstrformat.cpp create mode 100644 src/zstring.cpp create mode 100644 src/zstring.h create mode 100644 src/zstringpool.cpp create mode 100644 strifehelp.acs create mode 100644 thingdef_specials.gperf create mode 100644 tools/dehsupp/Makefile.mgw create mode 100644 tools/dehsupp/dehsupp.vcproj create mode 100644 tools/dehsupp/parse.tab.c create mode 100644 tools/dehsupp/parse.y create mode 100644 tools/lemon/Makefile.mgw create mode 100644 tools/lemon/lemon.c create mode 100644 tools/lemon/lemon.html create mode 100644 tools/lemon/lemon.vcproj create mode 100644 tools/lemon/lempar.c create mode 100644 tools/makewad/Makefile.mgw create mode 100644 tools/makewad/makewad.c create mode 100644 tools/makewad/makewad.vcproj create mode 100644 tools/re2c/Makefile.am create mode 100644 tools/re2c/Makefile.in create mode 100644 tools/re2c/Makefile.mgw create mode 100644 tools/re2c/README create mode 100644 tools/re2c/README.in create mode 100644 tools/re2c/aclocal.m4 create mode 100644 tools/re2c/actions.cc create mode 100644 tools/re2c/basics.h create mode 100644 tools/re2c/code.cc create mode 100644 tools/re2c/config.h.in create mode 100644 tools/re2c/configure create mode 100644 tools/re2c/configure.in create mode 100644 tools/re2c/configwin.h create mode 100644 tools/re2c/dfa.cc create mode 100644 tools/re2c/dfa.h create mode 100644 tools/re2c/doc/loplas.ps create mode 100644 tools/re2c/doc/sample.bib create mode 100644 tools/re2c/examples/basemmap.c create mode 100644 tools/re2c/examples/c.re create mode 100644 tools/re2c/examples/cmmap.re create mode 100644 tools/re2c/examples/cnokw.re create mode 100644 tools/re2c/examples/cunroll.re create mode 100644 tools/re2c/examples/modula.re create mode 100644 tools/re2c/examples/rexx/README create mode 100644 tools/re2c/examples/rexx/rexx.l create mode 100644 tools/re2c/examples/rexx/scanio.c create mode 100644 tools/re2c/examples/sample.re create mode 100644 tools/re2c/examples/simple.re create mode 100644 tools/re2c/globals.h create mode 100644 tools/re2c/ins.h create mode 100644 tools/re2c/install-sh create mode 100644 tools/re2c/main.cc create mode 100644 tools/re2c/makerpm.in create mode 100644 tools/re2c/mbo_getopt.cc create mode 100644 tools/re2c/mbo_getopt.h create mode 100644 tools/re2c/missing create mode 100644 tools/re2c/mkinstalldirs create mode 100644 tools/re2c/parser.cc create mode 100644 tools/re2c/parser.h create mode 100644 tools/re2c/parser.y create mode 100644 tools/re2c/re.h create mode 100644 tools/re2c/re2c.1 create mode 100644 tools/re2c/re2c.1.in create mode 100644 tools/re2c/re2c.spec.in create mode 100644 tools/re2c/re2c.vcproj create mode 100644 tools/re2c/scanner.cc create mode 100644 tools/re2c/scanner.h create mode 100644 tools/re2c/scanner.re create mode 100644 tools/re2c/stamp-h.in create mode 100644 tools/re2c/substr.cc create mode 100644 tools/re2c/substr.h create mode 100644 tools/re2c/test.c create mode 100644 tools/re2c/test.re create mode 100644 tools/re2c/token.h create mode 100644 tools/re2c/translate.cc create mode 100644 tools/re2c/y.tab.h create mode 100644 tools/xlatcc/Makefile.mgw create mode 100644 tools/xlatcc/gen.c create mode 100644 tools/xlatcc/xlat-parse.tab.c create mode 100644 tools/xlatcc/xlat-parse.y create mode 100644 tools/xlatcc/xlat.h create mode 100644 tools/xlatcc/xlatcc.vcproj create mode 100644 wadsrc/Makefile create mode 100644 wadsrc/Makefile.mgw create mode 100644 wadsrc/Makefile2 create mode 100644 wadsrc/animated.lmp create mode 100644 wadsrc/animdefs.txt create mode 100644 wadsrc/artibox.png create mode 100644 wadsrc/badpatch.lmp create mode 100644 wadsrc/clerface.lmp create mode 100644 wadsrc/confont.lmp create mode 100644 wadsrc/dbigfont.lmp create mode 100644 wadsrc/decals/bal7scr1.png create mode 100644 wadsrc/decals/bal7scr2.png create mode 100644 wadsrc/decals/bfglite1.png create mode 100644 wadsrc/decals/bfglite2.png create mode 100644 wadsrc/decals/bfgscrc1.png create mode 100644 wadsrc/decals/bfgscrc2.png create mode 100644 wadsrc/decals/blast1.png create mode 100644 wadsrc/decals/bsmear1.png create mode 100644 wadsrc/decals/bsmear2.png create mode 100644 wadsrc/decals/bsplat1.png create mode 100644 wadsrc/decals/bsplat2.png create mode 100644 wadsrc/decals/bsplat3.png create mode 100644 wadsrc/decals/bsplat4.png create mode 100644 wadsrc/decals/bsplat5.png create mode 100644 wadsrc/decals/bsplat6.png create mode 100644 wadsrc/decals/bsplat7.png create mode 100644 wadsrc/decals/cbalscr1.png create mode 100644 wadsrc/decals/cbalscr2.png create mode 100644 wadsrc/decals/cbowmark.png create mode 100644 wadsrc/decals/chip1.png create mode 100644 wadsrc/decals/chip2.png create mode 100644 wadsrc/decals/chip3.png create mode 100644 wadsrc/decals/chip4.png create mode 100644 wadsrc/decals/chip5.png create mode 100644 wadsrc/decals/decaldef.txt create mode 100644 wadsrc/decals/plasma1.png create mode 100644 wadsrc/decals/plasma2.png create mode 100644 wadsrc/decals/scorch1.png create mode 100644 wadsrc/dehsupp.lmp create mode 100644 wadsrc/dehsupp.txt create mode 100644 wadsrc/doomx.lmp create mode 100644 wadsrc/dsempty.lmp create mode 100644 wadsrc/fiteface.lmp create mode 100644 wadsrc/fonta164.lmp create mode 100644 wadsrc/fonta165.lmp create mode 100644 wadsrc/fonta182.lmp create mode 100644 wadsrc/fonta188.lmp create mode 100644 wadsrc/fonta191.lmp create mode 100644 wadsrc/fonta60.lmp create mode 100644 wadsrc/fonta61.lmp create mode 100644 wadsrc/fonta62.lmp create mode 100644 wadsrc/fonta63.lmp create mode 100644 wadsrc/foo create mode 100644 wadsrc/hamoback.png create mode 100644 wadsrc/hereticx.lmp create mode 100644 wadsrc/icebreak.flac create mode 100644 wadsrc/iceca0.png create mode 100644 wadsrc/icecb0.png create mode 100644 wadsrc/icecc0.png create mode 100644 wadsrc/icecd0.png create mode 100644 wadsrc/icedeath.flac create mode 100644 wadsrc/invgeml1.lmp create mode 100644 wadsrc/invgeml2.lmp create mode 100644 wadsrc/invgemr1.lmp create mode 100644 wadsrc/invgemr2.lmp create mode 100644 wadsrc/languages/english-us.txt create mode 100644 wadsrc/languages/french.txt create mode 100644 wadsrc/languages/italian.txt create mode 100644 wadsrc/mageface.lmp create mode 100644 wadsrc/mapinfo/doom1.txt create mode 100644 wadsrc/mapinfo/doom2.txt create mode 100644 wadsrc/mapinfo/heretic.txt create mode 100644 wadsrc/mapinfo/hexen.txt create mode 100644 wadsrc/mapinfo/plutonia.txt create mode 100644 wadsrc/mapinfo/strife.txt create mode 100644 wadsrc/mapinfo/tnt.txt create mode 100644 wadsrc/noflat.png create mode 100644 wadsrc/quake.flac create mode 100644 wadsrc/railgunfire.flac create mode 100644 wadsrc/sbigfont.lmp create mode 100644 wadsrc/secret.flac create mode 100644 wadsrc/selectbo.png create mode 100644 wadsrc/sndeax.txt create mode 100644 wadsrc/sndinfo.txt create mode 100644 wadsrc/sndseq.txt create mode 100644 wadsrc/spaldoom.lmp create mode 100644 wadsrc/spalhtic.lmp create mode 100644 wadsrc/spark1.flac create mode 100644 wadsrc/spark2.flac create mode 100644 wadsrc/spark3.flac create mode 100644 wadsrc/stcfn196.lmp create mode 100644 wadsrc/stcfn197.lmp create mode 100644 wadsrc/stcfn214.lmp create mode 100644 wadsrc/stcfn220.lmp create mode 100644 wadsrc/stcfn223.lmp create mode 100644 wadsrc/stfbany.lmp create mode 100644 wadsrc/stkeys6.lmp create mode 100644 wadsrc/stkeys7.lmp create mode 100644 wadsrc/stkeys8.lmp create mode 100644 wadsrc/stpbany.lmp create mode 100644 wadsrc/strfhelp.o create mode 100644 wadsrc/strifex.lmp create mode 100644 wadsrc/terrain.txt create mode 100644 wadsrc/tlgl.png create mode 100644 wadsrc/tnt1a0.png create mode 100644 wadsrc/unkna0.png create mode 100644 wadsrc/wadmake create mode 100644 wadsrc/wadsrc.vcproj create mode 100644 wadsrc/x11r6rgb.txt create mode 100644 wadsrc/xhairb1.imgz create mode 100644 wadsrc/xhairb2.png create mode 100644 wadsrc/xhairb3.imgz create mode 100644 wadsrc/xhairb4.imgz create mode 100644 wadsrc/xhairb5.imgz create mode 100644 wadsrc/xhairb6.imgz create mode 100644 wadsrc/xhairb7.imgz create mode 100644 wadsrc/xhairs1.imgz create mode 100644 wadsrc/xhairs2.imgz create mode 100644 wadsrc/xhairs3.imgz create mode 100644 wadsrc/xhairs4.imgz create mode 100644 wadsrc/xhairs5.imgz create mode 100644 wadsrc/xhairs6.imgz create mode 100644 wadsrc/xhairs7.imgz create mode 100644 wadsrc/xlat/defines.i create mode 100644 wadsrc/xlat/doom.x create mode 100644 wadsrc/xlat/doomxlat.txt create mode 100644 wadsrc/xlat/heretic.x create mode 100644 wadsrc/xlat/hereticxlat.txt create mode 100644 wadsrc/xlat/specials.i create mode 100644 wadsrc/xlat/strife.x create mode 100644 wadsrc/xlat/strifexlat.txt create mode 100644 wadsrc/zdoom.lst create mode 100644 zdoom.sln create mode 100644 zdoom.vcproj create mode 100644 zlib/ChangeLog create mode 100644 zlib/FAQ create mode 100644 zlib/INDEX create mode 100644 zlib/Makefile create mode 100644 zlib/Makefile.in create mode 100644 zlib/Makefile.mgw create mode 100644 zlib/README create mode 100644 zlib/adler32.c create mode 100644 zlib/algorithm.txt create mode 100644 zlib/compress.c create mode 100644 zlib/configure create mode 100644 zlib/crc32.c create mode 100644 zlib/crc32.h create mode 100644 zlib/deflate.c create mode 100644 zlib/deflate.h create mode 100644 zlib/example.c create mode 100644 zlib/gzio.c create mode 100644 zlib/infback.c create mode 100644 zlib/inffast.c create mode 100644 zlib/inffast.h create mode 100644 zlib/inffixed.h create mode 100644 zlib/inflate.c create mode 100644 zlib/inflate.h create mode 100644 zlib/inftrees.c create mode 100644 zlib/inftrees.h create mode 100644 zlib/minigzip.c create mode 100644 zlib/trees.c create mode 100644 zlib/trees.h create mode 100644 zlib/uncompr.c create mode 100644 zlib/zconf.h create mode 100644 zlib/zconf.in.h create mode 100644 zlib/zlib.3 create mode 100644 zlib/zlib.h create mode 100644 zlib/zlib.vcproj create mode 100644 zlib/zutil.c create mode 100644 zlib/zutil.h diff --git a/FLAC/FLAC++/decoder.h b/FLAC/FLAC++/decoder.h new file mode 100644 index 00000000000..d3ca72fb351 --- /dev/null +++ b/FLAC/FLAC++/decoder.h @@ -0,0 +1,354 @@ +/* libFLAC++ - Free Lossless Audio Codec library + * Copyright (C) 2002,2003,2004 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 FLACPP__DECODER_H +#define FLACPP__DECODER_H + +#include "export.h" + +// [RH] ZDoom doesn't need these +//#include "FLAC/file_decoder.h" +//#include "FLAC/seekable_stream_decoder.h" +#include "FLAC/stream_decoder.h" + + +/** \file include/FLAC++/decoder.h + * + * \brief + * This module contains the classes which implement the various + * decoders. + * + * See the detailed documentation in the + * \link flacpp_decoder decoder \endlink module. + */ + +/** \defgroup flacpp_decoder FLAC++/decoder.h: decoder classes + * \ingroup flacpp + * + * \brief + * This module describes the three decoder layers provided by libFLAC++. + * + * The libFLAC++ decoder classes are object wrappers around their + * counterparts in libFLAC. All three decoding layers available in + * libFLAC are also provided here. The interface is very similar; + * make sure to read the \link flac_decoder libFLAC decoder module \endlink. + * + * The only real difference here is that instead of passing in C function + * pointers for callbacks, you inherit from the decoder class and provide + * implementations for the callbacks in the derived class; because of this + * there is no need for a 'client_data' property. + */ + +namespace FLAC { + namespace Decoder { + + // ============================================================ + // + // Equivalent: FLAC__StreamDecoder + // + // ============================================================ + + /** \defgroup flacpp_stream_decoder FLAC++/decoder.h: stream decoder class + * \ingroup flacpp_decoder + * + * \brief + * This class wraps the ::FLAC__StreamDecoder. + * + * See the \link flac_stream_decoder libFLAC stream decoder module \endlink. + * + * \{ + */ + + /** This class wraps the ::FLAC__StreamDecoder. + */ + class FLACPP_API Stream { + public: + class FLACPP_API State { + public: + inline State(::FLAC__StreamDecoderState state): state_(state) { } + inline operator ::FLAC__StreamDecoderState() const { return state_; } + inline const char *as_cstring() const { return ::FLAC__StreamDecoderStateString[state_]; } + inline const char *resolved_as_cstring(const Stream &decoder) const { return ::FLAC__stream_decoder_get_resolved_state_string(decoder.decoder_); } + protected: + ::FLAC__StreamDecoderState state_; + }; + + Stream(); + virtual ~Stream(); + + bool is_valid() const; + inline operator bool() const { return is_valid(); } + + bool set_metadata_respond(::FLAC__MetadataType type); + bool set_metadata_respond_application(const FLAC__byte id[4]); + bool set_metadata_respond_all(); + bool set_metadata_ignore(::FLAC__MetadataType type); + bool set_metadata_ignore_application(const FLAC__byte id[4]); + bool set_metadata_ignore_all(); + + State get_state() const; + unsigned get_channels() const; + ::FLAC__ChannelAssignment get_channel_assignment() const; + unsigned get_bits_per_sample() const; + unsigned get_sample_rate() const; + unsigned get_blocksize() const; + + /** Initialize the instance; as with the C interface, + * init() should be called after construction and 'set' + * calls but before any of the 'process' calls. + */ + State init(); + + void finish(); + + bool flush(); + bool reset(); + + bool process_single(); + bool process_until_end_of_metadata(); + bool process_until_end_of_stream(); + bool skip_single_frame(); + protected: + virtual ::FLAC__StreamDecoderReadStatus read_callback(FLAC__byte buffer[], unsigned *bytes) = 0; + virtual ::FLAC__StreamDecoderWriteStatus write_callback(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[]) = 0; + virtual void metadata_callback(const ::FLAC__StreamMetadata *metadata) = 0; + virtual void error_callback(::FLAC__StreamDecoderErrorStatus status) = 0; + +#if (defined _MSC_VER) || (defined __GNUG__ && (__GNUG__ < 2 || (__GNUG__ == 2 && __GNUC_MINOR__ < 96))) + // lame hack: some MSVC/GCC versions can't see a protected decoder_ from nested State::resolved_as_cstring() + friend State; +#endif + ::FLAC__StreamDecoder *decoder_; + private: + static ::FLAC__StreamDecoderReadStatus read_callback_(const ::FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *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); + + // Private and undefined so you can't use them: + Stream(const Stream &); + void operator=(const Stream &); + }; + + /* \} */ + +#if 0 // [RH] Don't need these for ZDoom + // ============================================================ + // + // Equivalent: FLAC__SeekableStreamDecoder + // + // ============================================================ + + /** \defgroup flacpp_seekable_stream_decoder FLAC++/decoder.h: seekable stream decoder class + * \ingroup flacpp_decoder + * + * \brief + * This class wraps the ::FLAC__SeekableStreamDecoder. + * + * See the \link flac_seekable_stream_decoder libFLAC seekable stream decoder module \endlink. + * + * \{ + */ + + /** This class wraps the ::FLAC__SeekableStreamDecoder. + */ + class FLACPP_API SeekableStream { + public: + class FLACPP_API State { + public: + inline State(::FLAC__SeekableStreamDecoderState state): state_(state) { } + inline operator ::FLAC__SeekableStreamDecoderState() const { return state_; } + inline const char *as_cstring() const { return ::FLAC__SeekableStreamDecoderStateString[state_]; } + inline const char *resolved_as_cstring(const SeekableStream &decoder) const { return ::FLAC__seekable_stream_decoder_get_resolved_state_string(decoder.decoder_); } + protected: + ::FLAC__SeekableStreamDecoderState state_; + }; + + SeekableStream(); + virtual ~SeekableStream(); + + bool is_valid() const; + inline operator bool() const { return is_valid(); } + + bool set_md5_checking(bool value); + bool set_metadata_respond(::FLAC__MetadataType type); + bool set_metadata_respond_application(const FLAC__byte id[4]); + bool set_metadata_respond_all(); + bool set_metadata_ignore(::FLAC__MetadataType type); + bool set_metadata_ignore_application(const FLAC__byte id[4]); + bool set_metadata_ignore_all(); + + State get_state() const; + Stream::State get_stream_decoder_state() const; + bool get_md5_checking() const; + unsigned get_channels() const; + ::FLAC__ChannelAssignment get_channel_assignment() const; + unsigned get_bits_per_sample() const; + unsigned get_sample_rate() const; + unsigned get_blocksize() const; + + State init(); + + bool finish(); + + bool flush(); + bool reset(); + + bool process_single(); + bool process_until_end_of_metadata(); + bool process_until_end_of_stream(); + bool skip_single_frame(); + + bool seek_absolute(FLAC__uint64 sample); + protected: + virtual ::FLAC__SeekableStreamDecoderReadStatus read_callback(FLAC__byte buffer[], unsigned *bytes) = 0; + virtual ::FLAC__SeekableStreamDecoderSeekStatus seek_callback(FLAC__uint64 absolute_byte_offset) = 0; + virtual ::FLAC__SeekableStreamDecoderTellStatus tell_callback(FLAC__uint64 *absolute_byte_offset) = 0; + virtual ::FLAC__SeekableStreamDecoderLengthStatus length_callback(FLAC__uint64 *stream_length) = 0; + virtual bool eof_callback() = 0; + virtual ::FLAC__StreamDecoderWriteStatus write_callback(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[]) = 0; + virtual void metadata_callback(const ::FLAC__StreamMetadata *metadata) = 0; + virtual void error_callback(::FLAC__StreamDecoderErrorStatus status) = 0; + +#if (defined _MSC_VER) || (defined __GNUG__ && (__GNUG__ < 2 || (__GNUG__ == 2 && __GNUC_MINOR__ < 96))) + // lame hack: some MSVC/GCC versions can't see a protected decoder_ from nested State::resolved_as_cstring() + friend State; +#endif + ::FLAC__SeekableStreamDecoder *decoder_; + private: + static ::FLAC__SeekableStreamDecoderReadStatus read_callback_(const ::FLAC__SeekableStreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data); + static ::FLAC__SeekableStreamDecoderSeekStatus seek_callback_(const ::FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data); + static ::FLAC__SeekableStreamDecoderTellStatus tell_callback_(const ::FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data); + static ::FLAC__SeekableStreamDecoderLengthStatus length_callback_(const ::FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data); + static FLAC__bool eof_callback_(const ::FLAC__SeekableStreamDecoder *decoder, void *client_data); + static ::FLAC__StreamDecoderWriteStatus write_callback_(const ::FLAC__SeekableStreamDecoder *decoder, const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data); + static void metadata_callback_(const ::FLAC__SeekableStreamDecoder *decoder, const ::FLAC__StreamMetadata *metadata, void *client_data); + static void error_callback_(const ::FLAC__SeekableStreamDecoder *decoder, ::FLAC__StreamDecoderErrorStatus status, void *client_data); + + // Private and undefined so you can't use them: + SeekableStream(const SeekableStream &); + void operator=(const SeekableStream &); + }; + + /* \} */ + + // ============================================================ + // + // Equivalent: FLAC__FileDecoder + // + // ============================================================ + + /** \defgroup flacpp_file_decoder FLAC++/decoder.h: file decoder class + * \ingroup flacpp_decoder + * + * \brief + * This class wraps the ::FLAC__FileDecoder. + * + * See the \link flac_file_decoder libFLAC file decoder module \endlink. + * + * \{ + */ + + /** This class wraps the ::FLAC__FileDecoder. + */ + class FLACPP_API File { + public: + class FLACPP_API State { + public: + inline State(::FLAC__FileDecoderState state): state_(state) { } + inline operator ::FLAC__FileDecoderState() const { return state_; } + inline const char *as_cstring() const { return ::FLAC__FileDecoderStateString[state_]; } + inline const char *resolved_as_cstring(const File &decoder) const { return ::FLAC__file_decoder_get_resolved_state_string(decoder.decoder_); } + protected: + ::FLAC__FileDecoderState state_; + }; + + File(); + virtual ~File(); + + bool is_valid() const; + inline operator bool() const { return is_valid(); } + + bool set_md5_checking(bool value); + bool set_filename(const char *value); //!< 'value' may not be \c NULL; use "-" for stdin + bool set_metadata_respond(::FLAC__MetadataType type); + bool set_metadata_respond_application(const FLAC__byte id[4]); + bool set_metadata_respond_all(); + bool set_metadata_ignore(::FLAC__MetadataType type); + bool set_metadata_ignore_application(const FLAC__byte id[4]); + bool set_metadata_ignore_all(); + + State get_state() const; + SeekableStream::State get_seekable_stream_decoder_state() const; + Stream::State get_stream_decoder_state() const; + bool get_md5_checking() const; + unsigned get_channels() const; + ::FLAC__ChannelAssignment get_channel_assignment() const; + unsigned get_bits_per_sample() const; + unsigned get_sample_rate() const; + unsigned get_blocksize() const; + + State init(); + + bool finish(); + + bool process_single(); + bool process_until_end_of_metadata(); + bool process_until_end_of_file(); + bool skip_single_frame(); + + bool seek_absolute(FLAC__uint64 sample); + protected: + virtual ::FLAC__StreamDecoderWriteStatus write_callback(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[]) = 0; + virtual void metadata_callback(const ::FLAC__StreamMetadata *metadata) = 0; + virtual void error_callback(::FLAC__StreamDecoderErrorStatus status) = 0; + +#if (defined _MSC_VER) || (defined __GNUG__ && (__GNUG__ < 2 || (__GNUG__ == 2 && __GNUC_MINOR__ < 96))) + // lame hack: some MSVC/GCC versions can't see a protected decoder_ from nested State::resolved_as_cstring() + friend State; +#endif + ::FLAC__FileDecoder *decoder_; + private: + static ::FLAC__StreamDecoderWriteStatus write_callback_(const ::FLAC__FileDecoder *decoder, const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data); + static void metadata_callback_(const ::FLAC__FileDecoder *decoder, const ::FLAC__StreamMetadata *metadata, void *client_data); + static void error_callback_(const ::FLAC__FileDecoder *decoder, ::FLAC__StreamDecoderErrorStatus status, void *client_data); + + // Private and undefined so you can't use them: + File(const File &); + void operator=(const File &); + }; + + /* \} */ +#endif // [RH] + }; +}; + +#endif diff --git a/FLAC/FLAC++/export.h b/FLAC/FLAC++/export.h new file mode 100644 index 00000000000..262569097b7 --- /dev/null +++ b/FLAC/FLAC++/export.h @@ -0,0 +1,47 @@ +/* libFLAC++ - Free Lossless Audio Codec library + * Copyright (C) 2002,2003,2004 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 FLACPP__EXPORT_H +#define FLACPP__EXPORT_H + +#if defined(FLAC__NO_DLL) || !defined(_MSC_VER) || 1 +#define FLACPP_API + +#else + +#ifdef FLACPP_API_EXPORTS +#define FLACPP_API _declspec(dllexport) +#else +#define FLACPP_API _declspec(dllimport) + +#endif +#endif +#endif diff --git a/FLAC/FLAC.dsp b/FLAC/FLAC.dsp new file mode 100644 index 00000000000..d0363b456f6 --- /dev/null +++ b/FLAC/FLAC.dsp @@ -0,0 +1,327 @@ +# Microsoft Developer Studio Project File - Name="FLAC" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=FLAC - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "FLAC.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "FLAC.mak" CFG="FLAC - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "FLAC - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE "FLAC - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "FLAC - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /ZI /W3 /Od /D "WIN32" /D "_DEBUG" /D "_LIB" /D "FLAC__CPU_IA32" /D "FLAC__HAS_NASM" /D "FLAC__SSE_OS" /D "FLAC__USE_3DNOW" /D "_MBCS" /Gm PRECOMP_VC7_TOBEREMOVED /GZ /c /GX +# ADD CPP /nologo /MTd /ZI /W3 /Od /D "WIN32" /D "_DEBUG" /D "_LIB" /D "FLAC__CPU_IA32" /D "FLAC__HAS_NASM" /D "FLAC__SSE_OS" /D "FLAC__USE_3DNOW" /D "_MBCS" /Gm PRECOMP_VC7_TOBEREMOVED /GZ /c /GX +# ADD BASE MTL /nologo /win32 +# ADD MTL /nologo /win32 +# ADD BASE RSC /l 1033 +# ADD RSC /l 1033 +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo /out:"Debug\FLAC.lib" +# ADD LIB32 /nologo /out:"Debug\FLAC.lib" + +!ELSEIF "$(CFG)" == "FLAC - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /Zi /W3 /O2 /Ob1 /Oy /D "WIN32" /D "NDEBUG" /D "_LIB" /D "FLAC__CPU_IA32" /D "FLAC__HAS_NASM" /D "FLAC__SSE_OS" /D "FLAC__USE_3DNOW" /D "_MBCS" /GF /Gy PRECOMP_VC7_TOBEREMOVED /c /GX +# ADD CPP /nologo /MT /Zi /W3 /O2 /Ob1 /Oy /D "WIN32" /D "NDEBUG" /D "_LIB" /D "FLAC__CPU_IA32" /D "FLAC__HAS_NASM" /D "FLAC__SSE_OS" /D "FLAC__USE_3DNOW" /D "_MBCS" /GF /Gy PRECOMP_VC7_TOBEREMOVED /c /GX +# ADD BASE MTL /nologo /win32 +# ADD MTL /nologo /win32 +# ADD BASE RSC /l 1033 +# ADD RSC /l 1033 +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo /out:"Release\FLAC.lib" +# ADD LIB32 /nologo /out:"Release\FLAC.lib" + +!ENDIF + +# Begin Target + +# Name "FLAC - Win32 Debug" +# Name "FLAC - Win32 Release" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;def;odl;idl;hpj;bat;asm" +# Begin Source File + +SOURCE=bitbuffer.c +# End Source File +# Begin Source File + +SOURCE=bitmath.c +# End Source File +# Begin Source File + +SOURCE=cpu.c +# End Source File +# Begin Source File + +SOURCE=crc.c +# End Source File +# Begin Source File + +SOURCE=fixed.c +# End Source File +# Begin Source File + +SOURCE=format.c +# End Source File +# Begin Source File + +SOURCE=lpc.c +# End Source File +# Begin Source File + +SOURCE=stream_decoder.c +# End Source File +# Begin Source File + +SOURCE=stream_decoder_pp.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl;inc" +# Begin Group "Protected" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=protected\stream_decoder.h +# End Source File +# End Group +# Begin Group "Private" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=private\bitbuffer.h +# End Source File +# Begin Source File + +SOURCE=private\bitmath.h +# End Source File +# Begin Source File + +SOURCE=private\cpu.h +# End Source File +# Begin Source File + +SOURCE=private\crc.h +# End Source File +# Begin Source File + +SOURCE=private\fixed.h +# End Source File +# Begin Source File + +SOURCE=private\format.h +# End Source File +# Begin Source File + +SOURCE=private\lpc.h +# End Source File +# End Group +# Begin Group "FLAC" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=FLAC\assert.h +# End Source File +# Begin Source File + +SOURCE=FLAC\export.h +# End Source File +# Begin Source File + +SOURCE=FLAC\format.h +# End Source File +# Begin Source File + +SOURCE=FLAC\ordinals.h +# End Source File +# Begin Source File + +SOURCE=FLAC\stream_decoder.h +# End Source File +# End Group +# Begin Group "FLAC++" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=FLAC++\decoder.h +# End Source File +# Begin Source File + +SOURCE=FLAC++\export.h +# End Source File +# End Group +# End Group +# Begin Group "IA32 Files" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=ia32\cpu_asm.nasm + +!IF "$(CFG)" == "FLAC - Win32 Debug" + +# PROP Ignore_Default_Tool 1 +# Begin Custom Build - Assembling $(InputPath)... +SOURCE="$(InputPath)" + +BuildCmds= \ + nasmw -o $(IntDir)\$(InputName).obj -d OBJ_FORMAT_win32 -f win32 $(InputPath) \ + + +"$(IntDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) +# End Custom Build + +!ELSEIF "$(CFG)" == "FLAC - Win32 Release" + +# PROP Ignore_Default_Tool 1 +# Begin Custom Build - Assembling $(InputPath)... +SOURCE="$(InputPath)" + +BuildCmds= \ + nasmw -o $(IntDir)\$(InputName).obj -d OBJ_FORMAT_win32 -f win32 $(InputPath) \ + + +"$(IntDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) +# End Custom Build + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=ia32\fixed_asm.nasm + +!IF "$(CFG)" == "FLAC - Win32 Debug" + +# PROP Ignore_Default_Tool 1 +# Begin Custom Build - Assembling $(InputPath)... +SOURCE="$(InputPath)" + +BuildCmds= \ + nasmw -o $(IntDir)\$(InputName).obj -d OBJ_FORMAT_win32 -f win32 $(InputPath) \ + + +"$(IntDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) +# End Custom Build + +!ELSEIF "$(CFG)" == "FLAC - Win32 Release" + +# PROP Ignore_Default_Tool 1 +# Begin Custom Build - Assembling $(InputPath)... +SOURCE="$(InputPath)" + +BuildCmds= \ + nasmw -o $(IntDir)\$(InputName).obj -d OBJ_FORMAT_win32 -f win32 $(InputPath) \ + + +"$(IntDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) +# End Custom Build + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=ia32\lpc_asm.nasm + +!IF "$(CFG)" == "FLAC - Win32 Debug" + +# PROP Ignore_Default_Tool 1 +# Begin Custom Build - Assembling $(InputPath)... +SOURCE="$(InputPath)" + +BuildCmds= \ + nasmw -o $(IntDir)\$(InputName).obj -d OBJ_FORMAT_win32 -f win32 $(InputPath) \ + + +"$(IntDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) +# End Custom Build + +!ELSEIF "$(CFG)" == "FLAC - Win32 Release" + +# PROP Ignore_Default_Tool 1 +# Begin Custom Build - Assembling $(InputPath)... +SOURCE="$(InputPath)" + +BuildCmds= \ + nasmw -o $(IntDir)\$(InputName).obj -d OBJ_FORMAT_win32 -f win32 $(InputPath) \ + + +"$(IntDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) +# End Custom Build + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=ia32\nasm.h +# End Source File +# End Group +# Begin Source File + +SOURCE=ReadMe.txt +# End Source File +# End Target +# End Project + diff --git a/FLAC/FLAC.vcproj b/FLAC/FLAC.vcproj new file mode 100644 index 00000000000..85599facc14 --- /dev/null +++ b/FLAC/FLAC.vcproj @@ -0,0 +1,276 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FLAC/FLAC/assert.h b/FLAC/FLAC/assert.h new file mode 100644 index 00000000000..cab471a2a25 --- /dev/null +++ b/FLAC/FLAC/assert.h @@ -0,0 +1,45 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2001,2002,2003,2004 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/FLAC/FLAC/export.h b/FLAC/FLAC/export.h new file mode 100644 index 00000000000..613af742385 --- /dev/null +++ b/FLAC/FLAC/export.h @@ -0,0 +1,47 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2000,2001,2002,2003,2004 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 + +#if defined(FLAC__NO_DLL) || !defined(_MSC_VER) || 1 +#define FLAC_API + +#else + +#ifdef FLAC_API_EXPORTS +#define FLAC_API _declspec(dllexport) +#else +#define FLAC_API _declspec(dllimport) + +#endif +#endif +#endif diff --git a/FLAC/FLAC/format.h b/FLAC/FLAC/format.h new file mode 100644 index 00000000000..e003c34fe89 --- /dev/null +++ b/FLAC/FLAC/format.h @@ -0,0 +1,812 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2000,2001,2002,2003,2004 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 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 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 nulL-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 + * 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. */ + + 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_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; + +extern FLAC_API const unsigned FLAC__SUBFRAME_ZERO_PAD_LEN; /**< == 1 (bit) */ +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. */ + + 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; /**< == 2 (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 */ + + FLAC__METADATA_TYPE_CUESHEET = 5, + /**< CUESHEET block */ + + FLAC__METADATA_TYPE_UNDEFINED = 6 + /**< 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) + */ +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 '\0' */ + + 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) */ + + +/** 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_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 + * + *****************************************************************************/ + +/* @@@@ add to unit tests; it is already indirectly tested by the metadata_object tests */ +/** Tests that a sample rate is valid for FLAC. Since the rules for valid + * sample rates are slightly complex, they are encapsulated in this function. + * + * \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); + +/* @@@@ add to unit tests; it is already indirectly tested by the metadata_object tests */ +/** 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); + +/* @@@@ add to unit tests; it is already indirectly tested by the metadata_object tests */ +/** 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); + +/* @@@@ add to unit tests; it is already indirectly tested by the metadata_object tests */ +/** 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); + +/* \} */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/FLAC/FLAC/ordinals.h b/FLAC/FLAC/ordinals.h new file mode 100644 index 00000000000..77ec76085e0 --- /dev/null +++ b/FLAC/FLAC/ordinals.h @@ -0,0 +1,74 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2000,2001,2002,2003,2004 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 + +#ifndef _MSC_VER +#include +#endif + +typedef signed char FLAC__int8; +typedef unsigned char FLAC__uint8; + +#if defined _MSC_VER +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; +#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; +typedef float FLAC__real; + +#ifdef true +#undef true +#endif +#ifdef false +#undef false +#endif +#ifndef __cplusplus +#define true 1 +#define false 0 +#endif + +#endif diff --git a/FLAC/FLAC/stream_decoder.h b/FLAC/FLAC/stream_decoder.h new file mode 100644 index 00000000000..9c2c3670315 --- /dev/null +++ b/FLAC/FLAC/stream_decoder.h @@ -0,0 +1,873 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2000,2001,2002,2003,2004 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 "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 three decoder layers provided by libFLAC. + * + * For decoding FLAC streams, libFLAC provides three layers of access. The + * lowest layer is non-seekable stream-level decoding, the next is seekable + * stream-level decoding, and the highest layer is file-level decoding. The + * interfaces are described in the \link flac_stream_decoder stream decoder + * \endlink, \link flac_seekable_stream_decoder seekable stream decoder + * \endlink, and \link flac_file_decoder file decoder \endlink modules + * respectively. Typically you will choose the highest layer that your input + * source will support. + * + * The stream decoder relies on callbacks for all input and output and has no + * provisions for seeking. The seekable stream decoder wraps the stream + * decoder and exposes functions for seeking. However, you must provide + * extra callbacks for seek-related operations on your stream, like seek and + * tell. The file decoder wraps the seekable stream decoder and supplies + * most of the callbacks internally, simplifying the processing of standard + * files. + */ + +/** \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 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 and sets callbacks for + * reading, writing, error reporting, and metadata reporting using + * FLAC__stream_decoder_set_*() functions. + * - The program initializes the instance to validate the settings and + * prepare for decoding using FLAC__stream_decoder_init(). + * - 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 set the callbacks and client data, and call + * FLAC__stream_decoder_init(). The required callbacks are: + * + * - Read callback - This 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. + * - Write callback - This function will be called when the decoder has + * decoded a single frame of data. The decoder will pass the frame + * metadata as well as an array of pointers (one for each channel) + * pointing to the decoded audio. + * - Metadata callback - This function will be called when the decoder has + * decoded a metadata block. In a valid FLAC file there will always be + * one 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 STREAMINFO + * block; you can instruct the decoder to pass or filter other blocks with + * FLAC__stream_decoder_set_metadata_*() calls. + * - Error callback - This function will be called whenever an error occurs + * during decoding. + * + * 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 user 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 user 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. + * + * Note that the stream decoder has no real concept of stream position, it + * just converts data. To seek within a stream the callbacks have only to + * flush the decoder using FLAC__stream_decoder_flush() and start feeding + * data from the new position through the read callback. The seekable + * stream decoder does just this. + * + * 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 some metadata blocks can be big 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_ABORTED, + /**< The decoder was aborted by the read callback. */ + + FLAC__STREAM_DECODER_UNPARSEABLE_STREAM, + /**< The decoder encountered reserved fields in use in the stream. */ + + FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR, + /**< An error occurred allocating memory. */ + + FLAC__STREAM_DECODER_ALREADY_INITIALIZED, + /**< FLAC__stream_decoder_init() was called when the decoder was + * already initialized, usually because + * FLAC__stream_decoder_finish() was not called. + */ + + FLAC__STREAM_DECODER_INVALID_CALLBACK, + /**< FLAC__stream_decoder_init() was called without all callbacks being set. */ + + FLAC__STREAM_DECODER_UNINITIALIZED + /**< The decoder is in the uninitialized state. */ + +} 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[]; + + +/** 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 at the end of the stream. */ + + 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 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 in to the FLAC__StreamDecoder error callback. + */ +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__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. + * See FLAC__stream_decoder_set_read_callback() for more info. + * + * \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_set_client_data(). + * \retval FLAC__StreamDecoderReadStatus + * The callee's return status. + */ +typedef FLAC__StreamDecoderReadStatus (*FLAC__StreamDecoderReadCallback)(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data); + +/** Signature for the write callback. + * See FLAC__stream_decoder_set_write_callback() for more info. + * + * \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. + * Currently, the channel order has no meaning + * except for stereo streams; in this case channel + * 0 is left and 1 is right. + * \param client_data The callee's client data set through + * FLAC__stream_decoder_set_client_data(). + * \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. + * See FLAC__stream_decoder_set_metadata_callback() for more info. + * + * \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_set_client_data(). + */ +typedef void (*FLAC__StreamDecoderMetadataCallback)(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data); + +/** Signature for the error callback. + * See FLAC__stream_decoder_set_error_callback() for more info. + * + * \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_set_client_data(). + */ +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(); + +/** 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 read callback. + * 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. + * + * \note + * The callback is mandatory and must be set before initialization. + * + * \default \c NULL + * \param decoder A decoder instance to set. + * \param value See above. + * \assert + * \code decoder != NULL \endcode + * \code value != NULL \endcode + * \retval FLAC__bool + * \c false if the decoder is already initialized, else \c true. + */ +FLAC_API FLAC__bool FLAC__stream_decoder_set_read_callback(FLAC__StreamDecoder *decoder, FLAC__StreamDecoderReadCallback value); + +/** Set the write callback. + * The supplied function will be called when the decoder has decoded a + * single frame of data. The decoder will pass the frame metadata as + * well as an array of pointers (one for each channel) pointing to the + * decoded audio. + * + * \note + * The callback is mandatory and must be set before initialization. + * + * \default \c NULL + * \param decoder A decoder instance to set. + * \param value See above. + * \assert + * \code decoder != NULL \endcode + * \code value != NULL \endcode + * \retval FLAC__bool + * \c false if the decoder is already initialized, else \c true. + */ +FLAC_API FLAC__bool FLAC__stream_decoder_set_write_callback(FLAC__StreamDecoder *decoder, FLAC__StreamDecoderWriteCallback value); + +/** Set the metadata callback. + * The supplied function will be called when the decoder has decoded a metadata + * block. In a valid FLAC file there will always be one 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 STREAMINFO block; you can instruct + * the decoder to pass or filter other blocks with + * FLAC__stream_decoder_set_metadata_*() calls. + * + * \note + * The callback is mandatory and must be set before initialization. + * + * \default \c NULL + * \param decoder A decoder instance to set. + * \param value See above. + * \assert + * \code decoder != NULL \endcode + * \code value != 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_callback(FLAC__StreamDecoder *decoder, FLAC__StreamDecoderMetadataCallback value); + +/** Set the error callback. + * The supplied function will be called whenever an error occurs during + * decoding. + * + * \note + * The callback is mandatory and must be set before initialization. + * + * \default \c NULL + * \param decoder A decoder instance to set. + * \param value See above. + * \assert + * \code decoder != NULL \endcode + * \code value != NULL \endcode + * \retval FLAC__bool + * \c false if the decoder is already initialized, else \c true. + */ +FLAC_API FLAC__bool FLAC__stream_decoder_set_error_callback(FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorCallback value); + +/** Set the client data to be passed back to callbacks. + * This value will be supplied to callbacks in their \a client_data + * argument. + * + * \default \c NULL + * \param decoder A decoder instance to set. + * \param 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_client_data(FLAC__StreamDecoder *decoder, void *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 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); + +/** Initialize the decoder instance. + * 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. + * \assert + * \code decoder != NULL \endcode + * \retval FLAC__StreamDecoderState + * \c FLAC__STREAM_DECODER_SEARCH_FOR_METADATA if initialization was + * successful; see FLAC__StreamDecoderState for the meanings of other + * return values. + */ +FLAC_API FLAC__StreamDecoderState FLAC__stream_decoder_init(FLAC__StreamDecoder *decoder); + +/** 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 + */ +FLAC_API void 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. + * + * \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. + */ +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. + * + * \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. + */ +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 an error + * occurred. If the decoder loses sync it will call the error callback + * instead. + * + * 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 + * 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 read or write error occurred (except + * \c FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC), else \c true; + * in any case, check the decoder state with + * FLAC__stream_decoder_get_state() to see what went wrong or to + * check for lost synchronization (a sign of stream corruption). + */ +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. If the decoder loses sync it will call the + * error callback. + * + * \param decoder An initialized decoder instance. + * \assert + * \code decoder != NULL \endcode + * \retval FLAC__bool + * \c false if any read or write error occurred (except + * \c FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC), else \c true; + * in any case, check the decoder state with + * FLAC__stream_decoder_get_state() to see what went wrong or to + * check for lost synchronization (a sign of stream corruption). + */ +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. If the + * decoder loses sync it will call the error callback. + * + * \param decoder An initialized decoder instance. + * \assert + * \code decoder != NULL \endcode + * \retval FLAC__bool + * \c false if any read or write error occurred (except + * \c FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC), else \c true; + * in any case, check the decoder state with + * FLAC__stream_decoder_get_state() to see what went wrong or to + * check for lost synchronization (a sign of stream corruption). + */ +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, when used from the higher FLAC__SeekableStreamDecoder + * layer, can be used in more quickly determining FLAC frame boundaries + * when decoding of the actual data is not needed, for example when a + * application is separating a FLAC stream into frames for editing or + * storing in a container. To do this, the application can use + * FLAC__seekable_stream_decoder_skip_single_frame() to quickly advance + * to the next frame, then use + * FLAC__seekable_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 read or write error occurred (except + * \c FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC), or if the decoder + * is in the FLAC__STREAM_DECODER_SEARCH_FOR_METADATA or + * FLAC__STREAM_DECODER_READ_METADATA state, else \c true; + * in any case, check the decoder state with + * FLAC__stream_decoder_get_state() to see what went wrong or to + * check for lost synchronization (a sign of stream corruption). + */ +FLAC_API FLAC__bool FLAC__stream_decoder_skip_single_frame(FLAC__StreamDecoder *decoder); + +/* \} */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/FLAC/Makefile.mgw b/FLAC/Makefile.mgw new file mode 100644 index 00000000000..103847fa81a --- /dev/null +++ b/FLAC/Makefile.mgw @@ -0,0 +1,75 @@ +# Makefile for combined FLAC, FLAC++, derived from zlib's Makefile.mgw, +# which was itself derived from zlib's Makefile.dj2. +# Modified for mingw32 by C. Spieler, 6/16/98. +# Updated for zlib 1.2.x by Christian Spieler and Cosmin Truta, Mar-2003. +# Last updated: 1-Aug-2003. + +# Copyright (C) 1995-2003 Jean-loup Gailly. +# For conditions of distribution and use, see copyright notice in zlib.h + +STATICLIB = libflac.a + +#LOC = -DASMV +#LOC = -DDEBUG -g + +DEFINES = -D__MINW32__ -DWIN32 -DNDEBUG -D_LIB -DFLAC__CPU_IA32 -DFLAC_HAS_NASM -DFLAC__SSE_OS -DFLAC__USE_3DNOW -I. + +CCDV = @../ccdv +CC = gcc +CXX = g++ +CFLAGS = $(LOC) $(DEFINES) -O2 -Wall -fomit-frame-pointer +CXXFLAGS = $(LOC) $(DEFINES) -O2 -Wall + +NASM = nasmw +NASMFLAGS = -d OBJ_FORMAT_win32 -f win32 + +LD = $(CC) +LDFLAGS = $(LOC) -s + +AR = ar +ARFLAGS = rcs + +RC = windres +RCFLAGS = --define GCC_WINDRES + +OBJS = cpu_asm.o fixed_asm.o lpc_asm.o \ + bitbuffer.o bitmath.o cpu.o crc.o fixed.o format.o lpc.o memory.o stream_decoder.o stream_decoder_pp.o + +all: $(STATICLIB) + +test: example minigzip + ./example + echo hello world | minigzip | minigzip -d + +.c.o: + $(CCDV) $(CC) $(CFLAGS) -c -o $@ $< + +.cpp.o: + $(CCDV) $(CXX) $(CXXFLAGS) -c -o $@ $< + +$(STATICLIB): $(OBJS) + $(CCDV) $(AR) $(ARFLAGS) $@ $(OBJS) + + +.PHONY: clean + +clean: + -del /q /f $(STATICLIB) 2>nul + -del /q /f *.o 2>nul + +cpu_asm.o: ia32/cpu_asm.nasm + $(CCDV) $(NASM) -o $@ $(NASMFLAGS) $< +fixed_asm.o: ia32/fixed_asm.nasm + $(CCDV) $(NASM) -o $@ $(NASMFLAGS) $< +lpc_asm.o: ia32/lpc_asm.nasm + $(CCDV) $(NASM) -o $@ $(NASMFLAGS) $< +butbuffer.o: bitbuffer.c +bitmath.o: bitmath.c +cpu.o: cpu.c +crc.o: crc.c +fixed.o: fixed.c +format.o: format.c +lpc.o: lpc.c +memory.o: memory.c +stream_decoder.o: stream_decoder.c +stream_decoder_pp.o: stream_decoder_pp.cpp diff --git a/FLAC/ReadMe.txt b/FLAC/ReadMe.txt new file mode 100644 index 00000000000..6bc5f3e6136 --- /dev/null +++ b/FLAC/ReadMe.txt @@ -0,0 +1,6 @@ +This is not the complete FLAC distribution. It contains only what +ZDoom needs to decode compressed FLAC streams. For the complete +distribution, please visit . + +Of course, under Linux, you are encouraged to ignore this source +here and dynamically link to the full libraries. \ No newline at end of file diff --git a/FLAC/bitbuffer.c b/FLAC/bitbuffer.c new file mode 100644 index 00000000000..d31976a5114 --- /dev/null +++ b/FLAC/bitbuffer.c @@ -0,0 +1,2530 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2000,2001,2002,2003,2004 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. + */ + +#include /* for malloc() */ +#include /* for memcpy(), memset() */ +#include "private/bitbuffer.h" +#include "private/bitmath.h" +#include "private/crc.h" +#include "FLAC/assert.h" + +/* + * Along the way you will see two versions of some functions, selected + * by a FLAC__NO_MANUAL_INLINING macro. One is the simplified, more + * readable, and slow version, and the other is the same function + * where crucial parts have been manually inlined and are much faster. + * + */ + +/* + * This should be at least twice as large as the largest number of blurbs + * 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). + * + * The number we are actually using here is based on what would be the + * approximate maximum size of a verbatim frame at the default block size, + * for CD audio (4096 sample * 4 bytes per sample), plus some wiggle room. + * 32kbytes sounds reasonable. For kicks we subtract out 64 bytes for any + * alignment or malloc overhead. + * + * 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. + */ +static const unsigned FLAC__BITBUFFER_DEFAULT_CAPACITY = ((65536 - 64) * 8) / FLAC__BITS_PER_BLURB; /* blurbs */ + +#if FLAC__BITS_PER_BLURB == 8 +#define FLAC__BITS_PER_BLURB_LOG2 3 +#define FLAC__BYTES_PER_BLURB 1 +#define FLAC__BLURB_ALL_ONES ((FLAC__byte)0xff) +#define FLAC__BLURB_TOP_BIT_ONE ((FLAC__byte)0x80) +#define BLURB_BIT_TO_MASK(b) (((FLAC__blurb)'\x80') >> (b)) +#define CRC16_UPDATE_BLURB(bb, blurb, crc) FLAC__CRC16_UPDATE((blurb), (crc)); +#elif FLAC__BITS_PER_BLURB == 32 +#define FLAC__BITS_PER_BLURB_LOG2 5 +#define FLAC__BYTES_PER_BLURB 4 +#define FLAC__BLURB_ALL_ONES ((FLAC__uint32)0xffffffff) +#define FLAC__BLURB_TOP_BIT_ONE ((FLAC__uint32)0x80000000) +#define BLURB_BIT_TO_MASK(b) (((FLAC__blurb)0x80000000) >> (b)) +#define CRC16_UPDATE_BLURB(bb, blurb, crc) crc16_update_blurb((bb), (blurb)); +#else +/* ERROR, only sizes of 8 and 32 are supported */ +#endif + +#define FLAC__BLURBS_TO_BITS(blurbs) ((blurbs) << FLAC__BITS_PER_BLURB_LOG2) + +#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 + +struct FLAC__BitBuffer { + FLAC__blurb *buffer; + unsigned capacity; /* in blurbs */ + unsigned blurbs, bits; + unsigned total_bits; /* must always == FLAC__BITS_PER_BLURB*blurbs+bits */ + unsigned consumed_blurbs, consumed_bits; + unsigned total_consumed_bits; /* must always == FLAC__BITS_PER_BLURB*consumed_blurbs+consumed_bits */ + FLAC__uint16 read_crc16; +#if FLAC__BITS_PER_BLURB == 32 + unsigned crc16_align; +#endif + FLAC__blurb save_head, save_tail; +}; + +#if FLAC__BITS_PER_BLURB == 32 +static void crc16_update_blurb(FLAC__BitBuffer *bb, FLAC__blurb blurb) +{ + if(bb->crc16_align == 0) { + FLAC__CRC16_UPDATE(blurb >> 24, bb->read_crc16); + FLAC__CRC16_UPDATE((blurb >> 16) & 0xff, bb->read_crc16); + FLAC__CRC16_UPDATE((blurb >> 8) & 0xff, bb->read_crc16); + FLAC__CRC16_UPDATE(blurb & 0xff, bb->read_crc16); + } + else if(bb->crc16_align == 8) { + FLAC__CRC16_UPDATE((blurb >> 16) & 0xff, bb->read_crc16); + FLAC__CRC16_UPDATE((blurb >> 8) & 0xff, bb->read_crc16); + FLAC__CRC16_UPDATE(blurb & 0xff, bb->read_crc16); + } + else if(bb->crc16_align == 16) { + FLAC__CRC16_UPDATE((blurb >> 8) & 0xff, bb->read_crc16); + FLAC__CRC16_UPDATE(blurb & 0xff, bb->read_crc16); + } + else if(bb->crc16_align == 24) { + FLAC__CRC16_UPDATE(blurb & 0xff, bb->read_crc16); + } + bb->crc16_align = 0; +} +#endif + +/* + * WATCHOUT: The current implentation is not friendly to shrinking, i.e. it + * does not shift left what is consumed, it just chops off the end, whether + * there is unconsumed data there or not. This is OK because currently we + * never shrink the buffer, but if this ever changes, we'll have to do some + * fixups here. + */ +static FLAC__bool bitbuffer_resize_(FLAC__BitBuffer *bb, unsigned new_capacity) +{ + FLAC__blurb *new_buffer; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + + if(bb->capacity == new_capacity) + return true; + + new_buffer = (FLAC__blurb*)calloc(new_capacity, sizeof(FLAC__blurb)); + if(new_buffer == 0) + return false; + memcpy(new_buffer, bb->buffer, sizeof(FLAC__blurb)*min(bb->blurbs+(bb->bits?1:0), new_capacity)); + if(new_capacity < bb->blurbs+(bb->bits?1:0)) { + bb->blurbs = new_capacity; + bb->bits = 0; + bb->total_bits = FLAC__BLURBS_TO_BITS(new_capacity); + } + if(new_capacity < bb->consumed_blurbs+(bb->consumed_bits?1:0)) { + bb->consumed_blurbs = new_capacity; + bb->consumed_bits = 0; + bb->total_consumed_bits = FLAC__BLURBS_TO_BITS(new_capacity); + } + free(bb->buffer); /* we've already asserted above that (0 != bb->buffer) */ + bb->buffer = new_buffer; + bb->capacity = new_capacity; + return true; +} + +static FLAC__bool bitbuffer_grow_(FLAC__BitBuffer *bb, unsigned min_blurbs_to_add) +{ + unsigned new_capacity; + + FLAC__ASSERT(min_blurbs_to_add > 0); + + new_capacity = max(bb->capacity * 2, bb->capacity + min_blurbs_to_add); + return bitbuffer_resize_(bb, new_capacity); +} + +static FLAC__bool bitbuffer_ensure_size_(FLAC__BitBuffer *bb, unsigned bits_to_add) +{ + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + + if(FLAC__BLURBS_TO_BITS(bb->capacity) < bb->total_bits + bits_to_add) + return bitbuffer_grow_(bb, (bits_to_add >> FLAC__BITS_PER_BLURB_LOG2) + 2); + else + return true; +} + +static FLAC__bool bitbuffer_read_from_client_(FLAC__BitBuffer *bb, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) +{ + unsigned bytes; + FLAC__byte *target; + + /* first shift the unconsumed buffer data toward the front as much as possible */ + if(bb->total_consumed_bits >= FLAC__BITS_PER_BLURB) { + unsigned l = 0, r = bb->consumed_blurbs, r_end = bb->blurbs + (bb->bits? 1:0); + for( ; r < r_end; l++, r++) + bb->buffer[l] = bb->buffer[r]; + for( ; l < r_end; l++) + bb->buffer[l] = 0; + bb->blurbs -= bb->consumed_blurbs; + bb->total_bits -= FLAC__BLURBS_TO_BITS(bb->consumed_blurbs); + bb->consumed_blurbs = 0; + bb->total_consumed_bits = bb->consumed_bits; + } + + /* grow if we need to */ + if(bb->capacity <= 1) { + if(!bitbuffer_resize_(bb, 16)) + return false; + } + + /* set the target for reading, taking into account blurb alignment */ +#if FLAC__BITS_PER_BLURB == 8 + /* blurb == byte, so no gyrations necessary: */ + target = bb->buffer + bb->blurbs; + bytes = bb->capacity - bb->blurbs; +#elif FLAC__BITS_PER_BLURB == 32 + /* @@@ WATCHOUT: code currently only works for big-endian: */ + FLAC__ASSERT((bb->bits & 7) == 0); + target = (FLAC__byte*)(bb->buffer + bb->blurbs) + (bb->bits >> 3); + bytes = ((bb->capacity - bb->blurbs) << 2) - (bb->bits >> 3); /* i.e. (bb->capacity - bb->blurbs) * FLAC__BYTES_PER_BLURB - (bb->bits / 8) */ +#else + FLAC__ASSERT(false); /* ERROR, only sizes of 8 and 32 are supported */ +#endif + + /* finally, read in some data */ + if(!read_callback(target, &bytes, client_data)) + return false; + + /* now we have to handle partial blurb cases: */ +#if FLAC__BITS_PER_BLURB == 8 + /* blurb == byte, so no gyrations necessary: */ + bb->blurbs += bytes; + bb->total_bits += FLAC__BLURBS_TO_BITS(bytes); +#elif FLAC__BITS_PER_BLURB == 32 + /* @@@ WATCHOUT: code currently only works for big-endian: */ + { + const unsigned aligned_bytes = (bb->bits >> 3) + bytes; + bb->blurbs += (aligned_bytes >> 2); /* i.e. aligned_bytes / FLAC__BYTES_PER_BLURB */ + bb->bits = (aligned_bytes & 3u) << 3; /* i.e. (aligned_bytes % FLAC__BYTES_PER_BLURB) * 8 */ + bb->total_bits += (bytes << 3); + } +#else + FLAC__ASSERT(false); /* ERROR, only sizes of 8 and 32 are supported */ +#endif + return true; +} + +/*********************************************************************** + * + * Class constructor/destructor + * + ***********************************************************************/ + +FLAC__BitBuffer *FLAC__bitbuffer_new() +{ + FLAC__BitBuffer *bb = (FLAC__BitBuffer*)calloc(1, sizeof(FLAC__BitBuffer)); + + /* calloc() implies: + memset(bb, 0, sizeof(FLAC__BitBuffer)); + bb->buffer = 0; + bb->capacity = 0; + bb->blurbs = bb->bits = bb->total_bits = 0; + bb->consumed_blurbs = bb->consumed_bits = bb->total_consumed_bits = 0; + */ + return bb; +} + +void FLAC__bitbuffer_delete(FLAC__BitBuffer *bb) +{ + FLAC__ASSERT(0 != bb); + + FLAC__bitbuffer_free(bb); + free(bb); +} + +/*********************************************************************** + * + * Public class methods + * + ***********************************************************************/ + +FLAC__bool FLAC__bitbuffer_init(FLAC__BitBuffer *bb) +{ + FLAC__ASSERT(0 != bb); + + bb->buffer = 0; + bb->capacity = 0; + bb->blurbs = bb->bits = bb->total_bits = 0; + bb->consumed_blurbs = bb->consumed_bits = bb->total_consumed_bits = 0; + + return FLAC__bitbuffer_clear(bb); +} + +FLAC__bool FLAC__bitbuffer_init_from(FLAC__BitBuffer *bb, const FLAC__byte buffer[], unsigned bytes) +{ + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(bytes > 0); + + if(!FLAC__bitbuffer_init(bb)) + return false; + + if(!bitbuffer_ensure_size_(bb, bytes << 3)) + return false; + + FLAC__ASSERT(0 != buffer); + /* @@@ WATCHOUT: code currently only works for 8-bits-per-blurb inclusive-or big-endian: */ + memcpy((FLAC__byte*)bb->buffer, buffer, sizeof(FLAC__byte)*bytes); + bb->blurbs = bytes / FLAC__BYTES_PER_BLURB; + bb->bits = (bytes % FLAC__BYTES_PER_BLURB) << 3; + bb->total_bits = bytes << 3; + return true; +} + +FLAC__bool FLAC__bitbuffer_concatenate_aligned(FLAC__BitBuffer *dest, const FLAC__BitBuffer *src) +{ + unsigned bits_to_add = src->total_bits - src->total_consumed_bits; + + FLAC__ASSERT(0 != dest); + FLAC__ASSERT(0 != src); + + if(bits_to_add == 0) + return true; + if(dest->bits != src->consumed_bits) + return false; + if(!bitbuffer_ensure_size_(dest, bits_to_add)) + return false; + if(dest->bits == 0) { + memcpy(dest->buffer+dest->blurbs, src->buffer+src->consumed_blurbs, sizeof(FLAC__blurb)*(src->blurbs-src->consumed_blurbs + ((src->bits)? 1:0))); + } + else if(dest->bits + bits_to_add > FLAC__BITS_PER_BLURB) { + dest->buffer[dest->blurbs] <<= (FLAC__BITS_PER_BLURB - dest->bits); + dest->buffer[dest->blurbs] |= (src->buffer[src->consumed_blurbs] & ((1u << (FLAC__BITS_PER_BLURB-dest->bits)) - 1)); + memcpy(dest->buffer+dest->blurbs+1, src->buffer+src->consumed_blurbs+1, sizeof(FLAC__blurb)*(src->blurbs-src->consumed_blurbs-1 + ((src->bits)? 1:0))); + } + else { + dest->buffer[dest->blurbs] <<= bits_to_add; + dest->buffer[dest->blurbs] |= (src->buffer[src->consumed_blurbs] & ((1u << bits_to_add) - 1)); + } + dest->bits = src->bits; + dest->total_bits += bits_to_add; + dest->blurbs = dest->total_bits / FLAC__BITS_PER_BLURB; + + return true; +} + +void FLAC__bitbuffer_free(FLAC__BitBuffer *bb) +{ + FLAC__ASSERT(0 != bb); + + if(0 != bb->buffer) + free(bb->buffer); + bb->buffer = 0; + bb->capacity = 0; + bb->blurbs = bb->bits = bb->total_bits = 0; + bb->consumed_blurbs = bb->consumed_bits = bb->total_consumed_bits = 0; +} + +FLAC__bool FLAC__bitbuffer_clear(FLAC__BitBuffer *bb) +{ + if(bb->buffer == 0) { + bb->capacity = FLAC__BITBUFFER_DEFAULT_CAPACITY; + bb->buffer = (FLAC__blurb*)calloc(bb->capacity, sizeof(FLAC__blurb)); + if(bb->buffer == 0) + return false; + } + else { + memset(bb->buffer, 0, bb->blurbs + (bb->bits?1:0)); + } + bb->blurbs = bb->bits = bb->total_bits = 0; + bb->consumed_blurbs = bb->consumed_bits = bb->total_consumed_bits = 0; + return true; +} + +FLAC__bool FLAC__bitbuffer_clone(FLAC__BitBuffer *dest, const FLAC__BitBuffer *src) +{ + FLAC__ASSERT(0 != dest); + FLAC__ASSERT(0 != dest->buffer); + FLAC__ASSERT(0 != src); + FLAC__ASSERT(0 != src->buffer); + + if(dest->capacity < src->capacity) + if(!bitbuffer_resize_(dest, src->capacity)) + return false; + memcpy(dest->buffer, src->buffer, sizeof(FLAC__blurb)*min(src->capacity, src->blurbs+1)); + dest->blurbs = src->blurbs; + dest->bits = src->bits; + dest->total_bits = src->total_bits; + dest->consumed_blurbs = src->consumed_blurbs; + dest->consumed_bits = src->consumed_bits; + dest->total_consumed_bits = src->total_consumed_bits; + dest->read_crc16 = src->read_crc16; + return true; +} + +void FLAC__bitbuffer_reset_read_crc16(FLAC__BitBuffer *bb, FLAC__uint16 seed) +{ + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + FLAC__ASSERT((bb->consumed_bits & 7) == 0); + + bb->read_crc16 = seed; +#if FLAC__BITS_PER_BLURB == 8 + /* no need to do anything */ +#elif FLAC__BITS_PER_BLURB == 32 + bb->crc16_align = bb->consumed_bits; +#else + FLAC__ASSERT(false); /* ERROR, only sizes of 8 and 32 are supported */ +#endif +} + +FLAC__uint16 FLAC__bitbuffer_get_read_crc16(FLAC__BitBuffer *bb) +{ + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + FLAC__ASSERT((bb->bits & 7) == 0); + FLAC__ASSERT((bb->consumed_bits & 7) == 0); + +#if FLAC__BITS_PER_BLURB == 8 + /* no need to do anything */ +#elif FLAC__BITS_PER_BLURB == 32 + /*@@@ BUG: even though this probably can't happen with FLAC, need to fix the case where we are called here for the very first blurb and crc16_align is > 0 */ + if(bb->bits == 0 || bb->consumed_blurbs < bb->blurbs) { + if(bb->consumed_bits == 8) { + const FLAC__blurb blurb = bb->buffer[bb->consumed_blurbs]; + FLAC__CRC16_UPDATE(blurb >> 24, bb->read_crc16); + } + else if(bb->consumed_bits == 16) { + const FLAC__blurb blurb = bb->buffer[bb->consumed_blurbs]; + FLAC__CRC16_UPDATE(blurb >> 24, bb->read_crc16); + FLAC__CRC16_UPDATE((blurb >> 16) & 0xff, bb->read_crc16); + } + else if(bb->consumed_bits == 24) { + const FLAC__blurb blurb = bb->buffer[bb->consumed_blurbs]; + FLAC__CRC16_UPDATE(blurb >> 24, bb->read_crc16); + FLAC__CRC16_UPDATE((blurb >> 16) & 0xff, bb->read_crc16); + FLAC__CRC16_UPDATE((blurb >> 8) & 0xff, bb->read_crc16); + } + } + else { + if(bb->consumed_bits == 8) { + const FLAC__blurb blurb = bb->buffer[bb->consumed_blurbs]; + FLAC__CRC16_UPDATE(blurb >> (bb->bits-8), bb->read_crc16); + } + else if(bb->consumed_bits == 16) { + const FLAC__blurb blurb = bb->buffer[bb->consumed_blurbs]; + FLAC__CRC16_UPDATE(blurb >> (bb->bits-8), bb->read_crc16); + FLAC__CRC16_UPDATE((blurb >> (bb->bits-16)) & 0xff, bb->read_crc16); + } + else if(bb->consumed_bits == 24) { + const FLAC__blurb blurb = bb->buffer[bb->consumed_blurbs]; + FLAC__CRC16_UPDATE(blurb >> (bb->bits-8), bb->read_crc16); + FLAC__CRC16_UPDATE((blurb >> (bb->bits-16)) & 0xff, bb->read_crc16); + FLAC__CRC16_UPDATE((blurb >> (bb->bits-24)) & 0xff, bb->read_crc16); + } + } + bb->crc16_align = bb->consumed_bits; +#else + FLAC__ASSERT(false); /* ERROR, only sizes of 8 and 32 are supported */ +#endif + return bb->read_crc16; +} + +FLAC__uint16 FLAC__bitbuffer_get_write_crc16(const FLAC__BitBuffer *bb) +{ + FLAC__ASSERT((bb->bits & 7) == 0); /* assert that we're byte-aligned */ + +#if FLAC__BITS_PER_BLURB == 8 + return FLAC__crc16(bb->buffer, bb->blurbs); +#elif FLAC__BITS_PER_BLURB == 32 + /* @@@ WATCHOUT: code currently only works for big-endian: */ + return FLAC__crc16((FLAC__byte*)(bb->buffer), (bb->blurbs * FLAC__BYTES_PER_BLURB) + (bb->bits >> 3)); +#else + FLAC__ASSERT(false); /* ERROR, only sizes of 8 and 32 are supported */ +#endif +} + +FLAC__byte FLAC__bitbuffer_get_write_crc8(const FLAC__BitBuffer *bb) +{ + FLAC__ASSERT(0 != bb); + FLAC__ASSERT((bb->bits & 7) == 0); /* assert that we're byte-aligned */ + FLAC__ASSERT(bb->buffer[0] == 0xff); /* MAGIC NUMBER for the first byte of the sync code */ +#if FLAC__BITS_PER_BLURB == 8 + return FLAC__crc8(bb->buffer, bb->blurbs); +#elif FLAC__BITS_PER_BLURB == 32 + /* @@@ WATCHOUT: code currently only works for big-endian: */ + return FLAC__crc8((FLAC__byte*)(bb->buffer), (bb->blurbs * FLAC__BYTES_PER_BLURB) + (bb->bits >> 3)); +#else + FLAC__ASSERT(false); /* ERROR, only sizes of 8 and 32 are supported */ +#endif +} + +FLAC__bool FLAC__bitbuffer_is_byte_aligned(const FLAC__BitBuffer *bb) +{ + return ((bb->bits & 7) == 0); +} + +FLAC__bool FLAC__bitbuffer_is_consumed_byte_aligned(const FLAC__BitBuffer *bb) +{ + return ((bb->consumed_bits & 7) == 0); +} + +unsigned FLAC__bitbuffer_bits_left_for_byte_alignment(const FLAC__BitBuffer *bb) +{ + return 8 - (bb->consumed_bits & 7); +} + +unsigned FLAC__bitbuffer_get_input_bytes_unconsumed(const FLAC__BitBuffer *bb) +{ + FLAC__ASSERT((bb->consumed_bits & 7) == 0 && (bb->bits & 7) == 0); + return (bb->total_bits - bb->total_consumed_bits) >> 3; +} + +void FLAC__bitbuffer_get_buffer(FLAC__BitBuffer *bb, const FLAC__byte **buffer, unsigned *bytes) +{ + FLAC__ASSERT((bb->consumed_bits & 7) == 0 && (bb->bits & 7) == 0); +#if FLAC__BITS_PER_BLURB == 8 + *buffer = bb->buffer + bb->consumed_blurbs; + *bytes = bb->blurbs - bb->consumed_blurbs; +#elif FLAC__BITS_PER_BLURB == 32 + /* @@@ WATCHOUT: code currently only works for big-endian: */ + *buffer = (FLAC__byte*)(bb->buffer + bb->consumed_blurbs) + (bb->consumed_bits >> 3); + *bytes = (bb->total_bits - bb->total_consumed_bits) >> 3; +#else + FLAC__ASSERT(false); /* ERROR, only sizes of 8 and 32 are supported */ +#endif +} + +void FLAC__bitbuffer_release_buffer(FLAC__BitBuffer *bb) +{ +#if FLAC__BITS_PER_BLURB == 8 + (void)bb; +#elif FLAC__BITS_PER_BLURB == 32 + /* @@@ WATCHOUT: code currently only works for big-endian: */ + (void)bb; +#else + FLAC__ASSERT(false); /* ERROR, only sizes of 8 and 32 are supported */ +#endif +} + +FLAC__bool FLAC__bitbuffer_write_zeroes(FLAC__BitBuffer *bb, unsigned bits) +{ + unsigned n; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + + if(bits == 0) + return true; + if(!bitbuffer_ensure_size_(bb, bits)) + return false; + bb->total_bits += bits; + while(bits > 0) { + n = min(FLAC__BITS_PER_BLURB - bb->bits, bits); + bb->buffer[bb->blurbs] <<= n; + bits -= n; + bb->bits += n; + if(bb->bits == FLAC__BITS_PER_BLURB) { + bb->blurbs++; + bb->bits = 0; + } + } + return true; +} + +FLaC__INLINE FLAC__bool FLAC__bitbuffer_write_raw_uint32(FLAC__BitBuffer *bb, FLAC__uint32 val, unsigned bits) +{ + unsigned n, k; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + + FLAC__ASSERT(bits <= 32); + if(bits == 0) + return true; + /* inline the size check so we don't incure a function call unnecessarily */ + if(FLAC__BLURBS_TO_BITS(bb->capacity) < bb->total_bits + bits) { + if(!bitbuffer_ensure_size_(bb, bits)) + return false; + } + + /* zero-out unused bits; WATCHOUT: other code relies on this, so this needs to stay */ + if(bits < 32) /* @@@ gcc seems to require this because the following line causes incorrect results when bits==32; investigate */ + val &= (~(0xffffffff << bits)); /* zero-out unused bits */ + + bb->total_bits += bits; + while(bits > 0) { + n = FLAC__BITS_PER_BLURB - bb->bits; + if(n == FLAC__BITS_PER_BLURB) { /* i.e. bb->bits == 0 */ + if(bits < FLAC__BITS_PER_BLURB) { + bb->buffer[bb->blurbs] = (FLAC__blurb)val; + bb->bits = bits; + break; + } + else if(bits == FLAC__BITS_PER_BLURB) { + bb->buffer[bb->blurbs++] = (FLAC__blurb)val; + break; + } + else { + k = bits - FLAC__BITS_PER_BLURB; + bb->buffer[bb->blurbs++] = (FLAC__blurb)(val >> k); + /* we know k < 32 so no need to protect against the gcc bug mentioned above */ + val &= (~(0xffffffff << k)); + bits -= FLAC__BITS_PER_BLURB; + } + } + else if(bits <= n) { + bb->buffer[bb->blurbs] <<= bits; + bb->buffer[bb->blurbs] |= val; + if(bits == n) { + bb->blurbs++; + bb->bits = 0; + } + else + bb->bits += bits; + break; + } + else { + k = bits - n; + bb->buffer[bb->blurbs] <<= n; + bb->buffer[bb->blurbs] |= (val >> k); + /* we know n > 0 so k < 32 so no need to protect against the gcc bug mentioned above */ + val &= (~(0xffffffff << k)); + bits -= n; + bb->blurbs++; + bb->bits = 0; + } + } + + return true; +} + +FLAC__bool FLAC__bitbuffer_write_raw_int32(FLAC__BitBuffer *bb, FLAC__int32 val, unsigned bits) +{ + return FLAC__bitbuffer_write_raw_uint32(bb, (FLAC__uint32)val, bits); +} + +FLAC__bool FLAC__bitbuffer_write_raw_uint64(FLAC__BitBuffer *bb, FLAC__uint64 val, unsigned bits) +{ + static const FLAC__uint64 mask[] = { + 0, + FLAC__U64L(0x0000000000000001), FLAC__U64L(0x0000000000000003), FLAC__U64L(0x0000000000000007), FLAC__U64L(0x000000000000000F), + FLAC__U64L(0x000000000000001F), FLAC__U64L(0x000000000000003F), FLAC__U64L(0x000000000000007F), FLAC__U64L(0x00000000000000FF), + FLAC__U64L(0x00000000000001FF), FLAC__U64L(0x00000000000003FF), FLAC__U64L(0x00000000000007FF), FLAC__U64L(0x0000000000000FFF), + FLAC__U64L(0x0000000000001FFF), FLAC__U64L(0x0000000000003FFF), FLAC__U64L(0x0000000000007FFF), FLAC__U64L(0x000000000000FFFF), + FLAC__U64L(0x000000000001FFFF), FLAC__U64L(0x000000000003FFFF), FLAC__U64L(0x000000000007FFFF), FLAC__U64L(0x00000000000FFFFF), + FLAC__U64L(0x00000000001FFFFF), FLAC__U64L(0x00000000003FFFFF), FLAC__U64L(0x00000000007FFFFF), FLAC__U64L(0x0000000000FFFFFF), + FLAC__U64L(0x0000000001FFFFFF), FLAC__U64L(0x0000000003FFFFFF), FLAC__U64L(0x0000000007FFFFFF), FLAC__U64L(0x000000000FFFFFFF), + FLAC__U64L(0x000000001FFFFFFF), FLAC__U64L(0x000000003FFFFFFF), FLAC__U64L(0x000000007FFFFFFF), FLAC__U64L(0x00000000FFFFFFFF), + FLAC__U64L(0x00000001FFFFFFFF), FLAC__U64L(0x00000003FFFFFFFF), FLAC__U64L(0x00000007FFFFFFFF), FLAC__U64L(0x0000000FFFFFFFFF), + FLAC__U64L(0x0000001FFFFFFFFF), FLAC__U64L(0x0000003FFFFFFFFF), FLAC__U64L(0x0000007FFFFFFFFF), FLAC__U64L(0x000000FFFFFFFFFF), + FLAC__U64L(0x000001FFFFFFFFFF), FLAC__U64L(0x000003FFFFFFFFFF), FLAC__U64L(0x000007FFFFFFFFFF), FLAC__U64L(0x00000FFFFFFFFFFF), + FLAC__U64L(0x00001FFFFFFFFFFF), FLAC__U64L(0x00003FFFFFFFFFFF), FLAC__U64L(0x00007FFFFFFFFFFF), FLAC__U64L(0x0000FFFFFFFFFFFF), + FLAC__U64L(0x0001FFFFFFFFFFFF), FLAC__U64L(0x0003FFFFFFFFFFFF), FLAC__U64L(0x0007FFFFFFFFFFFF), FLAC__U64L(0x000FFFFFFFFFFFFF), + FLAC__U64L(0x001FFFFFFFFFFFFF), FLAC__U64L(0x003FFFFFFFFFFFFF), FLAC__U64L(0x007FFFFFFFFFFFFF), FLAC__U64L(0x00FFFFFFFFFFFFFF), + FLAC__U64L(0x01FFFFFFFFFFFFFF), FLAC__U64L(0x03FFFFFFFFFFFFFF), FLAC__U64L(0x07FFFFFFFFFFFFFF), FLAC__U64L(0x0FFFFFFFFFFFFFFF), + FLAC__U64L(0x1FFFFFFFFFFFFFFF), FLAC__U64L(0x3FFFFFFFFFFFFFFF), FLAC__U64L(0x7FFFFFFFFFFFFFFF), FLAC__U64L(0xFFFFFFFFFFFFFFFF) + }; + unsigned n, k; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + + FLAC__ASSERT(bits <= 64); + if(bits == 0) + return true; + if(!bitbuffer_ensure_size_(bb, bits)) + return false; + val &= mask[bits]; + bb->total_bits += bits; + while(bits > 0) { + if(bb->bits == 0) { + if(bits < FLAC__BITS_PER_BLURB) { + bb->buffer[bb->blurbs] = (FLAC__blurb)val; + bb->bits = bits; + break; + } + else if(bits == FLAC__BITS_PER_BLURB) { + bb->buffer[bb->blurbs++] = (FLAC__blurb)val; + break; + } + else { + k = bits - FLAC__BITS_PER_BLURB; + bb->buffer[bb->blurbs++] = (FLAC__blurb)(val >> k); + /* we know k < 64 so no need to protect against the gcc bug mentioned above */ + val &= (~(FLAC__U64L(0xffffffffffffffff) << k)); + bits -= FLAC__BITS_PER_BLURB; + } + } + else { + n = min(FLAC__BITS_PER_BLURB - bb->bits, bits); + k = bits - n; + bb->buffer[bb->blurbs] <<= n; + bb->buffer[bb->blurbs] |= (val >> k); + /* we know n > 0 so k < 64 so no need to protect against the gcc bug mentioned above */ + val &= (~(FLAC__U64L(0xffffffffffffffff) << k)); + bits -= n; + bb->bits += n; + if(bb->bits == FLAC__BITS_PER_BLURB) { + bb->blurbs++; + bb->bits = 0; + } + } + } + + return true; +} + +#if 0 /* UNUSED */ +FLAC__bool FLAC__bitbuffer_write_raw_int64(FLAC__BitBuffer *bb, FLAC__int64 val, unsigned bits) +{ + return FLAC__bitbuffer_write_raw_uint64(bb, (FLAC__uint64)val, bits); +} +#endif + +FLaC__INLINE FLAC__bool FLAC__bitbuffer_write_raw_uint32_little_endian(FLAC__BitBuffer *bb, FLAC__uint32 val) +{ + /* this doesn't need to be that fast as currently it is only used for vorbis comments */ + + /* NOTE: we rely on the fact that FLAC__bitbuffer_write_raw_uint32() masks out the unused bits */ + if(!FLAC__bitbuffer_write_raw_uint32(bb, val, 8)) + return false; + if(!FLAC__bitbuffer_write_raw_uint32(bb, val>>8, 8)) + return false; + if(!FLAC__bitbuffer_write_raw_uint32(bb, val>>16, 8)) + return false; + if(!FLAC__bitbuffer_write_raw_uint32(bb, val>>24, 8)) + return false; + + return true; +} + +FLaC__INLINE FLAC__bool FLAC__bitbuffer_write_byte_block(FLAC__BitBuffer *bb, const FLAC__byte vals[], unsigned nvals) +{ + unsigned i; + + /* this could be faster but currently we don't need it to be */ + for(i = 0; i < nvals; i++) { + if(!FLAC__bitbuffer_write_raw_uint32(bb, (FLAC__uint32)(vals[i]), 8)) + return false; + } + + return true; +} + +FLAC__bool FLAC__bitbuffer_write_unary_unsigned(FLAC__BitBuffer *bb, unsigned val) +{ + if(val < 32) + return FLAC__bitbuffer_write_raw_uint32(bb, 1, ++val); + else if(val < 64) + return FLAC__bitbuffer_write_raw_uint64(bb, 1, ++val); + else { + if(!FLAC__bitbuffer_write_zeroes(bb, val)) + return false; + return FLAC__bitbuffer_write_raw_uint32(bb, 1, 1); + } +} + +unsigned FLAC__bitbuffer_rice_bits(int val, unsigned parameter) +{ + unsigned msbs, uval; + + /* fold signed to unsigned */ + if(val < 0) + /* equivalent to + * (unsigned)(((--val) << 1) - 1); + * but without the overflow problem at MININT + */ + uval = (unsigned)(((-(++val)) << 1) + 1); + else + uval = (unsigned)(val << 1); + + msbs = uval >> parameter; + + return 1 + parameter + msbs; +} + +#if 0 /* UNUSED */ +unsigned FLAC__bitbuffer_golomb_bits_signed(int val, unsigned parameter) +{ + unsigned bits, msbs, uval; + unsigned k; + + FLAC__ASSERT(parameter > 0); + + /* fold signed to unsigned */ + if(val < 0) + /* equivalent to + * (unsigned)(((--val) << 1) - 1); + * but without the overflow problem at MININT + */ + 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__bitbuffer_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 */ + +#ifdef FLAC__SYMMETRIC_RICE +FLAC__bool FLAC__bitbuffer_write_symmetric_rice_signed(FLAC__BitBuffer *bb, int val, unsigned parameter) +{ + unsigned total_bits, interesting_bits, msbs; + FLAC__uint32 pattern; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + FLAC__ASSERT(parameter <= 31); + + /* init pattern with the unary end bit and the sign bit */ + if(val < 0) { + pattern = 3; + val = -val; + } + else + pattern = 2; + + msbs = val >> parameter; + interesting_bits = 2 + parameter; + total_bits = interesting_bits + msbs; + pattern <<= parameter; + pattern |= (val & ((1<buffer); + FLAC__ASSERT(parameter <= 31); + + *overflow = false; + + /* init pattern with the unary end bit and the sign bit */ + if(val < 0) { + pattern = 3; + val = -val; + } + else + pattern = 2; + + msbs = val >> parameter; + interesting_bits = 2 + parameter; + total_bits = interesting_bits + msbs; + pattern <<= parameter; + pattern |= (val & ((1< max_bits) { + *overflow = true; + return true; + } + else { + /* write the unary MSBs */ + if(!FLAC__bitbuffer_write_zeroes(bb, msbs)) + return false; + /* write the unary end bit, the sign bit, and binary LSBs */ + if(!FLAC__bitbuffer_write_raw_uint32(bb, pattern, interesting_bits)) + return false; + } + return true; +} +#endif /* UNUSED */ + +FLAC__bool FLAC__bitbuffer_write_symmetric_rice_signed_escape(FLAC__BitBuffer *bb, int val, unsigned parameter) +{ + unsigned total_bits, val_bits; + FLAC__uint32 pattern; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + FLAC__ASSERT(parameter <= 31); + + val_bits = FLAC__bitmath_silog2(val); + total_bits = 2 + parameter + 5 + val_bits; + + if(total_bits <= 32) { + pattern = 3; + pattern <<= (parameter + 5); + pattern |= val_bits; + pattern <<= val_bits; + pattern |= (val & ((1 << val_bits) - 1)); + if(!FLAC__bitbuffer_write_raw_uint32(bb, pattern, total_bits)) + return false; + } + else { + /* write the '-0' escape code first */ + if(!FLAC__bitbuffer_write_raw_uint32(bb, 3u << parameter, 2+parameter)) + return false; + /* write the length */ + if(!FLAC__bitbuffer_write_raw_uint32(bb, val_bits, 5)) + return false; + /* write the value */ + if(!FLAC__bitbuffer_write_raw_int32(bb, val, val_bits)) + return false; + } + return true; +} +#endif /* ifdef FLAC__SYMMETRIC_RICE */ + +FLAC__bool FLAC__bitbuffer_write_rice_signed(FLAC__BitBuffer *bb, int val, unsigned parameter) +{ + unsigned total_bits, interesting_bits, msbs, uval; + FLAC__uint32 pattern; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + FLAC__ASSERT(parameter <= 30); + + /* fold signed to unsigned */ + if(val < 0) + /* equivalent to + * (unsigned)(((--val) << 1) - 1); + * but without the overflow problem at MININT + */ + uval = (unsigned)(((-(++val)) << 1) + 1); + else + uval = (unsigned)(val << 1); + + msbs = uval >> parameter; + interesting_bits = 1 + parameter; + total_bits = interesting_bits + msbs; + pattern = 1 << parameter; /* the unary end bit */ + pattern |= (uval & ((1<buffer); + FLAC__ASSERT(parameter <= 30); + + *overflow = false; + + /* fold signed to unsigned */ + if(val < 0) + /* equivalent to + * (unsigned)(((--val) << 1) - 1); + * but without the overflow problem at MININT + */ + uval = (unsigned)(((-(++val)) << 1) + 1); + else + uval = (unsigned)(val << 1); + + msbs = uval >> parameter; + interesting_bits = 1 + parameter; + total_bits = interesting_bits + msbs; + pattern = 1 << parameter; /* the unary end bit */ + pattern |= (uval & ((1< max_bits) { + *overflow = true; + return true; + } + else { + /* write the unary MSBs */ + if(!FLAC__bitbuffer_write_zeroes(bb, msbs)) + return false; + /* write the unary end bit and binary LSBs */ + if(!FLAC__bitbuffer_write_raw_uint32(bb, pattern, interesting_bits)) + return false; + } + return true; +} +#endif /* UNUSED */ + +#if 0 /* UNUSED */ +FLAC__bool FLAC__bitbuffer_write_golomb_signed(FLAC__BitBuffer *bb, int val, unsigned parameter) +{ + unsigned total_bits, msbs, uval; + unsigned k; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + FLAC__ASSERT(parameter > 0); + + /* fold signed to unsigned */ + if(val < 0) + /* equivalent to + * (unsigned)(((--val) << 1) - 1); + * but without the overflow problem at MININT + */ + 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__bitbuffer_write_raw_uint32(bb, r+d, k+1)) + return false; + } + else { + if(!FLAC__bitbuffer_write_raw_uint32(bb, r, k)) + return false; + } + } + return true; +} + +FLAC__bool FLAC__bitbuffer_write_golomb_unsigned(FLAC__BitBuffer *bb, unsigned uval, unsigned parameter) +{ + unsigned total_bits, msbs; + unsigned k; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->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__bitbuffer_write_raw_uint32(bb, r+d, k+1)) + return false; + } + else { + if(!FLAC__bitbuffer_write_raw_uint32(bb, r, k)) + return false; + } + } + return true; +} +#endif /* UNUSED */ + +FLAC__bool FLAC__bitbuffer_write_utf8_uint32(FLAC__BitBuffer *bb, FLAC__uint32 val) +{ + FLAC__bool ok = 1; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + + FLAC__ASSERT(!(val & 0x80000000)); /* this version only handles 31 bits */ + + if(val < 0x80) { + return FLAC__bitbuffer_write_raw_uint32(bb, val, 8); + } + else if(val < 0x800) { + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0xC0 | (val>>6), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (val&0x3F), 8); + } + else if(val < 0x10000) { + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0xE0 | (val>>12), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | ((val>>6)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (val&0x3F), 8); + } + else if(val < 0x200000) { + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0xF0 | (val>>18), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | ((val>>12)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | ((val>>6)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (val&0x3F), 8); + } + else if(val < 0x4000000) { + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0xF8 | (val>>24), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | ((val>>18)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | ((val>>12)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | ((val>>6)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (val&0x3F), 8); + } + else { + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0xFC | (val>>30), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | ((val>>24)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | ((val>>18)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | ((val>>12)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | ((val>>6)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (val&0x3F), 8); + } + + return ok; +} + +FLAC__bool FLAC__bitbuffer_write_utf8_uint64(FLAC__BitBuffer *bb, FLAC__uint64 val) +{ + FLAC__bool ok = 1; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + + FLAC__ASSERT(!(val & FLAC__U64L(0xFFFFFFF000000000))); /* this version only handles 36 bits */ + + if(val < 0x80) { + return FLAC__bitbuffer_write_raw_uint32(bb, (FLAC__uint32)val, 8); + } + else if(val < 0x800) { + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0xC0 | (FLAC__uint32)(val>>6), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)(val&0x3F), 8); + } + else if(val < 0x10000) { + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0xE0 | (FLAC__uint32)(val>>12), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)((val>>6)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)(val&0x3F), 8); + } + else if(val < 0x200000) { + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0xF0 | (FLAC__uint32)(val>>18), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)((val>>12)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)((val>>6)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)(val&0x3F), 8); + } + else if(val < 0x4000000) { + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0xF8 | (FLAC__uint32)(val>>24), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)((val>>18)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)((val>>12)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)((val>>6)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)(val&0x3F), 8); + } + else if(val < 0x80000000) { + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0xFC | (FLAC__uint32)(val>>30), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)((val>>24)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)((val>>18)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)((val>>12)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)((val>>6)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)(val&0x3F), 8); + } + else { + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0xFE, 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)((val>>30)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)((val>>24)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)((val>>18)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)((val>>12)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)((val>>6)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)(val&0x3F), 8); + } + + return ok; +} + +FLAC__bool FLAC__bitbuffer_zero_pad_to_byte_boundary(FLAC__BitBuffer *bb) +{ + /* 0-pad to byte boundary */ + if(bb->bits & 7u) + return FLAC__bitbuffer_write_zeroes(bb, 8 - (bb->bits & 7u)); + else + return true; +} + +FLAC__bool FLAC__bitbuffer_peek_bit(FLAC__BitBuffer *bb, unsigned *val, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) +{ + /* to avoid a drastic speed penalty we don't: + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + FLAC__ASSERT(bb->bits == 0); + */ + + while(1) { + if(bb->total_consumed_bits < bb->total_bits) { + *val = (bb->buffer[bb->consumed_blurbs] & BLURB_BIT_TO_MASK(bb->consumed_bits))? 1 : 0; + return true; + } + else { + if(!bitbuffer_read_from_client_(bb, read_callback, client_data)) + return false; + } + } +} + +FLAC__bool FLAC__bitbuffer_read_bit(FLAC__BitBuffer *bb, unsigned *val, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) +{ + /* to avoid a drastic speed penalty we don't: + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + FLAC__ASSERT(bb->bits == 0); + */ + + while(1) { + if(bb->total_consumed_bits < bb->total_bits) { + *val = (bb->buffer[bb->consumed_blurbs] & BLURB_BIT_TO_MASK(bb->consumed_bits))? 1 : 0; + bb->consumed_bits++; + if(bb->consumed_bits == FLAC__BITS_PER_BLURB) { + CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16); + bb->consumed_blurbs++; + bb->consumed_bits = 0; + } + bb->total_consumed_bits++; + return true; + } + else { + if(!bitbuffer_read_from_client_(bb, read_callback, client_data)) + return false; + } + } +} + +FLAC__bool FLAC__bitbuffer_read_bit_to_uint32(FLAC__BitBuffer *bb, FLAC__uint32 *val, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) +{ + /* to avoid a drastic speed penalty we don't: + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + FLAC__ASSERT(bb->bits == 0); + */ + + while(1) { + if(bb->total_consumed_bits < bb->total_bits) { + *val <<= 1; + *val |= (bb->buffer[bb->consumed_blurbs] & BLURB_BIT_TO_MASK(bb->consumed_bits))? 1 : 0; + bb->consumed_bits++; + if(bb->consumed_bits == FLAC__BITS_PER_BLURB) { + CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16); + bb->consumed_blurbs++; + bb->consumed_bits = 0; + } + bb->total_consumed_bits++; + return true; + } + else { + if(!bitbuffer_read_from_client_(bb, read_callback, client_data)) + return false; + } + } +} + +FLAC__bool FLAC__bitbuffer_read_bit_to_uint64(FLAC__BitBuffer *bb, FLAC__uint64 *val, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) +{ + /* to avoid a drastic speed penalty we don't: + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + FLAC__ASSERT(bb->bits == 0); + */ + + while(1) { + if(bb->total_consumed_bits < bb->total_bits) { + *val <<= 1; + *val |= (bb->buffer[bb->consumed_blurbs] & BLURB_BIT_TO_MASK(bb->consumed_bits))? 1 : 0; + bb->consumed_bits++; + if(bb->consumed_bits == FLAC__BITS_PER_BLURB) { + CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16); + bb->consumed_blurbs++; + bb->consumed_bits = 0; + } + bb->total_consumed_bits++; + return true; + } + else { + if(!bitbuffer_read_from_client_(bb, read_callback, client_data)) + return false; + } + } +} + +FLaC__INLINE FLAC__bool FLAC__bitbuffer_read_raw_uint32(FLAC__BitBuffer *bb, FLAC__uint32 *val, const unsigned bits, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) +#ifdef FLAC__NO_MANUAL_INLINING +{ + unsigned i; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + + FLAC__ASSERT(bits <= 32); + + *val = 0; + for(i = 0; i < bits; i++) { + if(!FLAC__bitbuffer_read_bit_to_uint32(bb, val, read_callback, client_data)) + return false; + } + return true; +} +#else +{ + unsigned i, bits_ = bits; + FLAC__uint32 v = 0; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + + FLAC__ASSERT(bits <= 32); + FLAC__ASSERT((bb->capacity*FLAC__BITS_PER_BLURB) * 2 >= bits); + + if(bits == 0) { + *val = 0; + return true; + } + + while(bb->total_consumed_bits + bits > bb->total_bits) { + if(!bitbuffer_read_from_client_(bb, read_callback, client_data)) + return false; + } +#if FLAC__BITS_PER_BLURB > 8 + if(bb->bits == 0 || bb->consumed_blurbs < bb->blurbs) { /*@@@ comment on why this is here*/ +#endif + if(bb->consumed_bits) { + i = FLAC__BITS_PER_BLURB - bb->consumed_bits; + if(i <= bits_) { + v = bb->buffer[bb->consumed_blurbs] & (FLAC__BLURB_ALL_ONES >> bb->consumed_bits); + bits_ -= i; + CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16); + bb->consumed_blurbs++; + bb->consumed_bits = 0; + /* we hold off updating bb->total_consumed_bits until the end */ + } + else { + *val = (bb->buffer[bb->consumed_blurbs] & (FLAC__BLURB_ALL_ONES >> bb->consumed_bits)) >> (i-bits_); + bb->consumed_bits += bits_; + bb->total_consumed_bits += bits_; + return true; + } + } +#if FLAC__BITS_PER_BLURB == 32 + /* note that we know bits_ cannot be > 32 because of previous assertions */ + if(bits_ == FLAC__BITS_PER_BLURB) { + v = bb->buffer[bb->consumed_blurbs]; + CRC16_UPDATE_BLURB(bb, v, bb->read_crc16); + bb->consumed_blurbs++; + /* bb->consumed_bits is already 0 */ + bb->total_consumed_bits += bits; + *val = v; + return true; + } +#else + while(bits_ >= FLAC__BITS_PER_BLURB) { + v <<= FLAC__BITS_PER_BLURB; + v |= bb->buffer[bb->consumed_blurbs]; + bits_ -= FLAC__BITS_PER_BLURB; + CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16); + bb->consumed_blurbs++; + /* bb->consumed_bits is already 0 */ + /* we hold off updating bb->total_consumed_bits until the end */ + } +#endif + if(bits_ > 0) { + v <<= bits_; + v |= (bb->buffer[bb->consumed_blurbs] >> (FLAC__BITS_PER_BLURB-bits_)); + bb->consumed_bits = bits_; + /* we hold off updating bb->total_consumed_bits until the end */ + } + bb->total_consumed_bits += bits; + *val = v; +#if FLAC__BITS_PER_BLURB > 8 + } + else { + *val = 0; + for(i = 0; i < bits; i++) { + if(!FLAC__bitbuffer_read_bit_to_uint32(bb, val, read_callback, client_data)) + return false; + } + } +#endif + return true; +} +#endif + +FLAC__bool FLAC__bitbuffer_read_raw_int32(FLAC__BitBuffer *bb, FLAC__int32 *val, const unsigned bits, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) +#ifdef FLAC__NO_MANUAL_INLINING +{ + unsigned i; + FLAC__uint32 v; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + + FLAC__ASSERT(bits <= 32); + + if(bits == 0) { + *val = 0; + return true; + } + + v = 0; + for(i = 0; i < bits; i++) { + if(!FLAC__bitbuffer_read_bit_to_uint32(bb, &v, read_callback, client_data)) + return false; + } + + /* fix the sign */ + i = 32 - bits; + if(i) { + v <<= i; + *val = (FLAC__int32)v; + *val >>= i; + } + else + *val = (FLAC__int32)v; + + return true; +} +#else +{ + unsigned i, bits_ = bits; + FLAC__uint32 v = 0; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + + FLAC__ASSERT(bits <= 32); + FLAC__ASSERT((bb->capacity*FLAC__BITS_PER_BLURB) * 2 >= bits); + + if(bits == 0) { + *val = 0; + return true; + } + + while(bb->total_consumed_bits + bits > bb->total_bits) { + if(!bitbuffer_read_from_client_(bb, read_callback, client_data)) + return false; + } +#if FLAC__BITS_PER_BLURB > 8 + if(bb->bits == 0 || bb->consumed_blurbs < bb->blurbs) { /*@@@ comment on why this is here*/ +#endif + if(bb->consumed_bits) { + i = FLAC__BITS_PER_BLURB - bb->consumed_bits; + if(i <= bits_) { + v = bb->buffer[bb->consumed_blurbs] & (FLAC__BLURB_ALL_ONES >> bb->consumed_bits); + bits_ -= i; + CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16); + bb->consumed_blurbs++; + bb->consumed_bits = 0; + /* we hold off updating bb->total_consumed_bits until the end */ + } + else { + /* bits_ must be < FLAC__BITS_PER_BLURB-1 if we get to here */ + v = (bb->buffer[bb->consumed_blurbs] & (FLAC__BLURB_ALL_ONES >> bb->consumed_bits)); + v <<= (32-i); + *val = (FLAC__int32)v; + *val >>= (32-bits_); + bb->consumed_bits += bits_; + bb->total_consumed_bits += bits_; + return true; + } + } +#if FLAC__BITS_PER_BLURB == 32 + /* note that we know bits_ cannot be > 32 because of previous assertions */ + if(bits_ == FLAC__BITS_PER_BLURB) { + v = bb->buffer[bb->consumed_blurbs]; + bits_ = 0; + CRC16_UPDATE_BLURB(bb, v, bb->read_crc16); + bb->consumed_blurbs++; + /* bb->consumed_bits is already 0 */ + /* we hold off updating bb->total_consumed_bits until the end */ + } +#else + while(bits_ >= FLAC__BITS_PER_BLURB) { + v <<= FLAC__BITS_PER_BLURB; + v |= bb->buffer[bb->consumed_blurbs]; + bits_ -= FLAC__BITS_PER_BLURB; + CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16); + bb->consumed_blurbs++; + /* bb->consumed_bits is already 0 */ + /* we hold off updating bb->total_consumed_bits until the end */ + } +#endif + if(bits_ > 0) { + v <<= bits_; + v |= (bb->buffer[bb->consumed_blurbs] >> (FLAC__BITS_PER_BLURB-bits_)); + bb->consumed_bits = bits_; + /* we hold off updating bb->total_consumed_bits until the end */ + } + bb->total_consumed_bits += bits; +#if FLAC__BITS_PER_BLURB > 8 + } + else { + for(i = 0; i < bits; i++) { + if(!FLAC__bitbuffer_read_bit_to_uint32(bb, &v, read_callback, client_data)) + return false; + } + } +#endif + + /* fix the sign */ + i = 32 - bits; + if(i) { + v <<= i; + *val = (FLAC__int32)v; + *val >>= i; + } + else + *val = (FLAC__int32)v; + + return true; +} +#endif + +FLAC__bool FLAC__bitbuffer_read_raw_uint64(FLAC__BitBuffer *bb, FLAC__uint64 *val, const unsigned bits, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) +#ifdef FLAC__NO_MANUAL_INLINING +{ + unsigned i; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + + FLAC__ASSERT(bits <= 64); + + *val = 0; + for(i = 0; i < bits; i++) { + if(!FLAC__bitbuffer_read_bit_to_uint64(bb, val, read_callback, client_data)) + return false; + } + return true; +} +#else +{ + unsigned i, bits_ = bits; + FLAC__uint64 v = 0; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + + FLAC__ASSERT(bits <= 64); + FLAC__ASSERT((bb->capacity*FLAC__BITS_PER_BLURB) * 2 >= bits); + + if(bits == 0) { + *val = 0; + return true; + } + + while(bb->total_consumed_bits + bits > bb->total_bits) { + if(!bitbuffer_read_from_client_(bb, read_callback, client_data)) + return false; + } +#if FLAC__BITS_PER_BLURB > 8 + if(bb->bits == 0 || bb->consumed_blurbs < bb->blurbs) { /*@@@ comment on why this is here*/ +#endif + if(bb->consumed_bits) { + i = FLAC__BITS_PER_BLURB - bb->consumed_bits; + if(i <= bits_) { + v = bb->buffer[bb->consumed_blurbs] & (FLAC__BLURB_ALL_ONES >> bb->consumed_bits); + bits_ -= i; + CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16); + bb->consumed_blurbs++; + bb->consumed_bits = 0; + /* we hold off updating bb->total_consumed_bits until the end */ + } + else { + *val = (bb->buffer[bb->consumed_blurbs] & (FLAC__BLURB_ALL_ONES >> bb->consumed_bits)) >> (i-bits_); + bb->consumed_bits += bits_; + bb->total_consumed_bits += bits_; + return true; + } + } + while(bits_ >= FLAC__BITS_PER_BLURB) { + v <<= FLAC__BITS_PER_BLURB; + v |= bb->buffer[bb->consumed_blurbs]; + bits_ -= FLAC__BITS_PER_BLURB; + CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16); + bb->consumed_blurbs++; + /* bb->consumed_bits is already 0 */ + /* we hold off updating bb->total_consumed_bits until the end */ + } + if(bits_ > 0) { + v <<= bits_; + v |= (bb->buffer[bb->consumed_blurbs] >> (FLAC__BITS_PER_BLURB-bits_)); + bb->consumed_bits = bits_; + /* we hold off updating bb->total_consumed_bits until the end */ + } + bb->total_consumed_bits += bits; + *val = v; +#if FLAC__BITS_PER_BLURB > 8 + } + else { + *val = 0; + for(i = 0; i < bits; i++) { + if(!FLAC__bitbuffer_read_bit_to_uint64(bb, val, read_callback, client_data)) + return false; + } + } +#endif + return true; +} +#endif + +#if 0 /* UNUSED */ +FLAC__bool FLAC__bitbuffer_read_raw_int64(FLAC__BitBuffer *bb, FLAC__int64 *val, const unsigned bits, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) +#ifdef FLAC__NO_MANUAL_INLINING +{ + unsigned i; + FLAC__uint64 v; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + + FLAC__ASSERT(bits <= 64); + + v = 0; + for(i = 0; i < bits; i++) { + if(!FLAC__bitbuffer_read_bit_to_uint64(bb, &v, read_callback, client_data)) + return false; + } + /* fix the sign */ + i = 64 - bits; + if(i) { + v <<= i; + *val = (FLAC__int64)v; + *val >>= i; + } + else + *val = (FLAC__int64)v; + + return true; +} +#else +{ + unsigned i, bits_ = bits; + FLAC__uint64 v = 0; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + + FLAC__ASSERT(bits <= 64); + FLAC__ASSERT((bb->capacity*FLAC__BITS_PER_BLURB) * 2 >= bits); + + if(bits == 0) { + *val = 0; + return true; + } + + while(bb->total_consumed_bits + bits > bb->total_bits) { + if(!bitbuffer_read_from_client_(bb, read_callback, client_data)) + return false; + } +#if FLAC__BITS_PER_BLURB > 8 + if(bb->bits == 0 || bb->consumed_blurbs < bb->blurbs) { /*@@@ comment on why this is here*/ +#endif + if(bb->consumed_bits) { + i = FLAC__BITS_PER_BLURB - bb->consumed_bits; + if(i <= bits_) { + v = bb->buffer[bb->consumed_blurbs] & (FLAC__BLURB_ALL_ONES >> bb->consumed_bits); + bits_ -= i; + CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16); + bb->consumed_blurbs++; + bb->consumed_bits = 0; + /* we hold off updating bb->total_consumed_bits until the end */ + } + else { + /* bits_ must be < FLAC__BITS_PER_BLURB-1 if we get to here */ + v = (bb->buffer[bb->consumed_blurbs] & (FLAC__BLURB_ALL_ONES >> bb->consumed_bits)); + v <<= (64-i); + *val = (FLAC__int64)v; + *val >>= (64-bits_); + bb->consumed_bits += bits_; + bb->total_consumed_bits += bits_; + return true; + } + } + while(bits_ >= FLAC__BITS_PER_BLURB) { + v <<= FLAC__BITS_PER_BLURB; + v |= bb->buffer[bb->consumed_blurbs]; + bits_ -= FLAC__BITS_PER_BLURB; + CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16); + bb->consumed_blurbs++; + /* bb->consumed_bits is already 0 */ + /* we hold off updating bb->total_consumed_bits until the end */ + } + if(bits_ > 0) { + v <<= bits_; + v |= (bb->buffer[bb->consumed_blurbs] >> (FLAC__BITS_PER_BLURB-bits_)); + bb->consumed_bits = bits_; + /* we hold off updating bb->total_consumed_bits until the end */ + } + bb->total_consumed_bits += bits; +#if FLAC__BITS_PER_BLURB > 8 + } + else { + for(i = 0; i < bits; i++) { + if(!FLAC__bitbuffer_read_bit_to_uint64(bb, &v, read_callback, client_data)) + return false; + } + } +#endif + + /* fix the sign */ + i = 64 - bits; + if(i) { + v <<= i; + *val = (FLAC__int64)v; + *val >>= i; + } + else + *val = (FLAC__int64)v; + + return true; +} +#endif +#endif + +FLaC__INLINE FLAC__bool FLAC__bitbuffer_read_raw_uint32_little_endian(FLAC__BitBuffer *bb, FLAC__uint32 *val, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) +{ + FLAC__uint32 x8, x32 = 0; + + /* this doesn't need to be that fast as currently it is only used for vorbis comments */ + + if(!FLAC__bitbuffer_read_raw_uint32(bb, &x32, 8, read_callback, client_data)) + return false; + + if(!FLAC__bitbuffer_read_raw_uint32(bb, &x8, 8, read_callback, client_data)) + return false; + x32 |= (x8 << 8); + + if(!FLAC__bitbuffer_read_raw_uint32(bb, &x8, 8, read_callback, client_data)) + return false; + x32 |= (x8 << 16); + + if(!FLAC__bitbuffer_read_raw_uint32(bb, &x8, 8, read_callback, client_data)) + return false; + x32 |= (x8 << 24); + + *val = x32; + return true; +} + +FLAC__bool FLAC__bitbuffer_skip_bits_no_crc(FLAC__BitBuffer *bb, unsigned bits, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) +{ + /* + * @@@ a slightly 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 != bb); + FLAC__ASSERT(0 != bb->buffer); + + if(bits > 0) { + const unsigned n = bb->consumed_bits & 7; + unsigned m; + FLAC__uint32 x; + + if(n != 0) { + m = min(8-n, bits); + if(!FLAC__bitbuffer_read_raw_uint32(bb, &x, m, read_callback, client_data)) + return false; + bits -= m; + } + m = bits / 8; + if(m > 0) { + if(!FLAC__bitbuffer_read_byte_block_aligned_no_crc(bb, 0, m, read_callback, client_data)) + return false; + bits %= 8; + } + if(bits > 0) { + if(!FLAC__bitbuffer_read_raw_uint32(bb, &x, bits, read_callback, client_data)) + return false; + } + } + + return true; +} + +FLAC__bool FLAC__bitbuffer_read_byte_block_aligned_no_crc(FLAC__BitBuffer *bb, FLAC__byte *val, unsigned nvals, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) +{ + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + FLAC__ASSERT(FLAC__bitbuffer_is_byte_aligned(bb)); + FLAC__ASSERT(FLAC__bitbuffer_is_consumed_byte_aligned(bb)); +#if FLAC__BITS_PER_BLURB == 8 + while(nvals > 0) { + unsigned chunk = min(nvals, bb->blurbs - bb->consumed_blurbs); + if(chunk == 0) { + if(!bitbuffer_read_from_client_(bb, read_callback, client_data)) + return false; + } + else { + if(0 != val) { + memcpy(val, bb->buffer + bb->consumed_blurbs, FLAC__BYTES_PER_BLURB * chunk); + val += FLAC__BYTES_PER_BLURB * chunk; + } + nvals -= chunk; + bb->consumed_blurbs += chunk; + bb->total_consumed_bits = (bb->consumed_blurbs << FLAC__BITS_PER_BLURB_LOG2); + } + } +#else + @@@ need to write this still + FLAC__ASSERT(0); +#endif + + return true; +} + +FLaC__INLINE FLAC__bool FLAC__bitbuffer_read_unary_unsigned(FLAC__BitBuffer *bb, unsigned *val, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) +#ifdef FLAC__NO_MANUAL_INLINING +{ + unsigned bit, val_ = 0; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + + while(1) { + if(!FLAC__bitbuffer_read_bit(bb, &bit, read_callback, client_data)) + return false; + if(bit) + break; + else + val_++; + } + *val = val_; + return true; +} +#else +{ + unsigned i, val_ = 0; + unsigned total_blurbs_ = (bb->total_bits + (FLAC__BITS_PER_BLURB-1)) / FLAC__BITS_PER_BLURB; + FLAC__blurb b; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + +#if FLAC__BITS_PER_BLURB > 8 + if(bb->bits == 0 || bb->consumed_blurbs < bb->blurbs) { /*@@@ comment on why this is here*/ +#endif + if(bb->consumed_bits) { + b = bb->buffer[bb->consumed_blurbs] << bb->consumed_bits; + if(b) { + for(i = 0; !(b & FLAC__BLURB_TOP_BIT_ONE); i++) + b <<= 1; + *val = i; + i++; + bb->consumed_bits += i; + bb->total_consumed_bits += i; + if(bb->consumed_bits == FLAC__BITS_PER_BLURB) { + CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16); + bb->consumed_blurbs++; + bb->consumed_bits = 0; + } + return true; + } + else { + val_ = FLAC__BITS_PER_BLURB - bb->consumed_bits; + CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16); + bb->consumed_blurbs++; + bb->consumed_bits = 0; + bb->total_consumed_bits += val_; + } + } + while(1) { + if(bb->consumed_blurbs >= total_blurbs_) { + if(!bitbuffer_read_from_client_(bb, read_callback, client_data)) + return false; + total_blurbs_ = (bb->total_bits + (FLAC__BITS_PER_BLURB-1)) / FLAC__BITS_PER_BLURB; + } + b = bb->buffer[bb->consumed_blurbs]; + if(b) { + for(i = 0; !(b & FLAC__BLURB_TOP_BIT_ONE); i++) + b <<= 1; + val_ += i; + i++; + bb->consumed_bits = i; + *val = val_; + if(i == FLAC__BITS_PER_BLURB) { + CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16); + bb->consumed_blurbs++; + bb->consumed_bits = 0; + } + bb->total_consumed_bits += i; + return true; + } + else { + val_ += FLAC__BITS_PER_BLURB; + CRC16_UPDATE_BLURB(bb, 0, bb->read_crc16); + bb->consumed_blurbs++; + /* bb->consumed_bits is already 0 */ + bb->total_consumed_bits += FLAC__BITS_PER_BLURB; + } + } +#if FLAC__BITS_PER_BLURB > 8 + } + else { + while(1) { + if(!FLAC__bitbuffer_read_bit(bb, &i, read_callback, client_data)) + return false; + if(i) + break; + else + val_++; + } + *val = val_; + return true; + } +#endif +} +#endif + +#ifdef FLAC__SYMMETRIC_RICE +FLAC__bool FLAC__bitbuffer_read_symmetric_rice_signed(FLAC__BitBuffer *bb, int *val, unsigned parameter, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) +{ + FLAC__uint32 sign = 0, lsbs = 0, msbs = 0; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + FLAC__ASSERT(parameter <= 31); + + /* read the unary MSBs and end bit */ + if(!FLAC__bitbuffer_read_unary_unsigned(bb, &msbs, read_callback, client_data)) + return false; + + /* read the sign bit */ + if(!FLAC__bitbuffer_read_bit_to_uint32(bb, &sign, read_callback, client_data)) + return false; + + /* read the binary LSBs */ + if(!FLAC__bitbuffer_read_raw_uint32(bb, &lsbs, parameter, read_callback, client_data)) + return false; + + /* compose the value */ + *val = (msbs << parameter) | lsbs; + if(sign) + *val = -(*val); + + return true; +} +#endif /* ifdef FLAC__SYMMETRIC_RICE */ + +FLAC__bool FLAC__bitbuffer_read_rice_signed(FLAC__BitBuffer *bb, int *val, unsigned parameter, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) +{ + FLAC__uint32 lsbs = 0, msbs = 0; + unsigned uval; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + FLAC__ASSERT(parameter <= 31); + + /* read the unary MSBs and end bit */ + if(!FLAC__bitbuffer_read_unary_unsigned(bb, &msbs, read_callback, client_data)) + return false; + + /* read the binary LSBs */ + if(!FLAC__bitbuffer_read_raw_uint32(bb, &lsbs, parameter, read_callback, client_data)) + return false; + + /* compose the value */ + uval = (msbs << parameter) | lsbs; + if(uval & 1) + *val = -((int)(uval >> 1)) - 1; + else + *val = (int)(uval >> 1); + + return true; +} + +FLAC__bool FLAC__bitbuffer_read_rice_signed_block(FLAC__BitBuffer *bb, int vals[], unsigned nvals, unsigned parameter, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) +{ + const FLAC__blurb *buffer = bb->buffer; + + unsigned i, j, val_i = 0; + unsigned cbits = 0, uval = 0, msbs = 0, lsbs_left = 0; + FLAC__blurb blurb, save_blurb; + unsigned state = 0; /* 0 = getting unary MSBs, 1 = getting binary LSBs */ + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + FLAC__ASSERT(parameter <= 31); + + if(nvals == 0) + return true; + + i = bb->consumed_blurbs; + /* + * We unroll the main loop to take care of partially consumed blurbs here. + */ + if(bb->consumed_bits > 0) { + save_blurb = blurb = buffer[i]; + cbits = bb->consumed_bits; + blurb <<= cbits; + + while(1) { + if(state == 0) { + if(blurb) { + for(j = 0; !(blurb & FLAC__BLURB_TOP_BIT_ONE); j++) + blurb <<= 1; + msbs += j; + + /* dispose of the unary end bit */ + blurb <<= 1; + j++; + cbits += j; + + uval = 0; + lsbs_left = parameter; + state++; + if(cbits == FLAC__BITS_PER_BLURB) { + cbits = 0; + CRC16_UPDATE_BLURB(bb, save_blurb, bb->read_crc16); + break; + } + } + else { + msbs += FLAC__BITS_PER_BLURB - cbits; + cbits = 0; + CRC16_UPDATE_BLURB(bb, save_blurb, bb->read_crc16); + break; + } + } + else { + const unsigned available_bits = FLAC__BITS_PER_BLURB - cbits; + if(lsbs_left >= available_bits) { + uval <<= available_bits; + uval |= (blurb >> cbits); + cbits = 0; + CRC16_UPDATE_BLURB(bb, save_blurb, bb->read_crc16); + + if(lsbs_left == available_bits) { + /* compose the value */ + uval |= (msbs << parameter); + if(uval & 1) + vals[val_i++] = -((int)(uval >> 1)) - 1; + else + vals[val_i++] = (int)(uval >> 1); + if(val_i == nvals) + break; + + msbs = 0; + state = 0; + } + + lsbs_left -= available_bits; + break; + } + else { + uval <<= lsbs_left; + uval |= (blurb >> (FLAC__BITS_PER_BLURB - lsbs_left)); + blurb <<= lsbs_left; + cbits += lsbs_left; + + /* compose the value */ + uval |= (msbs << parameter); + if(uval & 1) + vals[val_i++] = -((int)(uval >> 1)) - 1; + else + vals[val_i++] = (int)(uval >> 1); + if(val_i == nvals) { + /* back up one if we exited the for loop because we read all nvals but the end came in the middle of a blurb */ + i--; + break; + } + + msbs = 0; + state = 0; + } + } + } + i++; + + bb->consumed_blurbs = i; + bb->consumed_bits = cbits; + bb->total_consumed_bits = (i << FLAC__BITS_PER_BLURB_LOG2) | cbits; + } + + /* + * Now that we are blurb-aligned the logic is slightly simpler + */ + while(val_i < nvals) { + for( ; i < bb->blurbs && val_i < nvals; i++) { + save_blurb = blurb = buffer[i]; + cbits = 0; + while(1) { + if(state == 0) { + if(blurb) { + for(j = 0; !(blurb & FLAC__BLURB_TOP_BIT_ONE); j++) + blurb <<= 1; + msbs += j; + + /* dispose of the unary end bit */ + blurb <<= 1; + j++; + cbits += j; + + uval = 0; + lsbs_left = parameter; + state++; + if(cbits == FLAC__BITS_PER_BLURB) { + cbits = 0; + CRC16_UPDATE_BLURB(bb, save_blurb, bb->read_crc16); + break; + } + } + else { + msbs += FLAC__BITS_PER_BLURB - cbits; + cbits = 0; + CRC16_UPDATE_BLURB(bb, save_blurb, bb->read_crc16); + break; + } + } + else { + const unsigned available_bits = FLAC__BITS_PER_BLURB - cbits; + if(lsbs_left >= available_bits) { + uval <<= available_bits; + uval |= (blurb >> cbits); + cbits = 0; + CRC16_UPDATE_BLURB(bb, save_blurb, bb->read_crc16); + + if(lsbs_left == available_bits) { + /* compose the value */ + uval |= (msbs << parameter); + if(uval & 1) + vals[val_i++] = -((int)(uval >> 1)) - 1; + else + vals[val_i++] = (int)(uval >> 1); + if(val_i == nvals) + break; + + msbs = 0; + state = 0; + } + + lsbs_left -= available_bits; + break; + } + else { + uval <<= lsbs_left; + uval |= (blurb >> (FLAC__BITS_PER_BLURB - lsbs_left)); + blurb <<= lsbs_left; + cbits += lsbs_left; + + /* compose the value */ + uval |= (msbs << parameter); + if(uval & 1) + vals[val_i++] = -((int)(uval >> 1)) - 1; + else + vals[val_i++] = (int)(uval >> 1); + if(val_i == nvals) { + /* back up one if we exited the for loop because we read all nvals but the end came in the middle of a blurb */ + i--; + break; + } + + msbs = 0; + state = 0; + } + } + } + } + bb->consumed_blurbs = i; + bb->consumed_bits = cbits; + bb->total_consumed_bits = (i << FLAC__BITS_PER_BLURB_LOG2) | cbits; + if(val_i < nvals) { + if(!bitbuffer_read_from_client_(bb, read_callback, client_data)) + return false; + /* these must be zero because we can only get here if we got to the end of the buffer */ + FLAC__ASSERT(bb->consumed_blurbs == 0); + FLAC__ASSERT(bb->consumed_bits == 0); + i = 0; + } + } + + return true; +} + +#if 0 /* UNUSED */ +FLAC__bool FLAC__bitbuffer_read_golomb_signed(FLAC__BitBuffer *bb, int *val, unsigned parameter, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) +{ + FLAC__uint32 lsbs = 0, msbs = 0; + unsigned bit, uval, k; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + + k = FLAC__bitmath_ilog2(parameter); + + /* read the unary MSBs and end bit */ + if(!FLAC__bitbuffer_read_unary_unsigned(bb, &msbs, read_callback, client_data)) + return false; + + /* read the binary LSBs */ + if(!FLAC__bitbuffer_read_raw_uint32(bb, &lsbs, k, read_callback, client_data)) + return false; + + if(parameter == 1u<= d) { + if(!FLAC__bitbuffer_read_bit(bb, &bit, read_callback, client_data)) + 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__bitbuffer_read_golomb_unsigned(FLAC__BitBuffer *bb, unsigned *val, unsigned parameter, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) +{ + FLAC__uint32 lsbs, msbs = 0; + unsigned bit, k; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + + k = FLAC__bitmath_ilog2(parameter); + + /* read the unary MSBs and end bit */ + if(!FLAC__bitbuffer_read_unary_unsigned(bb, &msbs, read_callback, client_data)) + return false; + + /* read the binary LSBs */ + if(!FLAC__bitbuffer_read_raw_uint32(bb, &lsbs, k, read_callback, client_data)) + return false; + + if(parameter == 1u<= d) { + if(!FLAC__bitbuffer_read_bit(bb, &bit, read_callback, client_data)) + 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__bitbuffer_read_utf8_uint32(FLAC__BitBuffer *bb, FLAC__uint32 *val, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data, FLAC__byte *raw, unsigned *rawlen) +{ + FLAC__uint32 v = 0; + FLAC__uint32 x; + unsigned i; + + if(!FLAC__bitbuffer_read_raw_uint32(bb, &x, 8, read_callback, client_data)) + 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__bitbuffer_read_raw_uint32(bb, &x, 8, read_callback, client_data)) + 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__bitbuffer_read_utf8_uint64(FLAC__BitBuffer *bb, FLAC__uint64 *val, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data, FLAC__byte *raw, unsigned *rawlen) +{ + FLAC__uint64 v = 0; + FLAC__uint32 x; + unsigned i; + + if(!FLAC__bitbuffer_read_raw_uint32(bb, &x, 8, read_callback, client_data)) + 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__bitbuffer_read_raw_uint32(bb, &x, 8, read_callback, client_data)) + 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; +} + +void FLAC__bitbuffer_dump(const FLAC__BitBuffer *bb, FILE *out) +{ + unsigned i, j; + if(bb == 0) { + fprintf(out, "bitbuffer is NULL\n"); + } + else { + fprintf(out, "bitbuffer: capacity=%u blurbs=%u bits=%u total_bits=%u consumed: blurbs=%u, bits=%u, total_bits=%u\n", bb->capacity, bb->blurbs, bb->bits, bb->total_bits, bb->consumed_blurbs, bb->consumed_bits, bb->total_consumed_bits); + + for(i = 0; i < bb->blurbs; i++) { + fprintf(out, "%08X: ", i); + for(j = 0; j < FLAC__BITS_PER_BLURB; j++) + if(i*FLAC__BITS_PER_BLURB+j < bb->total_consumed_bits) + fprintf(out, "."); + else + fprintf(out, "%01u", bb->buffer[i] & (1 << (FLAC__BITS_PER_BLURB-j-1)) ? 1:0); + fprintf(out, "\n"); + } + if(bb->bits > 0) { + fprintf(out, "%08X: ", i); + for(j = 0; j < bb->bits; j++) + if(i*FLAC__BITS_PER_BLURB+j < bb->total_consumed_bits) + fprintf(out, "."); + else + fprintf(out, "%01u", bb->buffer[i] & (1 << (bb->bits-j-1)) ? 1:0); + fprintf(out, "\n"); + } + } +} diff --git a/FLAC/bitmath.c b/FLAC/bitmath.c new file mode 100644 index 00000000000..5ace20b9f38 --- /dev/null +++ b/FLAC/bitmath.c @@ -0,0 +1,136 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2001,2002,2003,2004 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. + */ + +#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(unsigned 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/FLAC/cpu.c b/FLAC/cpu.c new file mode 100644 index 00000000000..63ce05e0937 --- /dev/null +++ b/FLAC/cpu.c @@ -0,0 +1,117 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2001,2002,2003,2004 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. + */ + +#include "private/cpu.h" +#include +#include + +#ifdef HAVE_CONFIG_H +#include +#endif + +#if defined FLAC__CPU_PPC +#if !defined FLAC__NO_ASM +#if defined __APPLE__ && defined __MACH__ +#include +#endif /* __APPLE__ && __MACH__ */ +#endif /* FLAC__NO_ASM */ +#endif /* FLAC__CPU_PPC */ + +const unsigned FLAC__CPUINFO_IA32_CPUID_CMOV = 0x00008000; +const unsigned FLAC__CPUINFO_IA32_CPUID_MMX = 0x00800000; +const unsigned FLAC__CPUINFO_IA32_CPUID_FXSR = 0x01000000; +const unsigned FLAC__CPUINFO_IA32_CPUID_SSE = 0x02000000; +const unsigned FLAC__CPUINFO_IA32_CPUID_SSE2 = 0x04000000; + +const unsigned FLAC__CPUINFO_IA32_CPUID_EXTENDED_AMD_3DNOW = 0x80000000; +const unsigned FLAC__CPUINFO_IA32_CPUID_EXTENDED_AMD_EXT3DNOW = 0x40000000; +const unsigned FLAC__CPUINFO_IA32_CPUID_EXTENDED_AMD_EXTMMX = 0x00400000; + + +void FLAC__cpu_info(FLAC__CPUInfo *info) +{ +#ifdef FLAC__CPU_IA32 + info->type = FLAC__CPUINFO_TYPE_IA32; +#if !defined FLAC__NO_ASM && defined FLAC__HAS_NASM + info->use_asm = true; + { + unsigned cpuid = FLAC__cpu_info_asm_ia32(); + info->data.ia32.cmov = (cpuid & FLAC__CPUINFO_IA32_CPUID_CMOV)? true : false; + info->data.ia32.mmx = (cpuid & FLAC__CPUINFO_IA32_CPUID_MMX)? true : false; + info->data.ia32.fxsr = (cpuid & FLAC__CPUINFO_IA32_CPUID_FXSR)? true : false; + info->data.ia32.sse = (cpuid & FLAC__CPUINFO_IA32_CPUID_SSE)? true : false; + info->data.ia32.sse2 = (cpuid & FLAC__CPUINFO_IA32_CPUID_SSE2)? true : false; + +#ifndef FLAC__SSE_OS + info->data.ia32.fxsr = info->data.ia32.sse = info->data.ia32.sse2 = false; +#endif + +#ifdef FLAC__USE_3DNOW + cpuid = FLAC__cpu_info_extended_amd_asm_ia32(); + info->data.ia32._3dnow = (cpuid & FLAC__CPUINFO_IA32_CPUID_EXTENDED_AMD_3DNOW)? true : false; + info->data.ia32.ext3dnow = (cpuid & FLAC__CPUINFO_IA32_CPUID_EXTENDED_AMD_EXT3DNOW)? true : false; + info->data.ia32.extmmx = (cpuid & FLAC__CPUINFO_IA32_CPUID_EXTENDED_AMD_EXTMMX)? true : false; +#else + info->data.ia32._3dnow = info->data.ia32.ext3dnow = info->data.ia32.extmmx = false; +#endif + } +#else + info->use_asm = false; +#endif +#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 __APPLE__ && defined __MACH__ + { + int selectors[2] = { CTL_HW, HW_VECTORUNIT }; + int result = 0; + size_t length = sizeof(result); + int error = sysctl(selectors, 2, &result, &length, 0, 0); + + info->data.ppc.altivec = error==0 ? result!=0 : 0; + } +#else /* __APPLE__ && __MACH__ */ + /* don't know of any other thread-safe way to check */ + info->data.ppc.altivec = 0; +#endif /* __APPLE__ && __MACH__ */ +#else /* FLAC__USE_ALTIVEC */ + info->data.ppc.altivec = 0; +#endif /* FLAC__USE_ALTIVEC */ +#else /* FLAC__NO_ASM */ + info->use_asm = false; +#endif /* FLAC__NO_ASM */ +#else + info->type = FLAC__CPUINFO_TYPE_UNKNOWN; + info->use_asm = false; +#endif +} diff --git a/FLAC/crc.c b/FLAC/crc.c new file mode 100644 index 00000000000..f453f8c7abe --- /dev/null +++ b/FLAC/crc.c @@ -0,0 +1,149 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2000,2001,2002,2003,2004 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. + */ + +#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 */ + +FLAC__uint16 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; +} + +void FLAC__crc16_update(const FLAC__byte data, FLAC__uint16 *crc) +{ + *crc = (*crc<<8) ^ FLAC__crc16_table[(*crc>>8) ^ data]; +} + +void FLAC__crc16_update_block(const FLAC__byte *data, unsigned len, FLAC__uint16 *crc) +{ + while(len--) + *crc = (*crc<<8) ^ FLAC__crc16_table[(*crc>>8) ^ *data++]; +} + +FLAC__uint16 FLAC__crc16(const FLAC__byte *data, unsigned len) +{ + FLAC__uint16 crc = 0; + + while(len--) + crc = (crc<<8) ^ FLAC__crc16_table[(crc>>8) ^ *data++]; + + return crc; +} diff --git a/FLAC/fixed.c b/FLAC/fixed.c new file mode 100644 index 00000000000..bf88461a666 --- /dev/null +++ b/FLAC/fixed.c @@ -0,0 +1,231 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2000,2001,2002,2003,2004 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. + */ + +#include +#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))) + +unsigned FLAC__fixed_compute_best_predictor(const FLAC__int32 data[], unsigned data_len, FLAC__real residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]) +{ + 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); + residual_bits_per_sample[0] = (FLAC__real)((total_error_0 > 0) ? log(M_LN2 * (double)total_error_0 / (double)data_len) / M_LN2 : 0.0); + residual_bits_per_sample[1] = (FLAC__real)((total_error_1 > 0) ? log(M_LN2 * (double)total_error_1 / (double)data_len) / M_LN2 : 0.0); + residual_bits_per_sample[2] = (FLAC__real)((total_error_2 > 0) ? log(M_LN2 * (double)total_error_2 / (double)data_len) / M_LN2 : 0.0); + residual_bits_per_sample[3] = (FLAC__real)((total_error_3 > 0) ? log(M_LN2 * (double)total_error_3 / (double)data_len) / M_LN2 : 0.0); + residual_bits_per_sample[4] = (FLAC__real)((total_error_4 > 0) ? log(M_LN2 * (double)total_error_4 / (double)data_len) / M_LN2 : 0.0); + + return order; +} + +unsigned FLAC__fixed_compute_best_predictor_wide(const FLAC__int32 data[], unsigned data_len, FLAC__real residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]) +{ + 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); +#if defined _MSC_VER || defined __MINGW32__ + /* with VC++ you have to spoon feed it the casting */ + residual_bits_per_sample[0] = (FLAC__real)((total_error_0 > 0) ? log(M_LN2 * (double)(FLAC__int64)total_error_0 / (double)data_len) / M_LN2 : 0.0); + residual_bits_per_sample[1] = (FLAC__real)((total_error_1 > 0) ? log(M_LN2 * (double)(FLAC__int64)total_error_1 / (double)data_len) / M_LN2 : 0.0); + residual_bits_per_sample[2] = (FLAC__real)((total_error_2 > 0) ? log(M_LN2 * (double)(FLAC__int64)total_error_2 / (double)data_len) / M_LN2 : 0.0); + residual_bits_per_sample[3] = (FLAC__real)((total_error_3 > 0) ? log(M_LN2 * (double)(FLAC__int64)total_error_3 / (double)data_len) / M_LN2 : 0.0); + residual_bits_per_sample[4] = (FLAC__real)((total_error_4 > 0) ? log(M_LN2 * (double)(FLAC__int64)total_error_4 / (double)data_len) / M_LN2 : 0.0); +#else + residual_bits_per_sample[0] = (FLAC__real)((total_error_0 > 0) ? log(M_LN2 * (double)total_error_0 / (double)data_len) / M_LN2 : 0.0); + residual_bits_per_sample[1] = (FLAC__real)((total_error_1 > 0) ? log(M_LN2 * (double)total_error_1 / (double)data_len) / M_LN2 : 0.0); + residual_bits_per_sample[2] = (FLAC__real)((total_error_2 > 0) ? log(M_LN2 * (double)total_error_2 / (double)data_len) / M_LN2 : 0.0); + residual_bits_per_sample[3] = (FLAC__real)((total_error_3 > 0) ? log(M_LN2 * (double)total_error_3 / (double)data_len) / M_LN2 : 0.0); + residual_bits_per_sample[4] = (FLAC__real)((total_error_4 > 0) ? log(M_LN2 * (double)total_error_4 / (double)data_len) / M_LN2 : 0.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: + for(i = 0; i < idata_len; i++) { + residual[i] = data[i]; + } + 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++) { + /* == data[i] - 2*data[i-1] + data[i-2] */ + residual[i] = data[i] - (data[i-1] << 1) + data[i-2]; + } + break; + case 3: + for(i = 0; i < idata_len; i++) { + /* == data[i] - 3*data[i-1] + 3*data[i-2] - data[i-3] */ + residual[i] = data[i] - (((data[i-1]-data[i-2])<<1) + (data[i-1]-data[i-2])) - data[i-3]; + } + break; + case 4: + for(i = 0; i < idata_len; i++) { + /* == data[i] - 4*data[i-1] + 6*data[i-2] - 4*data[i-3] + data[i-4] */ + residual[i] = data[i] - ((data[i-1]+data[i-3])<<2) + ((data[i-2]<<2) + (data[i-2]<<1)) + data[i-4]; + } + 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: + for(i = 0; i < idata_len; i++) { + data[i] = residual[i]; + } + 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++) { + /* == residual[i] + 2*data[i-1] - data[i-2] */ + data[i] = residual[i] + (data[i-1]<<1) - data[i-2]; + } + break; + case 3: + for(i = 0; i < idata_len; i++) { + /* residual[i] + 3*data[i-1] - 3*data[i-2]) + data[i-3] */ + data[i] = residual[i] + (((data[i-1]-data[i-2])<<1) + (data[i-1]-data[i-2])) + data[i-3]; + } + break; + case 4: + for(i = 0; i < idata_len; i++) { + /* == residual[i] + 4*data[i-1] - 6*data[i-2] + 4*data[i-3] - data[i-4] */ + data[i] = residual[i] + ((data[i-1]+data[i-3])<<2) - ((data[i-2]<<2) + (data[i-2]<<1)) - data[i-4]; + } + break; + default: + FLAC__ASSERT(0); + } +} diff --git a/FLAC/format.c b/FLAC/format.c new file mode 100644 index 00000000000..de07a0b2b7a --- /dev/null +++ b/FLAC/format.c @@ -0,0 +1,403 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2000,2001,2002,2003,2004 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. + */ + +#include +#include /* for qsort() */ +#include "FLAC/assert.h" +#include "FLAC/format.h" +#include "private/format.h" + +#ifdef HAVE_CONFIG_H +#include +#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 = "1.1.1"; + +#if defined _MSC_VER || defined __MINW32__ +/* yet one more hack because of MSVC6: */ +FLAC_API const char *FLAC__VENDOR_STRING = "reference libFLAC 1.1.1 20041001"; +#else +FLAC_API const char *FLAC__VENDOR_STRING = "reference libFLAC " VERSION " 20041001"; +#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_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 = 2; /* 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_RICE_RAW_LEN = 5; /* bits */ + +FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER = 15; /* == (1< FLAC__MAX_SAMPLE_RATE || + ( + sample_rate >= (1u << 16) && + !(sample_rate % 1000 == 0 || sample_rate % 10 == 0) + ) + ) { + return false; + } + else + return true; +} + +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; +} + +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; +} + +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) *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; +} + +/* + * 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; + object->capacity_by_order = max_partition_order; + } + + return true; +} diff --git a/FLAC/ia32/cpu_asm.nasm b/FLAC/ia32/cpu_asm.nasm new file mode 100644 index 00000000000..570aec344e4 --- /dev/null +++ b/FLAC/ia32/cpu_asm.nasm @@ -0,0 +1,100 @@ +; libFLAC - Free Lossless Audio Codec library +; Copyright (C) 2001,2002,2003 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. + +%include "ia32/nasm.h" + + data_section + +cglobal FLAC__cpu_info_asm_ia32 +cglobal FLAC__cpu_info_extended_amd_asm_ia32 +cglobal FLAC__cpu_info_sse_test_asm_ia32 + + code_section + +; ********************************************************************** +; + +have_cpuid: + pushfd + pop eax + mov edx, eax + xor eax, 0x00200000 + push eax + popfd + pushfd + pop eax + cmp eax, edx + jz .no_cpuid + mov eax, 1 + jmp .end +.no_cpuid: + xor eax, eax +.end: + ret + +cident FLAC__cpu_info_asm_ia32 + push ebx + call have_cpuid + test eax, eax + jz .no_cpuid + mov eax, 1 + cpuid + mov eax, edx + jmp .end +.no_cpuid: + xor eax, eax +.end + pop ebx + ret + +cident FLAC__cpu_info_extended_amd_asm_ia32 + push ebx + call have_cpuid + test eax, eax + jz .no_cpuid + mov eax, 0x80000000 + cpuid + cmp eax, 0x80000001 + jb .no_cpuid + mov eax, 0x80000001 + cpuid + mov eax, edx + jmp .end +.no_cpuid + xor eax, eax +.end + pop ebx + ret + +cident FLAC__cpu_info_sse_test_asm_ia32 + xorps xmm0, xmm0 + pop ebx + +end diff --git a/FLAC/ia32/fixed_asm.nasm b/FLAC/ia32/fixed_asm.nasm new file mode 100644 index 00000000000..9e93928e4db --- /dev/null +++ b/FLAC/ia32/fixed_asm.nasm @@ -0,0 +1,306 @@ +; libFLAC - Free Lossless Audio Codec library +; Copyright (C) 2001,2002,2003 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. + +%include "ia32/nasm.h" + + data_section + +cglobal FLAC__fixed_compute_best_predictor_asm_ia32_mmx_cmov + + code_section + +; ********************************************************************** +; +; unsigned FLAC__fixed_compute_best_predictor(const FLAC__int32 data[], unsigned data_len, FLAC__real residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]) +; { +; 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; +; +; residual_bits_per_sample[0] = (FLAC__real)((data_len > 0 && total_error_0 > 0) ? log(M_LN2 * (double)total_error_0 / (double)data_len) / M_LN2 : 0.0); +; residual_bits_per_sample[1] = (FLAC__real)((data_len > 0 && total_error_1 > 0) ? log(M_LN2 * (double)total_error_1 / (double)data_len) / M_LN2 : 0.0); +; residual_bits_per_sample[2] = (FLAC__real)((data_len > 0 && total_error_2 > 0) ? log(M_LN2 * (double)total_error_2 / (double)data_len) / M_LN2 : 0.0); +; residual_bits_per_sample[3] = (FLAC__real)((data_len > 0 && total_error_3 > 0) ? log(M_LN2 * (double)total_error_3 / (double)data_len) / M_LN2 : 0.0); +; residual_bits_per_sample[4] = (FLAC__real)((data_len > 0 && total_error_4 > 0) ? log(M_LN2 * (double)total_error_4 / (double)data_len) / M_LN2 : 0.0); +; +; return order; +; } + ALIGN 16 +cident FLAC__fixed_compute_best_predictor_asm_ia32_mmx_cmov + + ; esp + 36 == data[] + ; esp + 40 == data_len + ; esp + 44 == residual_bits_per_sample[] + + push ebp + push ebx + push esi + push edi + sub esp, byte 16 + ; qword [esp] == temp space for loading FLAC__uint64s to FPU regs + + ; ebx == &data[i] + ; ecx == loop counter (i) + ; ebp == order + ; mm0 == total_error_1:total_error_0 + ; mm1 == total_error_2:total_error_3 + ; mm2 == :total_error_4 + ; mm3 == last_error_1:last_error_0 + ; mm4 == last_error_2:last_error_3 + + mov ecx, [esp + 40] ; ecx = data_len + test ecx, ecx + jz near .data_len_is_0 + + mov ebx, [esp + 36] ; ebx = data[] + movd mm3, [ebx - 4] ; mm3 = 0:last_error_0 + movd mm2, [ebx - 8] ; mm2 = 0:data[-2] + movd mm1, [ebx - 12] ; mm1 = 0:data[-3] + movd mm0, [ebx - 16] ; mm0 = 0:data[-4] + movq mm5, mm3 ; mm5 = 0:last_error_0 + psubd mm5, mm2 ; mm5 = 0:last_error_1 + punpckldq mm3, mm5 ; mm3 = last_error_1:last_error_0 + psubd mm2, mm1 ; mm2 = 0:data[-2] - data[-3] + psubd mm5, mm2 ; mm5 = 0:last_error_2 + movq mm4, mm5 ; mm4 = 0:last_error_2 + psubd mm4, mm2 ; mm4 = 0:last_error_2 - (data[-2] - data[-3]) + paddd mm4, mm1 ; mm4 = 0:last_error_2 - (data[-2] - 2 * data[-3]) + psubd mm4, mm0 ; mm4 = 0:last_error_3 + punpckldq mm4, mm5 ; mm4 = last_error_2:last_error_3 + pxor mm0, mm0 ; mm0 = total_error_1:total_error_0 + pxor mm1, mm1 ; mm1 = total_error_2:total_error_3 + pxor mm2, mm2 ; mm2 = 0:total_error_4 + + ALIGN 16 +.loop: + movd mm7, [ebx] ; mm7 = 0:error_0 + add ebx, byte 4 + movq mm6, mm7 ; mm6 = 0:error_0 + psubd mm7, mm3 ; mm7 = :error_1 + punpckldq mm6, mm7 ; mm6 = error_1:error_0 + movq mm5, mm6 ; mm5 = error_1:error_0 + movq mm7, mm6 ; mm7 = error_1:error_0 + psubd mm5, mm3 ; mm5 = error_2: + movq mm3, mm6 ; mm3 = error_1:error_0 + psrad mm6, 31 + pxor mm7, mm6 + psubd mm7, mm6 ; mm7 = abs(error_1):abs(error_0) + paddd mm0, mm7 ; mm0 = total_error_1:total_error_0 + movq mm6, mm5 ; mm6 = error_2: + psubd mm5, mm4 ; mm5 = error_3: + punpckhdq mm5, mm6 ; mm5 = error_2:error_3 + movq mm7, mm5 ; mm7 = error_2:error_3 + movq mm6, mm5 ; mm6 = error_2:error_3 + psubd mm5, mm4 ; mm5 = :error_4 + movq mm4, mm6 ; mm4 = error_2:error_3 + psrad mm6, 31 + pxor mm7, mm6 + psubd mm7, mm6 ; mm7 = abs(error_2):abs(error_3) + paddd mm1, mm7 ; mm1 = total_error_2:total_error_3 + movq mm6, mm5 ; mm6 = :error_4 + psrad mm5, 31 + pxor mm6, mm5 + psubd mm6, mm5 ; mm6 = :abs(error_4) + paddd mm2, mm6 ; mm2 = :total_error_4 + + dec ecx + jnz short .loop + +; 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; + movq mm3, mm0 ; mm3 = total_error_1:total_error_0 + movd edi, mm2 ; edi = total_error_4 + movd esi, mm1 ; esi = total_error_3 + movd eax, mm0 ; eax = total_error_0 + punpckhdq mm1, mm1 ; mm1 = total_error_2:total_error_2 + punpckhdq mm3, mm3 ; mm3 = total_error_1:total_error_1 + movd edx, mm1 ; edx = total_error_2 + movd ecx, mm3 ; ecx = total_error_1 + + xor ebx, ebx + xor ebp, ebp + inc ebx + cmp ecx, eax + cmovb eax, ecx ; eax = min(total_error_0, total_error_1) + cmovbe ebp, ebx + inc ebx + cmp edx, eax + cmovb eax, edx ; eax = min(total_error_0, total_error_1, total_error_2) + cmovbe ebp, ebx + inc ebx + cmp esi, eax + cmovb eax, esi ; eax = min(total_error_0, total_error_1, total_error_2, total_error_3) + cmovbe ebp, ebx + inc ebx + cmp edi, eax + cmovb eax, edi ; eax = min(total_error_0, total_error_1, total_error_2, total_error_3, total_error_4) + cmovbe ebp, ebx + movd ebx, mm0 ; ebx = total_error_0 + emms + + ; residual_bits_per_sample[0] = (FLAC__real)((data_len > 0 && total_error_0 > 0) ? log(M_LN2 * (double)total_error_0 / (double)data_len) / M_LN2 : 0.0); + ; residual_bits_per_sample[1] = (FLAC__real)((data_len > 0 && total_error_1 > 0) ? log(M_LN2 * (double)total_error_1 / (double)data_len) / M_LN2 : 0.0); + ; residual_bits_per_sample[2] = (FLAC__real)((data_len > 0 && total_error_2 > 0) ? log(M_LN2 * (double)total_error_2 / (double)data_len) / M_LN2 : 0.0); + ; residual_bits_per_sample[3] = (FLAC__real)((data_len > 0 && total_error_3 > 0) ? log(M_LN2 * (double)total_error_3 / (double)data_len) / M_LN2 : 0.0); + ; residual_bits_per_sample[4] = (FLAC__real)((data_len > 0 && total_error_4 > 0) ? log(M_LN2 * (double)total_error_4 / (double)data_len) / M_LN2 : 0.0); + xor eax, eax + fild dword [esp + 40] ; ST = data_len (NOTE: assumes data_len is <2gigs) +.rbps_0: + test ebx, ebx + jz .total_error_0_is_0 + fld1 ; ST = 1.0 data_len + mov [esp], ebx + mov [esp + 4], eax ; [esp] = (FLAC__uint64)total_error_0 + mov ebx, [esp + 44] + fild qword [esp] ; ST = total_error_0 1.0 data_len + fdiv st2 ; ST = total_error_0/data_len 1.0 data_len + fldln2 ; ST = ln2 total_error_0/data_len 1.0 data_len + fmulp st1 ; ST = ln2*total_error_0/data_len 1.0 data_len + fyl2x ; ST = log2(ln2*total_error_0/data_len) data_len + fstp dword [ebx] ; residual_bits_per_sample[0] = log2(ln2*total_error_0/data_len) ST = data_len + jmp short .rbps_1 +.total_error_0_is_0: + mov ebx, [esp + 44] + mov [ebx], eax ; residual_bits_per_sample[0] = 0.0 +.rbps_1: + test ecx, ecx + jz .total_error_1_is_0 + fld1 ; ST = 1.0 data_len + mov [esp], ecx + mov [esp + 4], eax ; [esp] = (FLAC__uint64)total_error_1 + fild qword [esp] ; ST = total_error_1 1.0 data_len + fdiv st2 ; ST = total_error_1/data_len 1.0 data_len + fldln2 ; ST = ln2 total_error_1/data_len 1.0 data_len + fmulp st1 ; ST = ln2*total_error_1/data_len 1.0 data_len + fyl2x ; ST = log2(ln2*total_error_1/data_len) data_len + fstp dword [ebx + 4] ; residual_bits_per_sample[1] = log2(ln2*total_error_1/data_len) ST = data_len + jmp short .rbps_2 +.total_error_1_is_0: + mov [ebx + 4], eax ; residual_bits_per_sample[1] = 0.0 +.rbps_2: + test edx, edx + jz .total_error_2_is_0 + fld1 ; ST = 1.0 data_len + mov [esp], edx + mov [esp + 4], eax ; [esp] = (FLAC__uint64)total_error_2 + fild qword [esp] ; ST = total_error_2 1.0 data_len + fdiv st2 ; ST = total_error_2/data_len 1.0 data_len + fldln2 ; ST = ln2 total_error_2/data_len 1.0 data_len + fmulp st1 ; ST = ln2*total_error_2/data_len 1.0 data_len + fyl2x ; ST = log2(ln2*total_error_2/data_len) data_len + fstp dword [ebx + 8] ; residual_bits_per_sample[2] = log2(ln2*total_error_2/data_len) ST = data_len + jmp short .rbps_3 +.total_error_2_is_0: + mov [ebx + 8], eax ; residual_bits_per_sample[2] = 0.0 +.rbps_3: + test esi, esi + jz .total_error_3_is_0 + fld1 ; ST = 1.0 data_len + mov [esp], esi + mov [esp + 4], eax ; [esp] = (FLAC__uint64)total_error_3 + fild qword [esp] ; ST = total_error_3 1.0 data_len + fdiv st2 ; ST = total_error_3/data_len 1.0 data_len + fldln2 ; ST = ln2 total_error_3/data_len 1.0 data_len + fmulp st1 ; ST = ln2*total_error_3/data_len 1.0 data_len + fyl2x ; ST = log2(ln2*total_error_3/data_len) data_len + fstp dword [ebx + 12] ; residual_bits_per_sample[3] = log2(ln2*total_error_3/data_len) ST = data_len + jmp short .rbps_4 +.total_error_3_is_0: + mov [ebx + 12], eax ; residual_bits_per_sample[3] = 0.0 +.rbps_4: + test edi, edi + jz .total_error_4_is_0 + fld1 ; ST = 1.0 data_len + mov [esp], edi + mov [esp + 4], eax ; [esp] = (FLAC__uint64)total_error_4 + fild qword [esp] ; ST = total_error_4 1.0 data_len + fdiv st2 ; ST = total_error_4/data_len 1.0 data_len + fldln2 ; ST = ln2 total_error_4/data_len 1.0 data_len + fmulp st1 ; ST = ln2*total_error_4/data_len 1.0 data_len + fyl2x ; ST = log2(ln2*total_error_4/data_len) data_len + fstp dword [ebx + 16] ; residual_bits_per_sample[4] = log2(ln2*total_error_4/data_len) ST = data_len + jmp short .rbps_end +.total_error_4_is_0: + mov [ebx + 16], eax ; residual_bits_per_sample[4] = 0.0 +.rbps_end: + fstp st0 ; ST = [empty] + jmp short .end +.data_len_is_0: + ; data_len == 0, so residual_bits_per_sample[*] = 0.0 + xor ebp, ebp + mov edi, [esp + 44] + mov [edi], ebp + mov [edi + 4], ebp + mov [edi + 8], ebp + mov [edi + 12], ebp + mov [edi + 16], ebp + add ebp, byte 4 ; order = 4 + +.end: + mov eax, ebp ; return order + add esp, byte 16 + pop edi + pop esi + pop ebx + pop ebp + ret + +end diff --git a/FLAC/ia32/lpc_asm.nasm b/FLAC/ia32/lpc_asm.nasm new file mode 100644 index 00000000000..4eb104b9662 --- /dev/null +++ b/FLAC/ia32/lpc_asm.nasm @@ -0,0 +1,1503 @@ +; libFLAC - Free Lossless Audio Codec library +; Copyright (C) 2001,2002,2003 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. + +%include "ia32/nasm.h" + + data_section + +cglobal FLAC__lpc_compute_autocorrelation_asm_ia32 +cglobal FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_4 +cglobal FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_8 +cglobal FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_12 +cglobal FLAC__lpc_compute_autocorrelation_asm_ia32_3dnow +cglobal FLAC__lpc_compute_residual_from_qlp_coefficients_asm_ia32 +cglobal FLAC__lpc_compute_residual_from_qlp_coefficients_asm_ia32_mmx +cglobal FLAC__lpc_restore_signal_asm_ia32 +cglobal FLAC__lpc_restore_signal_asm_ia32_mmx + + code_section + +; ********************************************************************** +; +; void FLAC__lpc_compute_autocorrelation_asm(const FLAC__real data[], unsigned data_len, unsigned lag, FLAC__real autoc[]) +; { +; 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]; +; } +; } +; + ALIGN 16 +cident FLAC__lpc_compute_autocorrelation_asm_ia32 + ;[esp + 28] == autoc[] + ;[esp + 24] == lag + ;[esp + 20] == data_len + ;[esp + 16] == data[] + + ;ASSERT(lag > 0) + ;ASSERT(lag <= 33) + ;ASSERT(lag <= data_len) + +.begin: + push esi + push edi + push ebx + + ; for(coeff = 0; coeff < lag; coeff++) + ; autoc[coeff] = 0.0; + mov edi, [esp + 28] ; edi == autoc + mov ecx, [esp + 24] ; ecx = # of dwords (=lag) of 0 to write + xor eax, eax + rep stosd + + ; const unsigned limit = data_len - lag; + mov eax, [esp + 24] ; eax == lag + mov ecx, [esp + 20] + sub ecx, eax ; ecx == limit + + mov edi, [esp + 28] ; edi == autoc + mov esi, [esp + 16] ; esi == data + inc ecx ; we are looping <= limit so we add one to the counter + + ; for(sample = 0; sample <= limit; sample++) { + ; d = data[sample]; + ; for(coeff = 0; coeff < lag; coeff++) + ; autoc[coeff] += d * data[sample+coeff]; + ; } + fld dword [esi] ; ST = d <- data[sample] + ; each iteration is 11 bytes so we need (-eax)*11, so we do (-12*eax + eax) + lea edx, [eax + eax*2] + neg edx + lea edx, [eax + edx*4 + .jumper1_0 - .get_eip1] + call .get_eip1 +.get_eip1: + pop ebx + add edx, ebx + inc edx ; compensate for the shorter opcode on the last iteration + inc edx ; compensate for the shorter opcode on the last iteration + inc edx ; compensate for the shorter opcode on the last iteration + cmp eax, 33 + jne .loop1_start + sub edx, byte 9 ; compensate for the longer opcodes on the first iteration +.loop1_start: + jmp edx + + fld st0 ; ST = d d + fmul dword [esi + (32*4)] ; ST = d*data[sample+32] d WATCHOUT: not a byte displacement here! + fadd dword [edi + (32*4)] ; ST = autoc[32]+d*data[sample+32] d WATCHOUT: not a byte displacement here! + fstp dword [edi + (32*4)] ; autoc[32]+=d*data[sample+32] ST = d WATCHOUT: not a byte displacement here! + fld st0 ; ST = d d + fmul dword [esi + (31*4)] ; ST = d*data[sample+31] d + fadd dword [edi + (31*4)] ; ST = autoc[31]+d*data[sample+31] d + fstp dword [edi + (31*4)] ; autoc[31]+=d*data[sample+31] ST = d + fld st0 ; ST = d d + fmul dword [esi + (30*4)] ; ST = d*data[sample+30] d + fadd dword [edi + (30*4)] ; ST = autoc[30]+d*data[sample+30] d + fstp dword [edi + (30*4)] ; autoc[30]+=d*data[sample+30] ST = d + fld st0 ; ST = d d + fmul dword [esi + (29*4)] ; ST = d*data[sample+29] d + fadd dword [edi + (29*4)] ; ST = autoc[29]+d*data[sample+29] d + fstp dword [edi + (29*4)] ; autoc[29]+=d*data[sample+29] ST = d + fld st0 ; ST = d d + fmul dword [esi + (28*4)] ; ST = d*data[sample+28] d + fadd dword [edi + (28*4)] ; ST = autoc[28]+d*data[sample+28] d + fstp dword [edi + (28*4)] ; autoc[28]+=d*data[sample+28] ST = d + fld st0 ; ST = d d + fmul dword [esi + (27*4)] ; ST = d*data[sample+27] d + fadd dword [edi + (27*4)] ; ST = autoc[27]+d*data[sample+27] d + fstp dword [edi + (27*4)] ; autoc[27]+=d*data[sample+27] ST = d + fld st0 ; ST = d d + fmul dword [esi + (26*4)] ; ST = d*data[sample+26] d + fadd dword [edi + (26*4)] ; ST = autoc[26]+d*data[sample+26] d + fstp dword [edi + (26*4)] ; autoc[26]+=d*data[sample+26] ST = d + fld st0 ; ST = d d + fmul dword [esi + (25*4)] ; ST = d*data[sample+25] d + fadd dword [edi + (25*4)] ; ST = autoc[25]+d*data[sample+25] d + fstp dword [edi + (25*4)] ; autoc[25]+=d*data[sample+25] ST = d + fld st0 ; ST = d d + fmul dword [esi + (24*4)] ; ST = d*data[sample+24] d + fadd dword [edi + (24*4)] ; ST = autoc[24]+d*data[sample+24] d + fstp dword [edi + (24*4)] ; autoc[24]+=d*data[sample+24] ST = d + fld st0 ; ST = d d + fmul dword [esi + (23*4)] ; ST = d*data[sample+23] d + fadd dword [edi + (23*4)] ; ST = autoc[23]+d*data[sample+23] d + fstp dword [edi + (23*4)] ; autoc[23]+=d*data[sample+23] ST = d + fld st0 ; ST = d d + fmul dword [esi + (22*4)] ; ST = d*data[sample+22] d + fadd dword [edi + (22*4)] ; ST = autoc[22]+d*data[sample+22] d + fstp dword [edi + (22*4)] ; autoc[22]+=d*data[sample+22] ST = d + fld st0 ; ST = d d + fmul dword [esi + (21*4)] ; ST = d*data[sample+21] d + fadd dword [edi + (21*4)] ; ST = autoc[21]+d*data[sample+21] d + fstp dword [edi + (21*4)] ; autoc[21]+=d*data[sample+21] ST = d + fld st0 ; ST = d d + fmul dword [esi + (20*4)] ; ST = d*data[sample+20] d + fadd dword [edi + (20*4)] ; ST = autoc[20]+d*data[sample+20] d + fstp dword [edi + (20*4)] ; autoc[20]+=d*data[sample+20] ST = d + fld st0 ; ST = d d + fmul dword [esi + (19*4)] ; ST = d*data[sample+19] d + fadd dword [edi + (19*4)] ; ST = autoc[19]+d*data[sample+19] d + fstp dword [edi + (19*4)] ; autoc[19]+=d*data[sample+19] ST = d + fld st0 ; ST = d d + fmul dword [esi + (18*4)] ; ST = d*data[sample+18] d + fadd dword [edi + (18*4)] ; ST = autoc[18]+d*data[sample+18] d + fstp dword [edi + (18*4)] ; autoc[18]+=d*data[sample+18] ST = d + fld st0 ; ST = d d + fmul dword [esi + (17*4)] ; ST = d*data[sample+17] d + fadd dword [edi + (17*4)] ; ST = autoc[17]+d*data[sample+17] d + fstp dword [edi + (17*4)] ; autoc[17]+=d*data[sample+17] ST = d + fld st0 ; ST = d d + fmul dword [esi + (16*4)] ; ST = d*data[sample+16] d + fadd dword [edi + (16*4)] ; ST = autoc[16]+d*data[sample+16] d + fstp dword [edi + (16*4)] ; autoc[16]+=d*data[sample+16] ST = d + fld st0 ; ST = d d + fmul dword [esi + (15*4)] ; ST = d*data[sample+15] d + fadd dword [edi + (15*4)] ; ST = autoc[15]+d*data[sample+15] d + fstp dword [edi + (15*4)] ; autoc[15]+=d*data[sample+15] ST = d + fld st0 ; ST = d d + fmul dword [esi + (14*4)] ; ST = d*data[sample+14] d + fadd dword [edi + (14*4)] ; ST = autoc[14]+d*data[sample+14] d + fstp dword [edi + (14*4)] ; autoc[14]+=d*data[sample+14] ST = d + fld st0 ; ST = d d + fmul dword [esi + (13*4)] ; ST = d*data[sample+13] d + fadd dword [edi + (13*4)] ; ST = autoc[13]+d*data[sample+13] d + fstp dword [edi + (13*4)] ; autoc[13]+=d*data[sample+13] ST = d + fld st0 ; ST = d d + fmul dword [esi + (12*4)] ; ST = d*data[sample+12] d + fadd dword [edi + (12*4)] ; ST = autoc[12]+d*data[sample+12] d + fstp dword [edi + (12*4)] ; autoc[12]+=d*data[sample+12] ST = d + fld st0 ; ST = d d + fmul dword [esi + (11*4)] ; ST = d*data[sample+11] d + fadd dword [edi + (11*4)] ; ST = autoc[11]+d*data[sample+11] d + fstp dword [edi + (11*4)] ; autoc[11]+=d*data[sample+11] ST = d + fld st0 ; ST = d d + fmul dword [esi + (10*4)] ; ST = d*data[sample+10] d + fadd dword [edi + (10*4)] ; ST = autoc[10]+d*data[sample+10] d + fstp dword [edi + (10*4)] ; autoc[10]+=d*data[sample+10] ST = d + fld st0 ; ST = d d + fmul dword [esi + ( 9*4)] ; ST = d*data[sample+9] d + fadd dword [edi + ( 9*4)] ; ST = autoc[9]+d*data[sample+9] d + fstp dword [edi + ( 9*4)] ; autoc[9]+=d*data[sample+9] ST = d + fld st0 ; ST = d d + fmul dword [esi + ( 8*4)] ; ST = d*data[sample+8] d + fadd dword [edi + ( 8*4)] ; ST = autoc[8]+d*data[sample+8] d + fstp dword [edi + ( 8*4)] ; autoc[8]+=d*data[sample+8] ST = d + fld st0 ; ST = d d + fmul dword [esi + ( 7*4)] ; ST = d*data[sample+7] d + fadd dword [edi + ( 7*4)] ; ST = autoc[7]+d*data[sample+7] d + fstp dword [edi + ( 7*4)] ; autoc[7]+=d*data[sample+7] ST = d + fld st0 ; ST = d d + fmul dword [esi + ( 6*4)] ; ST = d*data[sample+6] d + fadd dword [edi + ( 6*4)] ; ST = autoc[6]+d*data[sample+6] d + fstp dword [edi + ( 6*4)] ; autoc[6]+=d*data[sample+6] ST = d + fld st0 ; ST = d d + fmul dword [esi + ( 5*4)] ; ST = d*data[sample+4] d + fadd dword [edi + ( 5*4)] ; ST = autoc[4]+d*data[sample+4] d + fstp dword [edi + ( 5*4)] ; autoc[4]+=d*data[sample+4] ST = d + fld st0 ; ST = d d + fmul dword [esi + ( 4*4)] ; ST = d*data[sample+4] d + fadd dword [edi + ( 4*4)] ; ST = autoc[4]+d*data[sample+4] d + fstp dword [edi + ( 4*4)] ; autoc[4]+=d*data[sample+4] ST = d + fld st0 ; ST = d d + fmul dword [esi + ( 3*4)] ; ST = d*data[sample+3] d + fadd dword [edi + ( 3*4)] ; ST = autoc[3]+d*data[sample+3] d + fstp dword [edi + ( 3*4)] ; autoc[3]+=d*data[sample+3] ST = d + fld st0 ; ST = d d + fmul dword [esi + ( 2*4)] ; ST = d*data[sample+2] d + fadd dword [edi + ( 2*4)] ; ST = autoc[2]+d*data[sample+2] d + fstp dword [edi + ( 2*4)] ; autoc[2]+=d*data[sample+2] ST = d + fld st0 ; ST = d d + fmul dword [esi + ( 1*4)] ; ST = d*data[sample+1] d + fadd dword [edi + ( 1*4)] ; ST = autoc[1]+d*data[sample+1] d + fstp dword [edi + ( 1*4)] ; autoc[1]+=d*data[sample+1] ST = d + fld st0 ; ST = d d + fmul dword [esi] ; ST = d*data[sample] d WATCHOUT: no displacement byte here! + fadd dword [edi] ; ST = autoc[0]+d*data[sample] d WATCHOUT: no displacement byte here! + fstp dword [edi] ; autoc[0]+=d*data[sample] ST = d WATCHOUT: no displacement byte here! +.jumper1_0: + + fstp st0 ; pop d, ST = empty + add esi, byte 4 ; sample++ + dec ecx + jz .loop1_end + fld dword [esi] ; ST = d <- data[sample] + jmp edx +.loop1_end: + + ; for(; sample < data_len; sample++) { + ; d = data[sample]; + ; for(coeff = 0; coeff < data_len - sample; coeff++) + ; autoc[coeff] += d * data[sample+coeff]; + ; } + mov ecx, [esp + 24] ; ecx <- lag + dec ecx ; ecx <- lag - 1 + jz near .end ; skip loop if 0 (i.e. lag == 1) + + fld dword [esi] ; ST = d <- data[sample] + mov eax, ecx ; eax <- lag - 1 == data_len - sample the first time through + ; each iteration is 11 bytes so we need (-eax)*11, so we do (-12*eax + eax) + lea edx, [eax + eax*2] + neg edx + lea edx, [eax + edx*4 + .jumper2_0 - .get_eip2] + call .get_eip2 +.get_eip2: + pop ebx + add edx, ebx + inc edx ; compensate for the shorter opcode on the last iteration + inc edx ; compensate for the shorter opcode on the last iteration + inc edx ; compensate for the shorter opcode on the last iteration + jmp edx + + fld st0 ; ST = d d + fmul dword [esi + (31*4)] ; ST = d*data[sample+31] d + fadd dword [edi + (31*4)] ; ST = autoc[31]+d*data[sample+31] d + fstp dword [edi + (31*4)] ; autoc[31]+=d*data[sample+31] ST = d + fld st0 ; ST = d d + fmul dword [esi + (30*4)] ; ST = d*data[sample+30] d + fadd dword [edi + (30*4)] ; ST = autoc[30]+d*data[sample+30] d + fstp dword [edi + (30*4)] ; autoc[30]+=d*data[sample+30] ST = d + fld st0 ; ST = d d + fmul dword [esi + (29*4)] ; ST = d*data[sample+29] d + fadd dword [edi + (29*4)] ; ST = autoc[29]+d*data[sample+29] d + fstp dword [edi + (29*4)] ; autoc[29]+=d*data[sample+29] ST = d + fld st0 ; ST = d d + fmul dword [esi + (28*4)] ; ST = d*data[sample+28] d + fadd dword [edi + (28*4)] ; ST = autoc[28]+d*data[sample+28] d + fstp dword [edi + (28*4)] ; autoc[28]+=d*data[sample+28] ST = d + fld st0 ; ST = d d + fmul dword [esi + (27*4)] ; ST = d*data[sample+27] d + fadd dword [edi + (27*4)] ; ST = autoc[27]+d*data[sample+27] d + fstp dword [edi + (27*4)] ; autoc[27]+=d*data[sample+27] ST = d + fld st0 ; ST = d d + fmul dword [esi + (26*4)] ; ST = d*data[sample+26] d + fadd dword [edi + (26*4)] ; ST = autoc[26]+d*data[sample+26] d + fstp dword [edi + (26*4)] ; autoc[26]+=d*data[sample+26] ST = d + fld st0 ; ST = d d + fmul dword [esi + (25*4)] ; ST = d*data[sample+25] d + fadd dword [edi + (25*4)] ; ST = autoc[25]+d*data[sample+25] d + fstp dword [edi + (25*4)] ; autoc[25]+=d*data[sample+25] ST = d + fld st0 ; ST = d d + fmul dword [esi + (24*4)] ; ST = d*data[sample+24] d + fadd dword [edi + (24*4)] ; ST = autoc[24]+d*data[sample+24] d + fstp dword [edi + (24*4)] ; autoc[24]+=d*data[sample+24] ST = d + fld st0 ; ST = d d + fmul dword [esi + (23*4)] ; ST = d*data[sample+23] d + fadd dword [edi + (23*4)] ; ST = autoc[23]+d*data[sample+23] d + fstp dword [edi + (23*4)] ; autoc[23]+=d*data[sample+23] ST = d + fld st0 ; ST = d d + fmul dword [esi + (22*4)] ; ST = d*data[sample+22] d + fadd dword [edi + (22*4)] ; ST = autoc[22]+d*data[sample+22] d + fstp dword [edi + (22*4)] ; autoc[22]+=d*data[sample+22] ST = d + fld st0 ; ST = d d + fmul dword [esi + (21*4)] ; ST = d*data[sample+21] d + fadd dword [edi + (21*4)] ; ST = autoc[21]+d*data[sample+21] d + fstp dword [edi + (21*4)] ; autoc[21]+=d*data[sample+21] ST = d + fld st0 ; ST = d d + fmul dword [esi + (20*4)] ; ST = d*data[sample+20] d + fadd dword [edi + (20*4)] ; ST = autoc[20]+d*data[sample+20] d + fstp dword [edi + (20*4)] ; autoc[20]+=d*data[sample+20] ST = d + fld st0 ; ST = d d + fmul dword [esi + (19*4)] ; ST = d*data[sample+19] d + fadd dword [edi + (19*4)] ; ST = autoc[19]+d*data[sample+19] d + fstp dword [edi + (19*4)] ; autoc[19]+=d*data[sample+19] ST = d + fld st0 ; ST = d d + fmul dword [esi + (18*4)] ; ST = d*data[sample+18] d + fadd dword [edi + (18*4)] ; ST = autoc[18]+d*data[sample+18] d + fstp dword [edi + (18*4)] ; autoc[18]+=d*data[sample+18] ST = d + fld st0 ; ST = d d + fmul dword [esi + (17*4)] ; ST = d*data[sample+17] d + fadd dword [edi + (17*4)] ; ST = autoc[17]+d*data[sample+17] d + fstp dword [edi + (17*4)] ; autoc[17]+=d*data[sample+17] ST = d + fld st0 ; ST = d d + fmul dword [esi + (16*4)] ; ST = d*data[sample+16] d + fadd dword [edi + (16*4)] ; ST = autoc[16]+d*data[sample+16] d + fstp dword [edi + (16*4)] ; autoc[16]+=d*data[sample+16] ST = d + fld st0 ; ST = d d + fmul dword [esi + (15*4)] ; ST = d*data[sample+15] d + fadd dword [edi + (15*4)] ; ST = autoc[15]+d*data[sample+15] d + fstp dword [edi + (15*4)] ; autoc[15]+=d*data[sample+15] ST = d + fld st0 ; ST = d d + fmul dword [esi + (14*4)] ; ST = d*data[sample+14] d + fadd dword [edi + (14*4)] ; ST = autoc[14]+d*data[sample+14] d + fstp dword [edi + (14*4)] ; autoc[14]+=d*data[sample+14] ST = d + fld st0 ; ST = d d + fmul dword [esi + (13*4)] ; ST = d*data[sample+13] d + fadd dword [edi + (13*4)] ; ST = autoc[13]+d*data[sample+13] d + fstp dword [edi + (13*4)] ; autoc[13]+=d*data[sample+13] ST = d + fld st0 ; ST = d d + fmul dword [esi + (12*4)] ; ST = d*data[sample+12] d + fadd dword [edi + (12*4)] ; ST = autoc[12]+d*data[sample+12] d + fstp dword [edi + (12*4)] ; autoc[12]+=d*data[sample+12] ST = d + fld st0 ; ST = d d + fmul dword [esi + (11*4)] ; ST = d*data[sample+11] d + fadd dword [edi + (11*4)] ; ST = autoc[11]+d*data[sample+11] d + fstp dword [edi + (11*4)] ; autoc[11]+=d*data[sample+11] ST = d + fld st0 ; ST = d d + fmul dword [esi + (10*4)] ; ST = d*data[sample+10] d + fadd dword [edi + (10*4)] ; ST = autoc[10]+d*data[sample+10] d + fstp dword [edi + (10*4)] ; autoc[10]+=d*data[sample+10] ST = d + fld st0 ; ST = d d + fmul dword [esi + ( 9*4)] ; ST = d*data[sample+9] d + fadd dword [edi + ( 9*4)] ; ST = autoc[9]+d*data[sample+9] d + fstp dword [edi + ( 9*4)] ; autoc[9]+=d*data[sample+9] ST = d + fld st0 ; ST = d d + fmul dword [esi + ( 8*4)] ; ST = d*data[sample+8] d + fadd dword [edi + ( 8*4)] ; ST = autoc[8]+d*data[sample+8] d + fstp dword [edi + ( 8*4)] ; autoc[8]+=d*data[sample+8] ST = d + fld st0 ; ST = d d + fmul dword [esi + ( 7*4)] ; ST = d*data[sample+7] d + fadd dword [edi + ( 7*4)] ; ST = autoc[7]+d*data[sample+7] d + fstp dword [edi + ( 7*4)] ; autoc[7]+=d*data[sample+7] ST = d + fld st0 ; ST = d d + fmul dword [esi + ( 6*4)] ; ST = d*data[sample+6] d + fadd dword [edi + ( 6*4)] ; ST = autoc[6]+d*data[sample+6] d + fstp dword [edi + ( 6*4)] ; autoc[6]+=d*data[sample+6] ST = d + fld st0 ; ST = d d + fmul dword [esi + ( 5*4)] ; ST = d*data[sample+4] d + fadd dword [edi + ( 5*4)] ; ST = autoc[4]+d*data[sample+4] d + fstp dword [edi + ( 5*4)] ; autoc[4]+=d*data[sample+4] ST = d + fld st0 ; ST = d d + fmul dword [esi + ( 4*4)] ; ST = d*data[sample+4] d + fadd dword [edi + ( 4*4)] ; ST = autoc[4]+d*data[sample+4] d + fstp dword [edi + ( 4*4)] ; autoc[4]+=d*data[sample+4] ST = d + fld st0 ; ST = d d + fmul dword [esi + ( 3*4)] ; ST = d*data[sample+3] d + fadd dword [edi + ( 3*4)] ; ST = autoc[3]+d*data[sample+3] d + fstp dword [edi + ( 3*4)] ; autoc[3]+=d*data[sample+3] ST = d + fld st0 ; ST = d d + fmul dword [esi + ( 2*4)] ; ST = d*data[sample+2] d + fadd dword [edi + ( 2*4)] ; ST = autoc[2]+d*data[sample+2] d + fstp dword [edi + ( 2*4)] ; autoc[2]+=d*data[sample+2] ST = d + fld st0 ; ST = d d + fmul dword [esi + ( 1*4)] ; ST = d*data[sample+1] d + fadd dword [edi + ( 1*4)] ; ST = autoc[1]+d*data[sample+1] d + fstp dword [edi + ( 1*4)] ; autoc[1]+=d*data[sample+1] ST = d + fld st0 ; ST = d d + fmul dword [esi] ; ST = d*data[sample] d WATCHOUT: no displacement byte here! + fadd dword [edi] ; ST = autoc[0]+d*data[sample] d WATCHOUT: no displacement byte here! + fstp dword [edi] ; autoc[0]+=d*data[sample] ST = d WATCHOUT: no displacement byte here! +.jumper2_0: + + fstp st0 ; pop d, ST = empty + add esi, byte 4 ; sample++ + dec ecx + jz .loop2_end + add edx, byte 11 ; adjust our inner loop counter by adjusting the jump target + fld dword [esi] ; ST = d <- data[sample] + jmp edx +.loop2_end: + +.end: + pop ebx + pop edi + pop esi + ret + + ALIGN 16 +cident FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_4 + ;[esp + 16] == autoc[] + ;[esp + 12] == lag + ;[esp + 8] == data_len + ;[esp + 4] == data[] + + ;ASSERT(lag > 0) + ;ASSERT(lag <= 4) + ;ASSERT(lag <= data_len) + + ; for(coeff = 0; coeff < lag; coeff++) + ; autoc[coeff] = 0.0; + xorps xmm5, xmm5 + + mov edx, [esp + 8] ; edx == data_len + mov eax, [esp + 4] ; eax == &data[sample] <- &data[0] + + movss xmm0, [eax] ; xmm0 = 0,0,0,data[0] + add eax, 4 + movaps xmm2, xmm0 ; xmm2 = 0,0,0,data[0] + shufps xmm0, xmm0, 0 ; xmm0 == data[sample],data[sample],data[sample],data[sample] = data[0],data[0],data[0],data[0] +.warmup: ; xmm2 == data[sample-3],data[sample-2],data[sample-1],data[sample] + mulps xmm0, xmm2 ; xmm0 = xmm0 * xmm2 + addps xmm5, xmm0 ; xmm5 += xmm0 * xmm2 + dec edx + jz .loop_end + ALIGN 16 +.loop_start: + ; start by reading the next sample + movss xmm0, [eax] ; xmm0 = 0,0,0,data[sample] + add eax, 4 + shufps xmm0, xmm0, 0 ; xmm0 = data[sample],data[sample],data[sample],data[sample] + shufps xmm2, xmm2, 93h ; 93h=2-1-0-3 => xmm2 gets rotated left by one float + movss xmm2, xmm0 + mulps xmm0, xmm2 ; xmm0 = xmm0 * xmm2 + addps xmm5, xmm0 ; xmm5 += xmm0 * xmm2 + dec edx + jnz .loop_start +.loop_end: + ; store autoc + mov edx, [esp + 16] ; edx == autoc + movups [edx], xmm5 + +.end: + ret + + ALIGN 16 +cident FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_8 + ;[esp + 16] == autoc[] + ;[esp + 12] == lag + ;[esp + 8] == data_len + ;[esp + 4] == data[] + + ;ASSERT(lag > 0) + ;ASSERT(lag <= 8) + ;ASSERT(lag <= data_len) + + ; for(coeff = 0; coeff < lag; coeff++) + ; autoc[coeff] = 0.0; + xorps xmm5, xmm5 + xorps xmm6, xmm6 + + mov edx, [esp + 8] ; edx == data_len + mov eax, [esp + 4] ; eax == &data[sample] <- &data[0] + + movss xmm0, [eax] ; xmm0 = 0,0,0,data[0] + add eax, 4 + movaps xmm2, xmm0 ; xmm2 = 0,0,0,data[0] + shufps xmm0, xmm0, 0 ; xmm0 == data[sample],data[sample],data[sample],data[sample] = data[0],data[0],data[0],data[0] + movaps xmm1, xmm0 ; xmm1 == data[sample],data[sample],data[sample],data[sample] = data[0],data[0],data[0],data[0] + xorps xmm3, xmm3 ; xmm3 = 0,0,0,0 +.warmup: ; xmm3:xmm2 == data[sample-7],data[sample-6],...,data[sample] + mulps xmm0, xmm2 + mulps xmm1, xmm3 ; xmm1:xmm0 = xmm1:xmm0 * xmm3:xmm2 + addps xmm5, xmm0 + addps xmm6, xmm1 ; xmm6:xmm5 += xmm1:xmm0 * xmm3:xmm2 + dec edx + jz .loop_end + ALIGN 16 +.loop_start: + ; start by reading the next sample + movss xmm0, [eax] ; xmm0 = 0,0,0,data[sample] + ; here we reorder the instructions; see the (#) indexes for a logical order + shufps xmm2, xmm2, 93h ; (3) 93h=2-1-0-3 => xmm2 gets rotated left by one float + add eax, 4 ; (0) + shufps xmm3, xmm3, 93h ; (4) 93h=2-1-0-3 => xmm3 gets rotated left by one float + shufps xmm0, xmm0, 0 ; (1) xmm0 = data[sample],data[sample],data[sample],data[sample] + movss xmm3, xmm2 ; (5) + movaps xmm1, xmm0 ; (2) xmm1 = data[sample],data[sample],data[sample],data[sample] + movss xmm2, xmm0 ; (6) + mulps xmm1, xmm3 ; (8) + mulps xmm0, xmm2 ; (7) xmm1:xmm0 = xmm1:xmm0 * xmm3:xmm2 + addps xmm6, xmm1 ; (10) + addps xmm5, xmm0 ; (9) xmm6:xmm5 += xmm1:xmm0 * xmm3:xmm2 + dec edx + jnz .loop_start +.loop_end: + ; store autoc + mov edx, [esp + 16] ; edx == autoc + movups [edx], xmm5 + movups [edx + 16], xmm6 + +.end: + ret + + ALIGN 16 +cident FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_12 + ;[esp + 16] == autoc[] + ;[esp + 12] == lag + ;[esp + 8] == data_len + ;[esp + 4] == data[] + + ;ASSERT(lag > 0) + ;ASSERT(lag <= 12) + ;ASSERT(lag <= data_len) + + ; for(coeff = 0; coeff < lag; coeff++) + ; autoc[coeff] = 0.0; + xorps xmm5, xmm5 + xorps xmm6, xmm6 + xorps xmm7, xmm7 + + mov edx, [esp + 8] ; edx == data_len + mov eax, [esp + 4] ; eax == &data[sample] <- &data[0] + + movss xmm0, [eax] ; xmm0 = 0,0,0,data[0] + add eax, 4 + movaps xmm2, xmm0 ; xmm2 = 0,0,0,data[0] + shufps xmm0, xmm0, 0 ; xmm0 == data[sample],data[sample],data[sample],data[sample] = data[0],data[0],data[0],data[0] + xorps xmm3, xmm3 ; xmm3 = 0,0,0,0 + xorps xmm4, xmm4 ; xmm4 = 0,0,0,0 +.warmup: ; xmm3:xmm2 == data[sample-7],data[sample-6],...,data[sample] + movaps xmm1, xmm0 + mulps xmm1, xmm2 + addps xmm5, xmm1 + movaps xmm1, xmm0 + mulps xmm1, xmm3 + addps xmm6, xmm1 + mulps xmm0, xmm4 + addps xmm7, xmm0 ; xmm7:xmm6:xmm5 += xmm0:xmm0:xmm0 * xmm4:xmm3:xmm2 + dec edx + jz .loop_end + ALIGN 16 +.loop_start: + ; start by reading the next sample + movss xmm0, [eax] ; xmm0 = 0,0,0,data[sample] + add eax, 4 + shufps xmm0, xmm0, 0 ; xmm0 = data[sample],data[sample],data[sample],data[sample] + + ; shift xmm4:xmm3:xmm2 left by one float + shufps xmm2, xmm2, 93h ; 93h=2-1-0-3 => xmm2 gets rotated left by one float + shufps xmm3, xmm3, 93h ; 93h=2-1-0-3 => xmm3 gets rotated left by one float + shufps xmm4, xmm4, 93h ; 93h=2-1-0-3 => xmm4 gets rotated left by one float + movss xmm4, xmm3 + movss xmm3, xmm2 + movss xmm2, xmm0 + + ; xmm7:xmm6:xmm5 += xmm0:xmm0:xmm0 * xmm3:xmm3:xmm2 + movaps xmm1, xmm0 + mulps xmm1, xmm2 + addps xmm5, xmm1 + movaps xmm1, xmm0 + mulps xmm1, xmm3 + addps xmm6, xmm1 + mulps xmm0, xmm4 + addps xmm7, xmm0 + + dec edx + jnz .loop_start +.loop_end: + ; store autoc + mov edx, [esp + 16] ; edx == autoc + movups [edx], xmm5 + movups [edx + 16], xmm6 + movups [edx + 32], xmm7 + +.end: + ret + + align 16 +cident FLAC__lpc_compute_autocorrelation_asm_ia32_3dnow + ;[ebp + 32] autoc + ;[ebp + 28] lag + ;[ebp + 24] data_len + ;[ebp + 20] data + + push ebp + push ebx + push esi + push edi + mov ebp, esp + + mov esi, [ebp + 20] + mov edi, [ebp + 24] + mov edx, [ebp + 28] + inc edx + and edx, byte -2 + mov eax, edx + neg eax + and esp, byte -8 + lea esp, [esp + 4 * eax] + mov ecx, edx + xor eax, eax +.loop0: + dec ecx + mov [esp + 4 * ecx], eax + jnz short .loop0 + + mov eax, edi + sub eax, edx + mov ebx, edx + and ebx, byte 1 + sub eax, ebx + lea ecx, [esi + 4 * eax - 12] + cmp esi, ecx + mov eax, esi + ja short .loop2_pre + align 16 ;4 nops +.loop1_i: + movd mm0, [eax] + movd mm2, [eax + 4] + movd mm4, [eax + 8] + movd mm6, [eax + 12] + mov ebx, edx + punpckldq mm0, mm0 + punpckldq mm2, mm2 + punpckldq mm4, mm4 + punpckldq mm6, mm6 + align 16 ;3 nops +.loop1_j: + sub ebx, byte 2 + movd mm1, [eax + 4 * ebx] + movd mm3, [eax + 4 * ebx + 4] + movd mm5, [eax + 4 * ebx + 8] + movd mm7, [eax + 4 * ebx + 12] + punpckldq mm1, mm3 + punpckldq mm3, mm5 + pfmul mm1, mm0 + punpckldq mm5, mm7 + pfmul mm3, mm2 + punpckldq mm7, [eax + 4 * ebx + 16] + pfmul mm5, mm4 + pfmul mm7, mm6 + pfadd mm1, mm3 + movq mm3, [esp + 4 * ebx] + pfadd mm5, mm7 + pfadd mm1, mm5 + pfadd mm3, mm1 + movq [esp + 4 * ebx], mm3 + jg short .loop1_j + + add eax, byte 16 + cmp eax, ecx + jb short .loop1_i + +.loop2_pre: + mov ebx, eax + sub eax, esi + shr eax, 2 + lea ecx, [esi + 4 * edi] + mov esi, ebx +.loop2_i: + movd mm0, [esi] + mov ebx, edi + sub ebx, eax + cmp ebx, edx + jbe short .loop2_j + mov ebx, edx +.loop2_j: + dec ebx + movd mm1, [esi + 4 * ebx] + pfmul mm1, mm0 + movd mm2, [esp + 4 * ebx] + pfadd mm1, mm2 + movd [esp + 4 * ebx], mm1 + + jnz short .loop2_j + + add esi, byte 4 + inc eax + cmp esi, ecx + jnz short .loop2_i + + mov edi, [ebp + 32] + mov edx, [ebp + 28] +.loop3: + dec edx + mov eax, [esp + 4 * edx] + mov [edi + 4 * edx], eax + jnz short .loop3 + + femms + + mov esp, ebp + pop edi + pop esi + pop ebx + pop ebp + ret + +;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[]) +; +; 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); +; } +; + ALIGN 16 +cident FLAC__lpc_compute_residual_from_qlp_coefficients_asm_ia32 + ;[esp + 40] residual[] + ;[esp + 36] lp_quantization + ;[esp + 32] order + ;[esp + 28] qlp_coeff[] + ;[esp + 24] data_len + ;[esp + 20] data[] + + ;ASSERT(order > 0) + + push ebp + push ebx + push esi + push edi + + mov esi, [esp + 20] ; esi = data[] + mov edi, [esp + 40] ; edi = residual[] + mov eax, [esp + 32] ; eax = order + mov ebx, [esp + 24] ; ebx = data_len + + test ebx, ebx + jz near .end ; do nothing if data_len == 0 +.begin: + cmp eax, byte 1 + jg short .i_1more + + mov ecx, [esp + 28] + mov edx, [ecx] ; edx = qlp_coeff[0] + mov eax, [esi - 4] ; eax = data[-1] + mov cl, [esp + 36] ; cl = lp_quantization + ALIGN 16 +.i_1_loop_i: + imul eax, edx + sar eax, cl + neg eax + add eax, [esi] + mov [edi], eax + mov eax, [esi] + add edi, byte 4 + add esi, byte 4 + dec ebx + jnz .i_1_loop_i + + jmp .end + +.i_1more: + cmp eax, byte 32 ; for order <= 32 there is a faster routine + jbe short .i_32 + + ; This version is here just for completeness, since FLAC__MAX_LPC_ORDER == 32 + ALIGN 16 +.i_32more_loop_i: + xor ebp, ebp + mov ecx, [esp + 32] + mov edx, ecx + shl edx, 2 + add edx, [esp + 28] + neg ecx + ALIGN 16 +.i_32more_loop_j: + sub edx, byte 4 + mov eax, [edx] + imul eax, [esi + 4 * ecx] + add ebp, eax + inc ecx + jnz short .i_32more_loop_j + + mov cl, [esp + 36] + sar ebp, cl + neg ebp + add ebp, [esi] + mov [edi], ebp + add esi, byte 4 + add edi, byte 4 + + dec ebx + jnz .i_32more_loop_i + + jmp .end + +.i_32: + sub edi, esi + neg eax + lea edx, [eax + eax * 8 + .jumper_0 - .get_eip0] + call .get_eip0 +.get_eip0: + pop eax + add edx, eax + inc edx + mov eax, [esp + 28] ; eax = qlp_coeff[] + xor ebp, ebp + jmp edx + + mov ecx, [eax + 124] + imul ecx, [esi - 128] + add ebp, ecx + mov ecx, [eax + 120] + imul ecx, [esi - 124] + add ebp, ecx + mov ecx, [eax + 116] + imul ecx, [esi - 120] + add ebp, ecx + mov ecx, [eax + 112] + imul ecx, [esi - 116] + add ebp, ecx + mov ecx, [eax + 108] + imul ecx, [esi - 112] + add ebp, ecx + mov ecx, [eax + 104] + imul ecx, [esi - 108] + add ebp, ecx + mov ecx, [eax + 100] + imul ecx, [esi - 104] + add ebp, ecx + mov ecx, [eax + 96] + imul ecx, [esi - 100] + add ebp, ecx + mov ecx, [eax + 92] + imul ecx, [esi - 96] + add ebp, ecx + mov ecx, [eax + 88] + imul ecx, [esi - 92] + add ebp, ecx + mov ecx, [eax + 84] + imul ecx, [esi - 88] + add ebp, ecx + mov ecx, [eax + 80] + imul ecx, [esi - 84] + add ebp, ecx + mov ecx, [eax + 76] + imul ecx, [esi - 80] + add ebp, ecx + mov ecx, [eax + 72] + imul ecx, [esi - 76] + add ebp, ecx + mov ecx, [eax + 68] + imul ecx, [esi - 72] + add ebp, ecx + mov ecx, [eax + 64] + imul ecx, [esi - 68] + add ebp, ecx + mov ecx, [eax + 60] + imul ecx, [esi - 64] + add ebp, ecx + mov ecx, [eax + 56] + imul ecx, [esi - 60] + add ebp, ecx + mov ecx, [eax + 52] + imul ecx, [esi - 56] + add ebp, ecx + mov ecx, [eax + 48] + imul ecx, [esi - 52] + add ebp, ecx + mov ecx, [eax + 44] + imul ecx, [esi - 48] + add ebp, ecx + mov ecx, [eax + 40] + imul ecx, [esi - 44] + add ebp, ecx + mov ecx, [eax + 36] + imul ecx, [esi - 40] + add ebp, ecx + mov ecx, [eax + 32] + imul ecx, [esi - 36] + add ebp, ecx + mov ecx, [eax + 28] + imul ecx, [esi - 32] + add ebp, ecx + mov ecx, [eax + 24] + imul ecx, [esi - 28] + add ebp, ecx + mov ecx, [eax + 20] + imul ecx, [esi - 24] + add ebp, ecx + mov ecx, [eax + 16] + imul ecx, [esi - 20] + add ebp, ecx + mov ecx, [eax + 12] + imul ecx, [esi - 16] + add ebp, ecx + mov ecx, [eax + 8] + imul ecx, [esi - 12] + add ebp, ecx + mov ecx, [eax + 4] + imul ecx, [esi - 8] + add ebp, ecx + mov ecx, [eax] ; there is one byte missing + imul ecx, [esi - 4] + add ebp, ecx +.jumper_0: + + mov cl, [esp + 36] + sar ebp, cl + neg ebp + add ebp, [esi] + mov [edi + esi], ebp + add esi, byte 4 + + dec ebx + jz short .end + xor ebp, ebp + jmp edx + +.end: + pop edi + pop esi + pop ebx + pop ebp + ret + +; WATCHOUT: this routine works on 16 bit data which means bits-per-sample for +; the channel must be <= 16. Especially note that this routine cannot be used +; for side-channel coded 16bps channels since the effective bps is 17. + ALIGN 16 +cident FLAC__lpc_compute_residual_from_qlp_coefficients_asm_ia32_mmx + ;[esp + 40] residual[] + ;[esp + 36] lp_quantization + ;[esp + 32] order + ;[esp + 28] qlp_coeff[] + ;[esp + 24] data_len + ;[esp + 20] data[] + + ;ASSERT(order > 0) + + push ebp + push ebx + push esi + push edi + + mov esi, [esp + 20] ; esi = data[] + mov edi, [esp + 40] ; edi = residual[] + mov eax, [esp + 32] ; eax = order + mov ebx, [esp + 24] ; ebx = data_len + + test ebx, ebx + jz near .end ; do nothing if data_len == 0 + dec ebx + test ebx, ebx + jz near .last_one + + mov edx, [esp + 28] ; edx = qlp_coeff[] + movd mm6, [esp + 36] ; mm6 = 0:lp_quantization + mov ebp, esp + + and esp, 0xfffffff8 + + xor ecx, ecx +.copy_qlp_loop: + push word [edx + 4 * ecx] + inc ecx + cmp ecx, eax + jnz short .copy_qlp_loop + + and ecx, 0x3 + test ecx, ecx + je short .za_end + sub ecx, byte 4 +.za_loop: + push word 0 + inc eax + inc ecx + jnz short .za_loop +.za_end: + + movq mm5, [esp + 2 * eax - 8] + movd mm4, [esi - 16] + punpckldq mm4, [esi - 12] + movd mm0, [esi - 8] + punpckldq mm0, [esi - 4] + packssdw mm4, mm0 + + cmp eax, byte 4 + jnbe short .mmx_4more + + align 16 +.mmx_4_loop_i: + movd mm1, [esi] + movq mm3, mm4 + punpckldq mm1, [esi + 4] + psrlq mm4, 16 + movq mm0, mm1 + psllq mm0, 48 + por mm4, mm0 + movq mm2, mm4 + psrlq mm4, 16 + pxor mm0, mm0 + punpckhdq mm0, mm1 + pmaddwd mm3, mm5 + pmaddwd mm2, mm5 + psllq mm0, 16 + por mm4, mm0 + movq mm0, mm3 + punpckldq mm3, mm2 + punpckhdq mm0, mm2 + paddd mm3, mm0 + psrad mm3, mm6 + psubd mm1, mm3 + movd [edi], mm1 + punpckhdq mm1, mm1 + movd [edi + 4], mm1 + + add edi, byte 8 + add esi, byte 8 + + sub ebx, 2 + jg .mmx_4_loop_i + jmp .mmx_end + +.mmx_4more: + shl eax, 2 + neg eax + add eax, byte 16 + + align 16 +.mmx_4more_loop_i: + movd mm1, [esi] + punpckldq mm1, [esi + 4] + movq mm3, mm4 + psrlq mm4, 16 + movq mm0, mm1 + psllq mm0, 48 + por mm4, mm0 + movq mm2, mm4 + psrlq mm4, 16 + pxor mm0, mm0 + punpckhdq mm0, mm1 + pmaddwd mm3, mm5 + pmaddwd mm2, mm5 + psllq mm0, 16 + por mm4, mm0 + + mov ecx, esi + add ecx, eax + mov edx, esp + + align 16 +.mmx_4more_loop_j: + movd mm0, [ecx - 16] + movd mm7, [ecx - 8] + punpckldq mm0, [ecx - 12] + punpckldq mm7, [ecx - 4] + packssdw mm0, mm7 + pmaddwd mm0, [edx] + punpckhdq mm7, mm7 + paddd mm3, mm0 + movd mm0, [ecx - 12] + punpckldq mm0, [ecx - 8] + punpckldq mm7, [ecx] + packssdw mm0, mm7 + pmaddwd mm0, [edx] + paddd mm2, mm0 + + add edx, byte 8 + add ecx, byte 16 + cmp ecx, esi + jnz .mmx_4more_loop_j + + movq mm0, mm3 + punpckldq mm3, mm2 + punpckhdq mm0, mm2 + paddd mm3, mm0 + psrad mm3, mm6 + psubd mm1, mm3 + movd [edi], mm1 + punpckhdq mm1, mm1 + movd [edi + 4], mm1 + + add edi, byte 8 + add esi, byte 8 + + sub ebx, 2 + jg near .mmx_4more_loop_i + +.mmx_end: + emms + mov esp, ebp +.last_one: + mov eax, [esp + 32] + inc ebx + jnz near FLAC__lpc_compute_residual_from_qlp_coefficients_asm_ia32.begin + +.end: + pop edi + pop esi + pop ebx + pop ebp + ret + +; ********************************************************************** +; +; 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[]) +; { +; unsigned i, j; +; FLAC__int32 sum; +; +; FLAC__ASSERT(order > 0); +; +; 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); +; } +; } + ALIGN 16 +cident FLAC__lpc_restore_signal_asm_ia32 + ;[esp + 40] data[] + ;[esp + 36] lp_quantization + ;[esp + 32] order + ;[esp + 28] qlp_coeff[] + ;[esp + 24] data_len + ;[esp + 20] residual[] + + ;ASSERT(order > 0) + + push ebp + push ebx + push esi + push edi + + mov esi, [esp + 20] ; esi = residual[] + mov edi, [esp + 40] ; edi = data[] + mov eax, [esp + 32] ; eax = order + mov ebx, [esp + 24] ; ebx = data_len + + test ebx, ebx + jz near .end ; do nothing if data_len == 0 + +.begin: + cmp eax, byte 1 + jg short .x87_1more + + mov ecx, [esp + 28] + mov edx, [ecx] + mov eax, [edi - 4] + mov cl, [esp + 36] + ALIGN 16 +.x87_1_loop_i: + imul eax, edx + sar eax, cl + add eax, [esi] + mov [edi], eax + add esi, byte 4 + add edi, byte 4 + dec ebx + jnz .x87_1_loop_i + + jmp .end + +.x87_1more: + cmp eax, byte 32 ; for order <= 32 there is a faster routine + jbe short .x87_32 + + ; This version is here just for completeness, since FLAC__MAX_LPC_ORDER == 32 + ALIGN 16 +.x87_32more_loop_i: + xor ebp, ebp + mov ecx, [esp + 32] + mov edx, ecx + shl edx, 2 + add edx, [esp + 28] + neg ecx + ALIGN 16 +.x87_32more_loop_j: + sub edx, byte 4 + mov eax, [edx] + imul eax, [edi + 4 * ecx] + add ebp, eax + inc ecx + jnz short .x87_32more_loop_j + + mov cl, [esp + 36] + sar ebp, cl + add ebp, [esi] + mov [edi], ebp + add edi, byte 4 + add esi, byte 4 + + dec ebx + jnz .x87_32more_loop_i + + jmp .end + +.x87_32: + sub esi, edi + neg eax + lea edx, [eax + eax * 8 + .jumper_0 - .get_eip0] + call .get_eip0 +.get_eip0: + pop eax + add edx, eax + inc edx ; compensate for the shorter opcode on the last iteration + mov eax, [esp + 28] ; eax = qlp_coeff[] + xor ebp, ebp + jmp edx + + mov ecx, [eax + 124] ; ecx = qlp_coeff[31] + imul ecx, [edi - 128] ; ecx = qlp_coeff[31] * data[i-32] + add ebp, ecx ; sum += qlp_coeff[31] * data[i-32] + mov ecx, [eax + 120] ; ecx = qlp_coeff[30] + imul ecx, [edi - 124] ; ecx = qlp_coeff[30] * data[i-31] + add ebp, ecx ; sum += qlp_coeff[30] * data[i-31] + mov ecx, [eax + 116] ; ecx = qlp_coeff[29] + imul ecx, [edi - 120] ; ecx = qlp_coeff[29] * data[i-30] + add ebp, ecx ; sum += qlp_coeff[29] * data[i-30] + mov ecx, [eax + 112] ; ecx = qlp_coeff[28] + imul ecx, [edi - 116] ; ecx = qlp_coeff[28] * data[i-29] + add ebp, ecx ; sum += qlp_coeff[28] * data[i-29] + mov ecx, [eax + 108] ; ecx = qlp_coeff[27] + imul ecx, [edi - 112] ; ecx = qlp_coeff[27] * data[i-28] + add ebp, ecx ; sum += qlp_coeff[27] * data[i-28] + mov ecx, [eax + 104] ; ecx = qlp_coeff[26] + imul ecx, [edi - 108] ; ecx = qlp_coeff[26] * data[i-27] + add ebp, ecx ; sum += qlp_coeff[26] * data[i-27] + mov ecx, [eax + 100] ; ecx = qlp_coeff[25] + imul ecx, [edi - 104] ; ecx = qlp_coeff[25] * data[i-26] + add ebp, ecx ; sum += qlp_coeff[25] * data[i-26] + mov ecx, [eax + 96] ; ecx = qlp_coeff[24] + imul ecx, [edi - 100] ; ecx = qlp_coeff[24] * data[i-25] + add ebp, ecx ; sum += qlp_coeff[24] * data[i-25] + mov ecx, [eax + 92] ; ecx = qlp_coeff[23] + imul ecx, [edi - 96] ; ecx = qlp_coeff[23] * data[i-24] + add ebp, ecx ; sum += qlp_coeff[23] * data[i-24] + mov ecx, [eax + 88] ; ecx = qlp_coeff[22] + imul ecx, [edi - 92] ; ecx = qlp_coeff[22] * data[i-23] + add ebp, ecx ; sum += qlp_coeff[22] * data[i-23] + mov ecx, [eax + 84] ; ecx = qlp_coeff[21] + imul ecx, [edi - 88] ; ecx = qlp_coeff[21] * data[i-22] + add ebp, ecx ; sum += qlp_coeff[21] * data[i-22] + mov ecx, [eax + 80] ; ecx = qlp_coeff[20] + imul ecx, [edi - 84] ; ecx = qlp_coeff[20] * data[i-21] + add ebp, ecx ; sum += qlp_coeff[20] * data[i-21] + mov ecx, [eax + 76] ; ecx = qlp_coeff[19] + imul ecx, [edi - 80] ; ecx = qlp_coeff[19] * data[i-20] + add ebp, ecx ; sum += qlp_coeff[19] * data[i-20] + mov ecx, [eax + 72] ; ecx = qlp_coeff[18] + imul ecx, [edi - 76] ; ecx = qlp_coeff[18] * data[i-19] + add ebp, ecx ; sum += qlp_coeff[18] * data[i-19] + mov ecx, [eax + 68] ; ecx = qlp_coeff[17] + imul ecx, [edi - 72] ; ecx = qlp_coeff[17] * data[i-18] + add ebp, ecx ; sum += qlp_coeff[17] * data[i-18] + mov ecx, [eax + 64] ; ecx = qlp_coeff[16] + imul ecx, [edi - 68] ; ecx = qlp_coeff[16] * data[i-17] + add ebp, ecx ; sum += qlp_coeff[16] * data[i-17] + mov ecx, [eax + 60] ; ecx = qlp_coeff[15] + imul ecx, [edi - 64] ; ecx = qlp_coeff[15] * data[i-16] + add ebp, ecx ; sum += qlp_coeff[15] * data[i-16] + mov ecx, [eax + 56] ; ecx = qlp_coeff[14] + imul ecx, [edi - 60] ; ecx = qlp_coeff[14] * data[i-15] + add ebp, ecx ; sum += qlp_coeff[14] * data[i-15] + mov ecx, [eax + 52] ; ecx = qlp_coeff[13] + imul ecx, [edi - 56] ; ecx = qlp_coeff[13] * data[i-14] + add ebp, ecx ; sum += qlp_coeff[13] * data[i-14] + mov ecx, [eax + 48] ; ecx = qlp_coeff[12] + imul ecx, [edi - 52] ; ecx = qlp_coeff[12] * data[i-13] + add ebp, ecx ; sum += qlp_coeff[12] * data[i-13] + mov ecx, [eax + 44] ; ecx = qlp_coeff[11] + imul ecx, [edi - 48] ; ecx = qlp_coeff[11] * data[i-12] + add ebp, ecx ; sum += qlp_coeff[11] * data[i-12] + mov ecx, [eax + 40] ; ecx = qlp_coeff[10] + imul ecx, [edi - 44] ; ecx = qlp_coeff[10] * data[i-11] + add ebp, ecx ; sum += qlp_coeff[10] * data[i-11] + mov ecx, [eax + 36] ; ecx = qlp_coeff[ 9] + imul ecx, [edi - 40] ; ecx = qlp_coeff[ 9] * data[i-10] + add ebp, ecx ; sum += qlp_coeff[ 9] * data[i-10] + mov ecx, [eax + 32] ; ecx = qlp_coeff[ 8] + imul ecx, [edi - 36] ; ecx = qlp_coeff[ 8] * data[i- 9] + add ebp, ecx ; sum += qlp_coeff[ 8] * data[i- 9] + mov ecx, [eax + 28] ; ecx = qlp_coeff[ 7] + imul ecx, [edi - 32] ; ecx = qlp_coeff[ 7] * data[i- 8] + add ebp, ecx ; sum += qlp_coeff[ 7] * data[i- 8] + mov ecx, [eax + 24] ; ecx = qlp_coeff[ 6] + imul ecx, [edi - 28] ; ecx = qlp_coeff[ 6] * data[i- 7] + add ebp, ecx ; sum += qlp_coeff[ 6] * data[i- 7] + mov ecx, [eax + 20] ; ecx = qlp_coeff[ 5] + imul ecx, [edi - 24] ; ecx = qlp_coeff[ 5] * data[i- 6] + add ebp, ecx ; sum += qlp_coeff[ 5] * data[i- 6] + mov ecx, [eax + 16] ; ecx = qlp_coeff[ 4] + imul ecx, [edi - 20] ; ecx = qlp_coeff[ 4] * data[i- 5] + add ebp, ecx ; sum += qlp_coeff[ 4] * data[i- 5] + mov ecx, [eax + 12] ; ecx = qlp_coeff[ 3] + imul ecx, [edi - 16] ; ecx = qlp_coeff[ 3] * data[i- 4] + add ebp, ecx ; sum += qlp_coeff[ 3] * data[i- 4] + mov ecx, [eax + 8] ; ecx = qlp_coeff[ 2] + imul ecx, [edi - 12] ; ecx = qlp_coeff[ 2] * data[i- 3] + add ebp, ecx ; sum += qlp_coeff[ 2] * data[i- 3] + mov ecx, [eax + 4] ; ecx = qlp_coeff[ 1] + imul ecx, [edi - 8] ; ecx = qlp_coeff[ 1] * data[i- 2] + add ebp, ecx ; sum += qlp_coeff[ 1] * data[i- 2] + mov ecx, [eax] ; ecx = qlp_coeff[ 0] (NOTE: one byte missing from instruction) + imul ecx, [edi - 4] ; ecx = qlp_coeff[ 0] * data[i- 1] + add ebp, ecx ; sum += qlp_coeff[ 0] * data[i- 1] +.jumper_0: + + mov cl, [esp + 36] + sar ebp, cl ; ebp = (sum >> lp_quantization) + add ebp, [esi + edi] ; ebp = residual[i] + (sum >> lp_quantization) + mov [edi], ebp ; data[i] = residual[i] + (sum >> lp_quantization) + add edi, byte 4 + + dec ebx + jz short .end + xor ebp, ebp + jmp edx + +.end: + pop edi + pop esi + pop ebx + pop ebp + ret + +; WATCHOUT: this routine works on 16 bit data which means bits-per-sample for +; the channel must be <= 16. Especially note that this routine cannot be used +; for side-channel coded 16bps channels since the effective bps is 17. +; WATCHOUT: this routine requires that each data array have a buffer of up to +; 3 zeroes in front (at negative indices) for alignment purposes, i.e. for each +; channel n, data[n][-1] through data[n][-3] should be accessible and zero. + ALIGN 16 +cident FLAC__lpc_restore_signal_asm_ia32_mmx + ;[esp + 40] data[] + ;[esp + 36] lp_quantization + ;[esp + 32] order + ;[esp + 28] qlp_coeff[] + ;[esp + 24] data_len + ;[esp + 20] residual[] + + ;ASSERT(order > 0) + + push ebp + push ebx + push esi + push edi + + mov esi, [esp + 20] + mov edi, [esp + 40] + mov eax, [esp + 32] + mov ebx, [esp + 24] + + test ebx, ebx + jz near .end ; do nothing if data_len == 0 + cmp eax, byte 4 + jb near FLAC__lpc_restore_signal_asm_ia32.begin + + mov edx, [esp + 28] + movd mm6, [esp + 36] + mov ebp, esp + + and esp, 0xfffffff8 + + xor ecx, ecx +.copy_qlp_loop: + push word [edx + 4 * ecx] + inc ecx + cmp ecx, eax + jnz short .copy_qlp_loop + + and ecx, 0x3 + test ecx, ecx + je short .za_end + sub ecx, byte 4 +.za_loop: + push word 0 + inc eax + inc ecx + jnz short .za_loop +.za_end: + + movq mm5, [esp + 2 * eax - 8] + movd mm4, [edi - 16] + punpckldq mm4, [edi - 12] + movd mm0, [edi - 8] + punpckldq mm0, [edi - 4] + packssdw mm4, mm0 + + cmp eax, byte 4 + jnbe short .mmx_4more + + align 16 +.mmx_4_loop_i: + movq mm7, mm4 + pmaddwd mm7, mm5 + movq mm0, mm7 + punpckhdq mm7, mm7 + paddd mm7, mm0 + psrad mm7, mm6 + movd mm1, [esi] + paddd mm7, mm1 + movd [edi], mm7 + psllq mm7, 48 + psrlq mm4, 16 + por mm4, mm7 + + add esi, byte 4 + add edi, byte 4 + + dec ebx + jnz .mmx_4_loop_i + jmp .mmx_end +.mmx_4more: + shl eax, 2 + neg eax + add eax, byte 16 + align 16 +.mmx_4more_loop_i: + mov ecx, edi + add ecx, eax + mov edx, esp + + movq mm7, mm4 + pmaddwd mm7, mm5 + + align 16 +.mmx_4more_loop_j: + movd mm0, [ecx - 16] + punpckldq mm0, [ecx - 12] + movd mm1, [ecx - 8] + punpckldq mm1, [ecx - 4] + packssdw mm0, mm1 + pmaddwd mm0, [edx] + paddd mm7, mm0 + + add edx, byte 8 + add ecx, byte 16 + cmp ecx, edi + jnz .mmx_4more_loop_j + + movq mm0, mm7 + punpckhdq mm7, mm7 + paddd mm7, mm0 + psrad mm7, mm6 + movd mm1, [esi] + paddd mm7, mm1 + movd [edi], mm7 + psllq mm7, 48 + psrlq mm4, 16 + por mm4, mm7 + + add esi, byte 4 + add edi, byte 4 + + dec ebx + jnz short .mmx_4more_loop_i +.mmx_end: + emms + mov esp, ebp + +.end: + pop edi + pop esi + pop ebx + pop ebp + ret + +end diff --git a/FLAC/ia32/nasm.h b/FLAC/ia32/nasm.h new file mode 100644 index 00000000000..00aecef3aad --- /dev/null +++ b/FLAC/ia32/nasm.h @@ -0,0 +1,75 @@ +; libFLAC - Free Lossless Audio Codec library +; Copyright (C) 2001,2002,2003 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. + + bits 32 + +%ifdef OBJ_FORMAT_win32 + %define FLAC__PUBLIC_NEEDS_UNDERSCORE + %idefine code_section section .text align=16 class=CODE use32 + %idefine data_section section .data align=32 class=DATA use32 + %idefine bss_section section .bss align=32 class=DATA use32 +%elifdef OBJ_FORMAT_aout + %define FLAC__PUBLIC_NEEDS_UNDERSCORE + %idefine code_section section .text + %idefine data_section section .data + %idefine bss_section section .bss +%elifdef OBJ_FORMAT_aoutb + %define FLAC__PUBLIC_NEEDS_UNDERSCORE + %idefine code_section section .text + %idefine data_section section .data + %idefine bss_section section .bss +%elifdef OBJ_FORMAT_elf + %idefine code_section section .text align=16 + %idefine data_section section .data align=32 + %idefine bss_section section .bss align=32 +%else + %error unsupported object format! +%endif + +%imacro cglobal 1 + %ifdef FLAC__PUBLIC_NEEDS_UNDERSCORE + global _%1 + %else + global %1 + %endif +%endmacro + +%imacro cextern 1 + %ifdef FLAC__PUBLIC_NEEDS_UNDERSCORE + extern _%1 + %else + extern %1 + %endif +%endmacro + +%imacro cident 1 +_%1: +%1: +%endmacro diff --git a/FLAC/lpc.c b/FLAC/lpc.c new file mode 100644 index 00000000000..275b707a359 --- /dev/null +++ b/FLAC/lpc.c @@ -0,0 +1,423 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2000,2001,2002,2003,2004 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. + */ + +#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 M_LN2 +/* math.h in VC++ doesn't seem to have this (how Microsoft is that?) */ +#define M_LN2 0.69314718055994530942 +#endif + +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); + + 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__real error[]) +{ + unsigned i, j; + double r, err, ref[FLAC__MAX_LPC_ORDER], lpc[FLAC__MAX_LPC_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++) { + 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] = (FLAC__real)err; + } +} + +int FLAC__lpc_quantize_coefficients(const FLAC__real lp_coeff[], unsigned order, unsigned precision, FLAC__int32 qlp_coeff[], int *shift) +{ + unsigned i; + double d, cmax = -1e32; + FLAC__int32 qmax, qmin; + const int max_shiftlimit = (1 << (FLAC__SUBFRAME_LPC_QLP_SHIFT_LEN-1)) - 1; + const int min_shiftlimit = -max_shiftlimit - 1; + + 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--; + + for(i = 0; i < order; i++) { + if(lp_coeff[i] == 0.0) + continue; + d = fabs(lp_coeff[i]); + if(d > cmax) + cmax = d; + } +redo_it: + if(cmax <= 0.0) { + /* => coefficients are all 0, which means our constant-detect didn't work */ + return 2; + } + else { + int log2cmax; + + (void)frexp(cmax, &log2cmax); + log2cmax--; + *shift = (int)precision - log2cmax - 1; + + if(*shift < min_shiftlimit || *shift > max_shiftlimit) { +#if 0 + /*@@@ this does not seem to help at all, but was not extensively tested either: */ + if(*shift > max_shiftlimit) + *shift = max_shiftlimit; + else +#endif + return 1; + } + } + + if(*shift >= 0) { + for(i = 0; i < order; i++) { + qlp_coeff[i] = (FLAC__int32)floor((double)lp_coeff[i] * (double)(1 << *shift)); + + /* double-check the result */ + if(qlp_coeff[i] > qmax || qlp_coeff[i] < qmin) { +#ifdef FLAC__OVERFLOW_DETECT + fprintf(stderr,"FLAC__lpc_quantize_coefficients: compensating for overflow, qlp_coeff[%u]=%d, lp_coeff[%u]=%f, cmax=%f, precision=%u, shift=%d, q=%f, f(q)=%f\n", i, qlp_coeff[i], i, lp_coeff[i], cmax, precision, *shift, (double)lp_coeff[i] * (double)(1 << *shift), floor((double)lp_coeff[i] * (double)(1 << *shift))); +#endif + cmax *= 2.0; + goto redo_it; + } + } + } + else { /* (*shift < 0) */ + const int nshift = -(*shift); +#ifdef DEBUG + fprintf(stderr,"FLAC__lpc_quantize_coefficients: negative shift = %d\n", *shift); +#endif + for(i = 0; i < order; i++) { + qlp_coeff[i] = (FLAC__int32)floor((double)lp_coeff[i] / (double)(1 << nshift)); + + /* double-check the result */ + if(qlp_coeff[i] > qmax || qlp_coeff[i] < qmin) { +#ifdef FLAC__OVERFLOW_DETECT + fprintf(stderr,"FLAC__lpc_quantize_coefficients: compensating for overflow, qlp_coeff[%u]=%d, lp_coeff[%u]=%f, cmax=%f, precision=%u, shift=%d, q=%f, f(q)=%f\n", i, qlp_coeff[i], i, lp_coeff[i], cmax, precision, *shift, (double)lp_coeff[i] / (double)(1 << nshift), floor((double)lp_coeff[i] / (double)(1 << nshift))); +#endif + cmax *= 2.0; + goto redo_it; + } + } + } + + 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[]) +{ +#ifdef FLAC__OVERFLOW_DETECT + FLAC__int64 sumo; +#endif + 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++) { +#ifdef FLAC__OVERFLOW_DETECT + sumo = 0; +#endif + sum = 0; + history = data; + for(j = 0; j < order; j++) { + sum += qlp_coeff[j] * (*(--history)); +#ifdef FLAC__OVERFLOW_DETECT + 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,sumo); +#endif +#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); + } + */ +} + +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[]) +{ + 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)); +#ifdef FLAC__OVERFLOW_DETECT + if(FLAC__bitmath_silog2_wide(sum >> lp_quantization) > 32) { + fprintf(stderr,"FLAC__lpc_compute_residual_from_qlp_coefficients_wide: OVERFLOW, i=%u, sum=%lld\n", i, sum >> lp_quantization); + break; + } + if(FLAC__bitmath_silog2_wide((FLAC__int64)(*data) - (sum >> lp_quantization)) > 32) { + fprintf(stderr,"FLAC__lpc_compute_residual_from_qlp_coefficients_wide: OVERFLOW, i=%u, data=%d, sum=%lld, residual=%lld\n", i, *data, sum >> lp_quantization, (FLAC__int64)(*data) - (sum >> lp_quantization)); + break; + } +#endif + *(residual++) = *(data++) - (FLAC__int32)(sum >> lp_quantization); + } +} + +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[]) +{ +#ifdef FLAC__OVERFLOW_DETECT + FLAC__int64 sumo; +#endif + unsigned i, j; + FLAC__int32 sum; + const FLAC__int32 *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++) { +#ifdef FLAC__OVERFLOW_DETECT + sumo = 0; +#endif + sum = 0; + history = data; + for(j = 0; j < order; j++) { + sum += qlp_coeff[j] * (*(--history)); +#ifdef FLAC__OVERFLOW_DETECT + 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,sumo); +#endif +#endif + } + *(data++) = *(residual++) + (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); + } + */ +} + +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[]) +{ + unsigned i, j; + FLAC__int64 sum; + const FLAC__int32 *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)); +#ifdef FLAC__OVERFLOW_DETECT + if(FLAC__bitmath_silog2_wide(sum >> lp_quantization) > 32) { + fprintf(stderr,"FLAC__lpc_restore_signal_wide: OVERFLOW, i=%u, sum=%lld\n", i, sum >> lp_quantization); + break; + } + if(FLAC__bitmath_silog2_wide((FLAC__int64)(*residual) + (sum >> lp_quantization)) > 32) { + fprintf(stderr,"FLAC__lpc_restore_signal_wide: OVERFLOW, i=%u, residual=%d, sum=%lld, data=%lld\n", i, *residual, sum >> lp_quantization, (FLAC__int64)(*residual) + (sum >> lp_quantization)); + break; + } +#endif + *(data++) = *(residual++) + (FLAC__int32)(sum >> lp_quantization); + } +} + +FLAC__real FLAC__lpc_compute_expected_bits_per_residual_sample(FLAC__real lpc_error, unsigned total_samples) +{ + double error_scale; + + FLAC__ASSERT(total_samples > 0); + + error_scale = 0.5 * M_LN2 * M_LN2 / (FLAC__real)total_samples; + + return FLAC__lpc_compute_expected_bits_per_residual_sample_with_error_scale(lpc_error, error_scale); +} + +FLAC__real FLAC__lpc_compute_expected_bits_per_residual_sample_with_error_scale(FLAC__real lpc_error, double error_scale) +{ + if(lpc_error > 0.0) { + FLAC__real bps = (FLAC__real)((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 float resolution */ + return (FLAC__real)1e32; + } + else { + return 0.0; + } +} + +unsigned FLAC__lpc_compute_best_order(const FLAC__real lpc_error[], unsigned max_order, unsigned total_samples, unsigned bits_per_signal_sample) +{ + unsigned order, best_order; + FLAC__real best_bits, tmp_bits; + double error_scale; + + FLAC__ASSERT(max_order > 0); + FLAC__ASSERT(total_samples > 0); + + error_scale = 0.5 * M_LN2 * M_LN2 / (FLAC__real)total_samples; + + best_order = 0; + best_bits = FLAC__lpc_compute_expected_bits_per_residual_sample_with_error_scale(lpc_error[0], error_scale) * (FLAC__real)total_samples; + + for(order = 1; order < max_order; order++) { + tmp_bits = FLAC__lpc_compute_expected_bits_per_residual_sample_with_error_scale(lpc_error[order], error_scale) * (FLAC__real)(total_samples - order) + (FLAC__real)(order * bits_per_signal_sample); + if(tmp_bits < best_bits) { + best_order = order; + best_bits = tmp_bits; + } + } + + return best_order+1; /* +1 since index of lpc_error[] is order-1 */ +} diff --git a/FLAC/memory.c b/FLAC/memory.c new file mode 100644 index 00000000000..a332f7275e3 --- /dev/null +++ b/FLAC/memory.c @@ -0,0 +1,169 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2001,2002,2003,2004 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. + */ + +#include "private/memory.h" +#include "FLAC/assert.h" + +#ifdef HAVE_CONFIG_H +#include +#endif + +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 = malloc(bytes+31); + *aligned_address = (void*)(((unsigned)x + 31) & -32); +#else + x = 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) +{ + union { void *v; FLAC__int32 *i; } pa; + FLAC__int32 *pu; /* aligned pointer, unaligned pointer */ + + FLAC__ASSERT(elements > 0); + FLAC__ASSERT(0 != unaligned_pointer); + FLAC__ASSERT(0 != aligned_pointer); + FLAC__ASSERT(unaligned_pointer != aligned_pointer); + + pu = (FLAC__int32*)FLAC__memory_alloc_aligned(sizeof(FLAC__int32) * elements, &pa.v); + if(0 == pu) { + return false; + } + else { + if(*unaligned_pointer != 0) + free(*unaligned_pointer); + *unaligned_pointer = pu; + *aligned_pointer = pa.i; + return true; + } +} + +FLAC__bool FLAC__memory_alloc_aligned_uint32_array(unsigned elements, FLAC__uint32 **unaligned_pointer, FLAC__uint32 **aligned_pointer) +{ + union { void *v; FLAC__uint32 *i; } pa; + FLAC__uint32 *pu; /* aligned pointer, unaligned pointer */ + + FLAC__ASSERT(elements > 0); + FLAC__ASSERT(0 != unaligned_pointer); + FLAC__ASSERT(0 != aligned_pointer); + FLAC__ASSERT(unaligned_pointer != aligned_pointer); + + pu = (FLAC__uint32*)FLAC__memory_alloc_aligned(sizeof(FLAC__uint32) * elements, &pa.v); + if(0 == pu) { + return false; + } + else { + if(*unaligned_pointer != 0) + free(*unaligned_pointer); + *unaligned_pointer = pu; + *aligned_pointer = pa.i; + return true; + } +} + +FLAC__bool FLAC__memory_alloc_aligned_uint64_array(unsigned elements, FLAC__uint64 **unaligned_pointer, FLAC__uint64 **aligned_pointer) +{ + union { void *v; FLAC__uint64 *i; } pa; + FLAC__uint64 *pu; /* aligned pointer, unaligned pointer */ + + FLAC__ASSERT(elements > 0); + FLAC__ASSERT(0 != unaligned_pointer); + FLAC__ASSERT(0 != aligned_pointer); + FLAC__ASSERT(unaligned_pointer != aligned_pointer); + + pu = (FLAC__uint64*)FLAC__memory_alloc_aligned(sizeof(FLAC__uint64) * elements, &pa.v); + if(0 == pu) { + return false; + } + else { + if(*unaligned_pointer != 0) + free(*unaligned_pointer); + *unaligned_pointer = pu; + *aligned_pointer = pa.i; + return true; + } +} + +FLAC__bool FLAC__memory_alloc_aligned_unsigned_array(unsigned elements, unsigned **unaligned_pointer, unsigned **aligned_pointer) +{ + union { void *v; unsigned *i; } pa; + unsigned *pu; /* aligned pointer, unaligned pointer */ + + FLAC__ASSERT(elements > 0); + FLAC__ASSERT(0 != unaligned_pointer); + FLAC__ASSERT(0 != aligned_pointer); + FLAC__ASSERT(unaligned_pointer != aligned_pointer); + + pu = (unsigned*)FLAC__memory_alloc_aligned(sizeof(unsigned) * elements, &pa.v); + if(0 == pu) { + return false; + } + else { + if(*unaligned_pointer != 0) + free(*unaligned_pointer); + *unaligned_pointer = pu; + *aligned_pointer = pa.i; + return true; + } +} + +FLAC__bool FLAC__memory_alloc_aligned_real_array(unsigned elements, FLAC__real **unaligned_pointer, FLAC__real **aligned_pointer) +{ + union { void *v; FLAC__real *r; } pa; + FLAC__real *pu; /* aligned pointer, unaligned pointer */ + + FLAC__ASSERT(elements > 0); + FLAC__ASSERT(0 != unaligned_pointer); + FLAC__ASSERT(0 != aligned_pointer); + FLAC__ASSERT(unaligned_pointer != aligned_pointer); + + pu = (FLAC__real*)FLAC__memory_alloc_aligned(sizeof(FLAC__real) * elements, &pa.v); + if(0 == pu) { + return false; + } + else { + if(*unaligned_pointer != 0) + free(*unaligned_pointer); + *unaligned_pointer = pu; + *aligned_pointer = pa.r; + return true; + } +} diff --git a/FLAC/private/bitbuffer.h b/FLAC/private/bitbuffer.h new file mode 100644 index 00000000000..fc6928037f8 --- /dev/null +++ b/FLAC/private/bitbuffer.h @@ -0,0 +1,159 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2000,2001,2002,2003 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__BITBUFFER_H +#define FLAC__PRIVATE__BITBUFFER_H + +#include /* for FILE */ +#include "FLAC/ordinals.h" + +/* @@@ This should be configurable. Valid values are currently 8 and 32. */ +/* @@@ WATCHOUT! do not use 32 with a little endian system yet. */ +#define FLAC__BITS_PER_BLURB 8 + +#if FLAC__BITS_PER_BLURB == 8 +typedef FLAC__byte FLAC__blurb; +#elif FLAC__BITS_PER_BLURB == 32 +typedef FLAC__uint32 FLAC__blurb; +#else +/* ERROR, only sizes of 8 and 32 are supported */ +#endif + +/* + * opaque structure definition + */ +struct FLAC__BitBuffer; +typedef struct FLAC__BitBuffer FLAC__BitBuffer; + +/* + * construction, deletion, initialization, cloning functions + */ +FLAC__BitBuffer *FLAC__bitbuffer_new(); +void FLAC__bitbuffer_delete(FLAC__BitBuffer *bb); +FLAC__bool FLAC__bitbuffer_init(FLAC__BitBuffer *bb); +FLAC__bool FLAC__bitbuffer_init_from(FLAC__BitBuffer *bb, const FLAC__byte buffer[], unsigned bytes); +FLAC__bool FLAC__bitbuffer_concatenate_aligned(FLAC__BitBuffer *dest, const FLAC__BitBuffer *src); +void FLAC__bitbuffer_free(FLAC__BitBuffer *bb); /* does not 'free(buffer)' */ +FLAC__bool FLAC__bitbuffer_clear(FLAC__BitBuffer *bb); +FLAC__bool FLAC__bitbuffer_clone(FLAC__BitBuffer *dest, const FLAC__BitBuffer *src); + +/* + * CRC functions + */ +void FLAC__bitbuffer_reset_read_crc16(FLAC__BitBuffer *bb, FLAC__uint16 seed); +FLAC__uint16 FLAC__bitbuffer_get_read_crc16(FLAC__BitBuffer *bb); +FLAC__uint16 FLAC__bitbuffer_get_write_crc16(const FLAC__BitBuffer *bb); +FLAC__byte FLAC__bitbuffer_get_write_crc8(const FLAC__BitBuffer *bb); + +/* + * info functions + */ +FLAC__bool FLAC__bitbuffer_is_byte_aligned(const FLAC__BitBuffer *bb); +FLAC__bool FLAC__bitbuffer_is_consumed_byte_aligned(const FLAC__BitBuffer *bb); +unsigned FLAC__bitbuffer_bits_left_for_byte_alignment(const FLAC__BitBuffer *bb); +unsigned FLAC__bitbuffer_get_input_bytes_unconsumed(const FLAC__BitBuffer *bb); /* do not call unless byte-aligned */ + +/* + * direct buffer access + */ +void FLAC__bitbuffer_get_buffer(FLAC__BitBuffer *bb, const FLAC__byte **buffer, unsigned *bytes); +void FLAC__bitbuffer_release_buffer(FLAC__BitBuffer *bb); + +/* + * write functions + */ +FLAC__bool FLAC__bitbuffer_write_zeroes(FLAC__BitBuffer *bb, unsigned bits); +FLAC__bool FLAC__bitbuffer_write_raw_uint32(FLAC__BitBuffer *bb, FLAC__uint32 val, unsigned bits); +FLAC__bool FLAC__bitbuffer_write_raw_int32(FLAC__BitBuffer *bb, FLAC__int32 val, unsigned bits); +FLAC__bool FLAC__bitbuffer_write_raw_uint64(FLAC__BitBuffer *bb, FLAC__uint64 val, unsigned bits); +#if 0 /* UNUSED */ +FLAC__bool FLAC__bitbuffer_write_raw_int64(FLAC__BitBuffer *bb, FLAC__int64 val, unsigned bits); +#endif +FLAC__bool FLAC__bitbuffer_write_raw_uint32_little_endian(FLAC__BitBuffer *bb, FLAC__uint32 val); /*only for bits=32*/ +FLAC__bool FLAC__bitbuffer_write_byte_block(FLAC__BitBuffer *bb, const FLAC__byte vals[], unsigned nvals); +FLAC__bool FLAC__bitbuffer_write_unary_unsigned(FLAC__BitBuffer *bb, unsigned val); +unsigned FLAC__bitbuffer_rice_bits(int val, unsigned parameter); +#if 0 /* UNUSED */ +unsigned FLAC__bitbuffer_golomb_bits_signed(int val, unsigned parameter); +unsigned FLAC__bitbuffer_golomb_bits_unsigned(unsigned val, unsigned parameter); +#endif +#ifdef FLAC__SYMMETRIC_RICE +FLAC__bool FLAC__bitbuffer_write_symmetric_rice_signed(FLAC__BitBuffer *bb, int val, unsigned parameter); +#if 0 /* UNUSED */ +FLAC__bool FLAC__bitbuffer_write_symmetric_rice_signed_guarded(FLAC__BitBuffer *bb, int val, unsigned parameter, unsigned max_bits, FLAC__bool *overflow); +#endif +FLAC__bool FLAC__bitbuffer_write_symmetric_rice_signed_escape(FLAC__BitBuffer *bb, int val, unsigned parameter); +#endif +FLAC__bool FLAC__bitbuffer_write_rice_signed(FLAC__BitBuffer *bb, int val, unsigned parameter); +#if 0 /* UNUSED */ +FLAC__bool FLAC__bitbuffer_write_rice_signed_guarded(FLAC__BitBuffer *bb, int val, unsigned parameter, unsigned max_bits, FLAC__bool *overflow); +#endif +#if 0 /* UNUSED */ +FLAC__bool FLAC__bitbuffer_write_golomb_signed(FLAC__BitBuffer *bb, int val, unsigned parameter); +FLAC__bool FLAC__bitbuffer_write_golomb_signed_guarded(FLAC__BitBuffer *bb, int val, unsigned parameter, unsigned max_bits, FLAC__bool *overflow); +FLAC__bool FLAC__bitbuffer_write_golomb_unsigned(FLAC__BitBuffer *bb, unsigned val, unsigned parameter); +FLAC__bool FLAC__bitbuffer_write_golomb_unsigned_guarded(FLAC__BitBuffer *bb, unsigned val, unsigned parameter, unsigned max_bits, FLAC__bool *overflow); +#endif +FLAC__bool FLAC__bitbuffer_write_utf8_uint32(FLAC__BitBuffer *bb, FLAC__uint32 val); +FLAC__bool FLAC__bitbuffer_write_utf8_uint64(FLAC__BitBuffer *bb, FLAC__uint64 val); +FLAC__bool FLAC__bitbuffer_zero_pad_to_byte_boundary(FLAC__BitBuffer *bb); + +/* + * read functions + */ +FLAC__bool FLAC__bitbuffer_peek_bit(FLAC__BitBuffer *bb, unsigned *val, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data); +FLAC__bool FLAC__bitbuffer_read_bit(FLAC__BitBuffer *bb, unsigned *val, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data); +FLAC__bool FLAC__bitbuffer_read_bit_to_uint32(FLAC__BitBuffer *bb, FLAC__uint32 *val, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data); +FLAC__bool FLAC__bitbuffer_read_bit_to_uint64(FLAC__BitBuffer *bb, FLAC__uint64 *val, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data); +FLAC__bool FLAC__bitbuffer_read_raw_uint32(FLAC__BitBuffer *bb, FLAC__uint32 *val, const unsigned bits, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data); +FLAC__bool FLAC__bitbuffer_read_raw_int32(FLAC__BitBuffer *bb, FLAC__int32 *val, const unsigned bits, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data); +FLAC__bool FLAC__bitbuffer_read_raw_uint64(FLAC__BitBuffer *bb, FLAC__uint64 *val, const unsigned bits, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data); +#if 0 /* UNUSED */ +FLAC__bool FLAC__bitbuffer_read_raw_int64(FLAC__BitBuffer *bb, FLAC__int64 *val, const unsigned bits, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data); +#endif +FLAC__bool FLAC__bitbuffer_read_raw_uint32_little_endian(FLAC__BitBuffer *bb, FLAC__uint32 *val, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data); /*only for bits=32*/ +FLAC__bool FLAC__bitbuffer_skip_bits_no_crc(FLAC__BitBuffer *bb, unsigned bits, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data); /* WATCHOUT: does not CRC the skipped data! */ /*@@@@ add to unit tests */ +FLAC__bool FLAC__bitbuffer_read_byte_block_aligned_no_crc(FLAC__BitBuffer *bb, FLAC__byte *val, unsigned nvals, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data); /* val may be 0 to skip bytes instead of reading them */ /* WATCHOUT: does not CRC the read data! */ +FLAC__bool FLAC__bitbuffer_read_unary_unsigned(FLAC__BitBuffer *bb, unsigned *val, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data); +#ifdef FLAC__SYMMETRIC_RICE +FLAC__bool FLAC__bitbuffer_read_symmetric_rice_signed(FLAC__BitBuffer *bb, int *val, unsigned parameter, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data); +#endif +FLAC__bool FLAC__bitbuffer_read_rice_signed(FLAC__BitBuffer *bb, int *val, unsigned parameter, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data); +FLAC__bool FLAC__bitbuffer_read_rice_signed_block(FLAC__BitBuffer *bb, int vals[], unsigned nvals, unsigned parameter, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data); +#if 0 /* UNUSED */ +FLAC__bool FLAC__bitbuffer_read_golomb_signed(FLAC__BitBuffer *bb, int *val, unsigned parameter, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data); +FLAC__bool FLAC__bitbuffer_read_golomb_unsigned(FLAC__BitBuffer *bb, unsigned *val, unsigned parameter, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data); +#endif +FLAC__bool FLAC__bitbuffer_read_utf8_uint32(FLAC__BitBuffer *bb, FLAC__uint32 *val, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data, FLAC__byte *raw, unsigned *rawlen); +FLAC__bool FLAC__bitbuffer_read_utf8_uint64(FLAC__BitBuffer *bb, FLAC__uint64 *val, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data, FLAC__byte *raw, unsigned *rawlen); +void FLAC__bitbuffer_dump(const FLAC__BitBuffer *bb, FILE *out); + +#endif diff --git a/FLAC/private/bitmath.h b/FLAC/private/bitmath.h new file mode 100644 index 00000000000..74220ae59d1 --- /dev/null +++ b/FLAC/private/bitmath.h @@ -0,0 +1,41 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2001,2002,2003 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 "FLAC/ordinals.h" + +unsigned FLAC__bitmath_ilog2(unsigned v); +unsigned FLAC__bitmath_silog2(int v); +unsigned FLAC__bitmath_silog2_wide(FLAC__int64 v); + +#endif diff --git a/FLAC/private/cpu.h b/FLAC/private/cpu.h new file mode 100644 index 00000000000..c7f7bd205d1 --- /dev/null +++ b/FLAC/private/cpu.h @@ -0,0 +1,87 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2001,2002,2003 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 +#endif + +typedef enum { + FLAC__CPUINFO_TYPE_IA32, + FLAC__CPUINFO_TYPE_UNKNOWN +} FLAC__CPUInfo_Type; + +typedef struct { + FLAC__bool cmov; + FLAC__bool mmx; + FLAC__bool fxsr; + FLAC__bool sse; + FLAC__bool sse2; + FLAC__bool _3dnow; + FLAC__bool ext3dnow; + FLAC__bool extmmx; +} FLAC__CPUInfo_IA32; + +extern const unsigned FLAC__CPUINFO_IA32_CPUID_CMOV; +extern const unsigned FLAC__CPUINFO_IA32_CPUID_MMX; +extern const unsigned FLAC__CPUINFO_IA32_CPUID_FXSR; +extern const unsigned FLAC__CPUINFO_IA32_CPUID_SSE; +extern const unsigned FLAC__CPUINFO_IA32_CPUID_SSE2; + +extern const unsigned FLAC__CPUINFO_IA32_CPUID_EXTENDED_AMD_3DNOW; +extern const unsigned FLAC__CPUINFO_IA32_CPUID_EXTENDED_AMD_EXT3DNOW; +extern const unsigned FLAC__CPUINFO_IA32_CPUID_EXTENDED_AMD_EXTMMX; + +typedef struct { + FLAC__bool use_asm; + FLAC__CPUInfo_Type type; + union { + FLAC__CPUInfo_IA32 ia32; + } data; +} FLAC__CPUInfo; + +void FLAC__cpu_info(FLAC__CPUInfo *info); + +#ifndef FLAC__NO_ASM +#ifdef FLAC__CPU_IA32 +#ifdef FLAC__HAS_NASM +unsigned FLAC__cpu_info_asm_ia32(); +unsigned FLAC__cpu_info_extended_amd_asm_ia32(); +unsigned FLAC__cpu_info_sse_test_asm_ia32(); +#endif +#endif +#endif + +#endif diff --git a/FLAC/private/crc.h b/FLAC/private/crc.h new file mode 100644 index 00000000000..2656c7b0397 --- /dev/null +++ b/FLAC/private/crc.h @@ -0,0 +1,57 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2000,2001,2002,2003 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 FLAC__uint16 FLAC__crc16_table[256]; +#define FLAC__CRC16_UPDATE(data, crc) (crc) = ((crc)<<8) ^ FLAC__crc16_table[((crc)>>8) ^ (data)]; +void FLAC__crc16_update(const FLAC__byte data, FLAC__uint16 *crc); +void FLAC__crc16_update_block(const FLAC__byte *data, unsigned len, FLAC__uint16 *crc); +FLAC__uint16 FLAC__crc16(const FLAC__byte *data, unsigned len); + +#endif diff --git a/FLAC/private/fixed.h b/FLAC/private/fixed.h new file mode 100644 index 00000000000..e2728e00a99 --- /dev/null +++ b/FLAC/private/fixed.h @@ -0,0 +1,91 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2000,2001,2002,2003 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 + +#include "FLAC/format.h" + +#ifdef HAVE_CONFIG_H +#include +#endif + +/* + * 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] + */ +unsigned FLAC__fixed_compute_best_predictor(const FLAC__int32 data[], unsigned data_len, FLAC__real 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__real 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__real residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]); + +/* + * 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/FLAC/private/format.h b/FLAC/private/format.h new file mode 100644 index 00000000000..691cfc2f557 --- /dev/null +++ b/FLAC/private/format.h @@ -0,0 +1,44 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2000,2001,2002,2003 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__FORMAT_H +#define FLAC__PRIVATE__FORMAT_H + +#include "FLAC/format.h" + +unsigned FLAC__format_get_max_rice_partition_order(unsigned blocksize, unsigned predictor_order); +unsigned FLAC__format_get_max_rice_partition_order_from_blocksize(unsigned blocksize); +unsigned FLAC__format_get_max_rice_partition_order_from_blocksize_limited_max_and_predictor_order(unsigned limit, unsigned blocksize, unsigned predictor_order); +void FLAC__format_entropy_coding_method_partitioned_rice_contents_init(FLAC__EntropyCodingMethod_PartitionedRiceContents *object); +void FLAC__format_entropy_coding_method_partitioned_rice_contents_clear(FLAC__EntropyCodingMethod_PartitionedRiceContents *object); +FLAC__bool FLAC__format_entropy_coding_method_partitioned_rice_contents_ensure_size(FLAC__EntropyCodingMethod_PartitionedRiceContents *object, unsigned max_partition_order); + +#endif diff --git a/FLAC/private/lpc.h b/FLAC/private/lpc.h new file mode 100644 index 00000000000..801f7c5f902 --- /dev/null +++ b/FLAC/private/lpc.h @@ -0,0 +1,185 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2000,2001,2002,2003 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__LPC_H +#define FLAC__PRIVATE__LPC_H + +#include "FLAC/format.h" + +#ifdef HAVE_CONFIG_H +#include +#endif + +/* + * FLAC__lpc_compute_autocorrelation() + * -------------------------------------------------------------------- + * Compute the autocorrelation for lags between 0 and lag-1. + * Assumes data[] outside of [0,data_len-1] == 0. + * Asserts that lag > 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 + * + * 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__real 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 + +/* + * 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 +#endif +#endif + +/* + * 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__real FLAC__lpc_compute_expected_bits_per_residual_sample(FLAC__real lpc_error, unsigned total_samples); +FLAC__real FLAC__lpc_compute_expected_bits_per_residual_sample_with_error_scale(FLAC__real lpc_error, 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 bits_per_signal_sample # of bits per sample in the original signal + * RETURN [1,max_order] best order + */ +unsigned FLAC__lpc_compute_best_order(const FLAC__real lpc_error[], unsigned max_order, unsigned total_samples, unsigned bits_per_signal_sample); + +#endif diff --git a/FLAC/private/memory.h b/FLAC/private/memory.h new file mode 100644 index 00000000000..0445ba0180c --- /dev/null +++ b/FLAC/private/memory.h @@ -0,0 +1,49 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2001,2002,2003,2004 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 + +#include /* for size_t */ + +#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); +FLAC__bool FLAC__memory_alloc_aligned_real_array(unsigned elements, FLAC__real **unaligned_pointer, FLAC__real **aligned_pointer); + +#endif diff --git a/FLAC/protected/stream_decoder.h b/FLAC/protected/stream_decoder.h new file mode 100644 index 00000000000..bc274677b80 --- /dev/null +++ b/FLAC/protected/stream_decoder.h @@ -0,0 +1,51 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2000,2001,2002,2003 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" + +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__StreamDecoderProtected; + +/* + * return the number of input bytes consumed + */ +unsigned FLAC__stream_decoder_get_input_bytes_unconsumed(const FLAC__StreamDecoder *decoder); + +#endif diff --git a/FLAC/stream_decoder.c b/FLAC/stream_decoder.c new file mode 100644 index 00000000000..4b1c5776f23 --- /dev/null +++ b/FLAC/stream_decoder.c @@ -0,0 +1,2112 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2000,2001,2002,2003,2004 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. + */ + +#include +#include /* for malloc() */ +#include /* for memset/memcpy() */ +#include "FLAC/assert.h" +#include "protected/stream_decoder.h" +#include "private/bitbuffer.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/memory.h" + +#ifdef HAVE_CONFIG_H +#include +#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 + +/*********************************************************************** + * + * Private static data + * + ***********************************************************************/ + +static FLAC__byte ID3V2_TAG_[3] = { 'I', 'D', '3' }; + +/*********************************************************************** + * + * Private class method prototypes + * + ***********************************************************************/ + +static void set_defaults_(FLAC__StreamDecoder *decoder); +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 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); +static FLAC__bool read_zero_padding_(FLAC__StreamDecoder *decoder); +static FLAC__bool read_callback_(FLAC__byte buffer[], unsigned *bytes, void *client_data); + +/*********************************************************************** + * + * Private class data + * + ***********************************************************************/ + +typedef struct FLAC__StreamDecoderPrivate { + FLAC__StreamDecoderReadCallback read_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[]); + void *client_data; + FLAC__BitBuffer *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 last_frame_number; + 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; + unsigned 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__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_ABORTED", + "FLAC__STREAM_DECODER_UNPARSEABLE_STREAM", + "FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR", + "FLAC__STREAM_DECODER_ALREADY_INITIALIZED", + "FLAC__STREAM_DECODER_INVALID_CALLBACK", + "FLAC__STREAM_DECODER_UNINITIALIZED" +}; + +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__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" +}; + +/*********************************************************************** + * + * Class constructor/destructor + * + ***********************************************************************/ +FLAC_API FLAC__StreamDecoder *FLAC__stream_decoder_new() +{ + 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__bitbuffer_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__bitbuffer_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]); + + 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); + + FLAC__stream_decoder_finish(decoder); + + if(0 != decoder->private_->metadata_filter_ids) + free(decoder->private_->metadata_filter_ids); + + FLAC__bitbuffer_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 + * + ***********************************************************************/ + +FLAC_API FLAC__StreamDecoderState FLAC__stream_decoder_init(FLAC__StreamDecoder *decoder) +{ + FLAC__ASSERT(0 != decoder); + + if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED) + return decoder->protected_->state = FLAC__STREAM_DECODER_ALREADY_INITIALIZED; + + if(0 == decoder->private_->read_callback || 0 == decoder->private_->write_callback || 0 == decoder->private_->metadata_callback || 0 == decoder->private_->error_callback) + return decoder->protected_->state = FLAC__STREAM_DECODER_INVALID_CALLBACK; + + if(!FLAC__bitbuffer_init(decoder->private_->input)) + return decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; + + decoder->private_->last_frame_number = 0; + decoder->private_->samples_decoded = 0; + decoder->private_->has_stream_info = false; + decoder->private_->cached = false; + + /* + * 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; + /* 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(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 + + if(!FLAC__stream_decoder_reset(decoder)) + return decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; + + return decoder->protected_->state; +} + +FLAC_API void FLAC__stream_decoder_finish(FLAC__StreamDecoder *decoder) +{ + unsigned i; + FLAC__ASSERT(0 != decoder); + if(decoder->protected_->state == FLAC__STREAM_DECODER_UNINITIALIZED) + return; + if(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__bitbuffer_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; + + set_defaults_(decoder); + + decoder->protected_->state = FLAC__STREAM_DECODER_UNINITIALIZED; +} + +FLAC_API FLAC__bool FLAC__stream_decoder_set_read_callback(FLAC__StreamDecoder *decoder, FLAC__StreamDecoderReadCallback 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; + decoder->private_->read_callback = value; + return true; +} + +FLAC_API FLAC__bool FLAC__stream_decoder_set_write_callback(FLAC__StreamDecoder *decoder, FLAC__StreamDecoderWriteCallback 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; + decoder->private_->write_callback = value; + return true; +} + +FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_callback(FLAC__StreamDecoder *decoder, FLAC__StreamDecoderMetadataCallback 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; + decoder->private_->metadata_callback = value; + return true; +} + +FLAC_API FLAC__bool FLAC__stream_decoder_set_error_callback(FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorCallback 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; + decoder->private_->error_callback = value; + return true; +} + +FLAC_API FLAC__bool FLAC__stream_decoder_set_client_data(FLAC__StreamDecoder *decoder, void *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; + decoder->private_->client_data = 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*)realloc(decoder->private_->metadata_filter_ids, decoder->private_->metadata_filter_ids_capacity * 2))) + return decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; + 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*)realloc(decoder->private_->metadata_filter_ids, decoder->private_->metadata_filter_ids_capacity * 2))) + return decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; + 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 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_flush(FLAC__StreamDecoder *decoder) +{ + FLAC__ASSERT(0 != decoder); + FLAC__ASSERT(0 != decoder->private_); + FLAC__ASSERT(0 != decoder->protected_); + + if(!FLAC__bitbuffer_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)) { + decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; + return false; + } + decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_METADATA; + + decoder->private_->samples_decoded = 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; + } + } +} + +/*********************************************************************** + * + * Protected class methods + * + ***********************************************************************/ + +unsigned FLAC__stream_decoder_get_input_bytes_unconsumed(const FLAC__StreamDecoder *decoder) +{ + FLAC__ASSERT(0 != decoder); + return FLAC__bitbuffer_get_input_bytes_unconsumed(decoder->private_->input); +} + +/*********************************************************************** + * + * Private class methods + * + ***********************************************************************/ + +void set_defaults_(FLAC__StreamDecoder *decoder) +{ + decoder->private_->read_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; +} + +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*)malloc(sizeof(FLAC__int32)*(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) +{ + unsigned 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__bitbuffer_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__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder)) + return false; /* the 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; /* the read_callback_ sets the state for us */ + } + continue; + } + if(x == 0xff) { /* MAGIC NUMBER for the first 8 frame sync bits */ + decoder->private_->header_warmup[0] = (FLAC__byte)x; + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder)) + return false; /* the 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) { + decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC, decoder->private_->client_data); + 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__bitbuffer_is_consumed_byte_aligned(decoder->private_->input)); + + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_IS_LAST_LEN, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + is_last = x? true : false; + + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &type, FLAC__STREAM_METADATA_TYPE_LEN, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &length, FLAC__STREAM_METADATA_LENGTH_LEN, read_callback_, decoder)) + return false; /* the 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(decoder->private_->metadata_filter[FLAC__METADATA_TYPE_STREAMINFO]) + 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_->metadata_filter[FLAC__METADATA_TYPE_SEEKTABLE]) + 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__bitbuffer_read_byte_block_aligned_no_crc(decoder->private_->input, block.data.application.id, FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + + 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__bitbuffer_read_byte_block_aligned_no_crc(decoder->private_->input, 0, real_length, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + } + else { + switch(type) { + case FLAC__METADATA_TYPE_PADDING: + /* skip the padding bytes */ + if(!FLAC__bitbuffer_read_byte_block_aligned_no_crc(decoder->private_->input, 0, real_length, read_callback_, decoder)) + return false; /* the 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__bitbuffer_read_byte_block_aligned_no_crc(decoder->private_->input, block.data.application.data, real_length, read_callback_, decoder)) + return false; /* the 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_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__bitbuffer_read_byte_block_aligned_no_crc(decoder->private_->input, block.data.unknown.data, real_length, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + } + else + block.data.unknown.data = 0; + break; + } + 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_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) + 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__bitbuffer_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__bitbuffer_read_raw_uint32(decoder->private_->input, &x, bits, read_callback_, decoder)) + return false; /* the 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__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN, read_callback_, decoder)) + return false; /* the 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__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN, read_callback_, decoder)) + return false; /* the 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__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN, read_callback_, decoder)) + return false; /* the 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__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN, read_callback_, decoder)) + return false; /* the 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__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN, read_callback_, decoder)) + return false; /* the 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__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN, read_callback_, decoder)) + return false; /* the 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__bitbuffer_read_raw_uint64(decoder->private_->input, &decoder->private_->stream_info.data.stream_info.total_samples, FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + used_bits += bits; + + if(!FLAC__bitbuffer_read_byte_block_aligned_no_crc(decoder->private_->input, decoder->private_->stream_info.data.stream_info.md5sum, 16, read_callback_, decoder)) + return false; /* the 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__bitbuffer_read_byte_block_aligned_no_crc(decoder->private_->input, 0, length, read_callback_, decoder)) + return false; /* the 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__bitbuffer_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*)realloc(decoder->private_->seek_table.data.seek_table.points, decoder->private_->seek_table.data.seek_table.num_points * 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__bitbuffer_read_raw_uint64(decoder->private_->input, &xx, FLAC__STREAM_METADATA_SEEKPOINT_SAMPLE_NUMBER_LEN, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + decoder->private_->seek_table.data.seek_table.points[i].sample_number = xx; + + if(!FLAC__bitbuffer_read_raw_uint64(decoder->private_->input, &xx, FLAC__STREAM_METADATA_SEEKPOINT_STREAM_OFFSET_LEN, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + decoder->private_->seek_table.data.seek_table.points[i].stream_offset = xx; + + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_SEEKPOINT_FRAME_SAMPLES_LEN, read_callback_, decoder)) + return false; /* the 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 an error_callback() here? there's an argument for either way */ + if(!FLAC__bitbuffer_read_byte_block_aligned_no_crc(decoder->private_->input, 0, length, read_callback_, decoder)) + return false; /* the 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__bitbuffer_is_consumed_byte_aligned(decoder->private_->input)); + + /* read vendor string */ + FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN == 32); + if(!FLAC__bitbuffer_read_raw_uint32_little_endian(decoder->private_->input, &obj->vendor_string.length, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + if(obj->vendor_string.length > 0) { + if(0 == (obj->vendor_string.entry = (FLAC__byte*)malloc(obj->vendor_string.length))) { + decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; + return false; + } + if(!FLAC__bitbuffer_read_byte_block_aligned_no_crc(decoder->private_->input, obj->vendor_string.entry, obj->vendor_string.length, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + } + else + obj->vendor_string.entry = 0; + + /* read num comments */ + FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN == 32); + if(!FLAC__bitbuffer_read_raw_uint32_little_endian(decoder->private_->input, &obj->num_comments, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + + /* read comments */ + if(obj->num_comments > 0) { + if(0 == (obj->comments = (FLAC__StreamMetadata_VorbisComment_Entry*)malloc(obj->num_comments * 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__bitbuffer_read_raw_uint32_little_endian(decoder->private_->input, &obj->comments[i].length, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + if(obj->comments[i].length > 0) { + if(0 == (obj->comments[i].entry = (FLAC__byte*)malloc(obj->comments[i].length))) { + decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; + return false; + } + if(!FLAC__bitbuffer_read_byte_block_aligned_no_crc(decoder->private_->input, obj->comments[i].entry, obj->comments[i].length, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + } + 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__bitbuffer_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__bitbuffer_read_byte_block_aligned_no_crc(decoder->private_->input, (FLAC__byte*)obj->media_catalog_number, FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN/8, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + + if(!FLAC__bitbuffer_read_raw_uint64(decoder->private_->input, &obj->lead_in, FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + obj->is_cd = x? true : false; + + if(!FLAC__bitbuffer_skip_bits_no_crc(decoder->private_->input, FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + obj->num_tracks = x; + + if(obj->num_tracks > 0) { + if(0 == (obj->tracks = (FLAC__StreamMetadata_CueSheet_Track*)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__bitbuffer_read_raw_uint64(decoder->private_->input, &track->offset, FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN, read_callback_, decoder)) + return false; /* the 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__bitbuffer_read_byte_block_aligned_no_crc(decoder->private_->input, (FLAC__byte*)track->isrc, FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN/8, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + track->type = x; + + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + track->pre_emphasis = x; + + if(!FLAC__bitbuffer_skip_bits_no_crc(decoder->private_->input, FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN, read_callback_, decoder)) + return false; /* the 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*)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__bitbuffer_read_raw_uint64(decoder->private_->input, &index->offset, FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + index->number = (FLAC__byte)x; + + if(!FLAC__bitbuffer_skip_bits_no_crc(decoder->private_->input, FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN, read_callback_, decoder)) + return false; /* the 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__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 24, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + /* get the size (in bytes) to skip */ + skip = 0; + for(i = 0; i < 4; i++) { + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + skip <<= 7; + skip |= (x & 0x7f); + } + /* skip the rest of the tag */ + if(!FLAC__bitbuffer_read_byte_block_aligned_no_crc(decoder->private_->input, 0, skip, read_callback_, decoder)) + return false; /* the 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(decoder->private_->has_stream_info && decoder->private_->stream_info.data.stream_info.total_samples) { + if(decoder->private_->samples_decoded >= decoder->private_->stream_info.data.stream_info.total_samples) { + decoder->protected_->state = FLAC__STREAM_DECODER_END_OF_STREAM; + return true; + } + } + + /* make sure we're byte aligned */ + if(!FLAC__bitbuffer_is_consumed_byte_aligned(decoder->private_->input)) { + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__bitbuffer_bits_left_for_byte_alignment(decoder->private_->input), read_callback_, decoder)) + return false; /* the 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__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder)) + return false; /* the 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__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder)) + return false; /* the 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) { + decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC, decoder->private_->client_data); + 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, left, right; + FLAC__uint16 frame_crc; /* the one we calculate from the input stream */ + FLAC__uint32 x; + + *got_a_frame = false; + + /* init the CRC */ + frame_crc = 0; + FLAC__CRC16_UPDATE(decoder->private_->header_warmup[0], frame_crc); + FLAC__CRC16_UPDATE(decoder->private_->header_warmup[1], frame_crc); + FLAC__bitbuffer_reset_read_crc16(decoder->private_->input, frame_crc); + + if(!read_frame_header_(decoder)) + return false; + if(decoder->protected_->state == FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC) + 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_READ_FRAME) { + decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; + return true; + } + } + if(!read_zero_padding_(decoder)) + return false; + + /* + * Read the frame CRC-16 from the footer and check + */ + frame_crc = FLAC__bitbuffer_get_read_crc16(decoder->private_->input); + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__FRAME_FOOTER_CRC_LEN, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + if(frame_crc == (FLAC__uint16)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++) { + mid = decoder->private_->output[0][i]; + side = decoder->private_->output[1][i]; + mid <<= 1; + if(side & 1) /* i.e. if 'side' is odd... */ + mid++; + left = mid + side; + right = mid - side; + decoder->private_->output[0][i] = left >> 1; + decoder->private_->output[1][i] = right >> 1; + } + break; + default: + FLAC__ASSERT(0); + break; + } + } + } + else { + /* Bad frame, emit error and zero the output signal */ + decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH, decoder->private_->client_data); + 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; + + /* 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(decoder->private_->write_callback(decoder, &decoder->private_->frame, (const FLAC__int32 * const *)decoder->private_->output, decoder->private_->client_data) != 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; + const FLAC__bool is_known_variable_blocksize_stream = (decoder->private_->has_stream_info && decoder->private_->stream_info.data.stream_info.min_blocksize != decoder->private_->stream_info.data.stream_info.max_blocksize); + const FLAC__bool is_known_fixed_blocksize_stream = (decoder->private_->has_stream_info && decoder->private_->stream_info.data.stream_info.min_blocksize == decoder->private_->stream_info.data.stream_info.max_blocksize); + + FLAC__ASSERT(FLAC__bitbuffer_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 the reserved bits are 0 + */ + if(raw_header[1] & 0x03) { /* 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. + */ + + /* + * 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__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder)) + return false; /* the 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; + decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER, decoder->private_->client_data); + 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: + if(is_known_fixed_blocksize_stream) + decoder->private_->frame.header.blocksize = decoder->private_->stream_info.data.stream_info.min_blocksize; + else + 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: + case 2: + case 3: + is_unparseable = true; + 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: + decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER, decoder->private_->client_data); + 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; + } + + if(raw_header[3] & 0x01) { /* this should be a zero padding bit */ + decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER, decoder->private_->client_data); + decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; + return true; + } + + if(blocksize_hint && is_known_variable_blocksize_stream) { + if(!FLAC__bitbuffer_read_utf8_uint64(decoder->private_->input, &xx, read_callback_, decoder, raw_header, &raw_header_len)) + return false; /* the 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; + decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER, decoder->private_->client_data); + 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 { + if(!FLAC__bitbuffer_read_utf8_uint32(decoder->private_->input, &x, read_callback_, decoder, raw_header, &raw_header_len)) + return false; /* the 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; + decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER, decoder->private_->client_data); + decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; + return true; + } + decoder->private_->last_frame_number = x; + decoder->private_->frame.header.number_type = FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER; + if(blocksize_hint) { + if(decoder->private_->has_stream_info) + decoder->private_->frame.header.number.sample_number = (FLAC__int64)decoder->private_->stream_info.data.stream_info.min_blocksize * (FLAC__int64)x; + else + is_unparseable = true; + } + else + decoder->private_->frame.header.number.sample_number = (FLAC__int64)decoder->private_->frame.header.blocksize * (FLAC__int64)x; + } + + if(blocksize_hint) { + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + raw_header[raw_header_len++] = (FLAC__byte)x; + if(blocksize_hint == 7) { + FLAC__uint32 _x; + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &_x, 8, read_callback_, decoder)) + return false; /* the 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__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder)) + return false; /* the 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__bitbuffer_read_raw_uint32(decoder->private_->input, &_x, 8, read_callback_, decoder)) + return false; /* the 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__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + crc8 = (FLAC__byte)x; + + if(FLAC__crc8(raw_header, raw_header_len) != crc8) { + decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER, decoder->private_->client_data); + decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; + return true; + } + + if(is_unparseable) { + decoder->protected_->state = FLAC__STREAM_DECODER_UNPARSEABLE_STREAM; + return false; + } + + 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; + + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder)) /* MAGIC NUMBER */ + return false; /* the read_callback_ sets the state for us */ + + wasted_bits = (x & 1); + x &= 0xfe; + + if(wasted_bits) { + unsigned u; + if(!FLAC__bitbuffer_read_unary_unsigned(decoder->private_->input, &u, read_callback_, decoder)) + return false; /* the 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) { + decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC, decoder->private_->client_data); + 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) { + decoder->protected_->state = FLAC__STREAM_DECODER_UNPARSEABLE_STREAM; + return false; + } + else if(x <= 24) { + if(!read_subframe_fixed_(decoder, channel, bps, (x>>1)&7, do_full_decode)) + return false; + } + else if(x < 64) { + decoder->protected_->state = FLAC__STREAM_DECODER_UNPARSEABLE_STREAM; + return false; + } + else { + if(!read_subframe_lpc_(decoder, channel, bps, ((x>>1)&31)+1, do_full_decode)) + return false; + } + + if(wasted_bits && do_full_decode) { + unsigned i; + 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__bitbuffer_read_raw_int32(decoder->private_->input, &x, bps, read_callback_, decoder)) + return false; /* the 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__bitbuffer_read_raw_int32(decoder->private_->input, &i32, bps, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + subframe->warmup[u] = i32; + } + + /* read entropy coding method info */ + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &u32, FLAC__ENTROPY_CODING_METHOD_TYPE_LEN, read_callback_, decoder)) + return false; /* the 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: + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &u32, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN, read_callback_, decoder)) + return false; /* the 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: + decoder->protected_->state = FLAC__STREAM_DECODER_UNPARSEABLE_STREAM; + return false; + } + + /* read residual */ + switch(subframe->entropy_coding_method.type) { + case FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE: + 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])) + 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__bitbuffer_read_raw_int32(decoder->private_->input, &i32, bps, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + subframe->warmup[u] = i32; + } + + /* read qlp coeff precision */ + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &u32, FLAC__SUBFRAME_LPC_QLP_COEFF_PRECISION_LEN, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + if(u32 == (1u << FLAC__SUBFRAME_LPC_QLP_COEFF_PRECISION_LEN) - 1) { + decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC, decoder->private_->client_data); + decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; + return true; + } + subframe->qlp_coeff_precision = u32+1; + + /* read qlp shift */ + if(!FLAC__bitbuffer_read_raw_int32(decoder->private_->input, &i32, FLAC__SUBFRAME_LPC_QLP_SHIFT_LEN, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + subframe->quantization_level = i32; + + /* read quantized lp coefficiencts */ + for(u = 0; u < order; u++) { + if(!FLAC__bitbuffer_read_raw_int32(decoder->private_->input, &i32, subframe->qlp_coeff_precision, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + subframe->qlp_coeff[u] = i32; + } + + /* read entropy coding method info */ + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &u32, FLAC__ENTROPY_CODING_METHOD_TYPE_LEN, read_callback_, decoder)) + return false; /* the 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: + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &u32, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN, read_callback_, decoder)) + return false; /* the 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: + decoder->protected_->state = FLAC__STREAM_DECODER_UNPARSEABLE_STREAM; + return false; + } + + /* read residual */ + switch(subframe->entropy_coding_method.type) { + case FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE: + 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])) + 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); + 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__bitbuffer_read_raw_int32(decoder->private_->input, &x, bps, read_callback_, decoder)) + return false; /* the 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__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; + + 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__bitbuffer_read_raw_uint32(decoder->private_->input, &rice_parameter, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + partitioned_rice_contents->parameters[partition] = rice_parameter; + if(rice_parameter < FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER) { +#ifdef FLAC__SYMMETRIC_RICE + for(u = (partition_order == 0 || partition > 0)? 0 : predictor_order; u < partition_samples; u++, sample++) { + if(!FLAC__bitbuffer_read_symmetric_rice_signed(decoder->private_->input, &i, rice_parameter, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + residual[sample] = i; + } +#else + u = (partition_order == 0 || partition > 0)? partition_samples : partition_samples - predictor_order; + if(!FLAC__bitbuffer_read_rice_signed_block(decoder->private_->input, residual + sample, u, rice_parameter, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + sample += u; +#endif + } + else { + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &rice_parameter, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_RAW_LEN, read_callback_, decoder)) + return false; /* the 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__bitbuffer_read_raw_int32(decoder->private_->input, &i, rice_parameter, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + residual[sample] = i; + } + } + } + + return true; +} + +FLAC__bool read_zero_padding_(FLAC__StreamDecoder *decoder) +{ + if(!FLAC__bitbuffer_is_consumed_byte_aligned(decoder->private_->input)) { + FLAC__uint32 zero = 0; + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &zero, FLAC__bitbuffer_bits_left_for_byte_alignment(decoder->private_->input), read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + if(zero != 0) { + decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC, decoder->private_->client_data); + decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; + } + } + return true; +} + +FLAC__bool read_callback_(FLAC__byte buffer[], unsigned *bytes, void *client_data) +{ + FLAC__StreamDecoder *decoder = (FLAC__StreamDecoder *)client_data; + FLAC__StreamDecoderReadStatus status; + + status = decoder->private_->read_callback(decoder, buffer, bytes, decoder->private_->client_data); + if(status == FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM) + decoder->protected_->state = FLAC__STREAM_DECODER_END_OF_STREAM; + else if(status == FLAC__STREAM_DECODER_READ_STATUS_ABORT) + decoder->protected_->state = FLAC__STREAM_DECODER_ABORTED; + return status == FLAC__STREAM_DECODER_READ_STATUS_CONTINUE; +} diff --git a/FLAC/stream_decoder_pp.cpp b/FLAC/stream_decoder_pp.cpp new file mode 100644 index 00000000000..af17688871b --- /dev/null +++ b/FLAC/stream_decoder_pp.cpp @@ -0,0 +1,222 @@ +/* libFLAC++ - Free Lossless Audio Codec library + * Copyright (C) 2002,2003,2004 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. + */ + +#include "FLAC++/decoder.h" +#include "FLAC/assert.h" + +#ifdef _MSC_VER +// warning C4800: 'int' : forcing to bool 'true' or 'false' (performance warning) +#pragma warning ( disable : 4800 ) +#endif + +namespace FLAC { + namespace Decoder { + + Stream::Stream(): + decoder_(::FLAC__stream_decoder_new()) + { } + + Stream::~Stream() + { + if(0 != decoder_) { + ::FLAC__stream_decoder_finish(decoder_); + ::FLAC__stream_decoder_delete(decoder_); + } + } + + bool Stream::is_valid() const + { + return 0 != decoder_; + } + + bool Stream::set_metadata_respond(::FLAC__MetadataType type) + { + FLAC__ASSERT(is_valid()); + return (bool)::FLAC__stream_decoder_set_metadata_respond(decoder_, type); + } + + bool Stream::set_metadata_respond_application(const FLAC__byte id[4]) + { + FLAC__ASSERT(is_valid()); + return (bool)::FLAC__stream_decoder_set_metadata_respond_application(decoder_, id); + } + + bool Stream::set_metadata_respond_all() + { + FLAC__ASSERT(is_valid()); + return (bool)::FLAC__stream_decoder_set_metadata_respond_all(decoder_); + } + + bool Stream::set_metadata_ignore(::FLAC__MetadataType type) + { + FLAC__ASSERT(is_valid()); + return (bool)::FLAC__stream_decoder_set_metadata_ignore(decoder_, type); + } + + bool Stream::set_metadata_ignore_application(const FLAC__byte id[4]) + { + FLAC__ASSERT(is_valid()); + return (bool)::FLAC__stream_decoder_set_metadata_ignore_application(decoder_, id); + } + + bool Stream::set_metadata_ignore_all() + { + FLAC__ASSERT(is_valid()); + return (bool)::FLAC__stream_decoder_set_metadata_ignore_all(decoder_); + } + + Stream::State Stream::get_state() const + { + FLAC__ASSERT(is_valid()); + return State(::FLAC__stream_decoder_get_state(decoder_)); + } + + unsigned Stream::get_channels() const + { + FLAC__ASSERT(is_valid()); + return ::FLAC__stream_decoder_get_channels(decoder_); + } + + ::FLAC__ChannelAssignment Stream::get_channel_assignment() const + { + FLAC__ASSERT(is_valid()); + return ::FLAC__stream_decoder_get_channel_assignment(decoder_); + } + + unsigned Stream::get_bits_per_sample() const + { + FLAC__ASSERT(is_valid()); + return ::FLAC__stream_decoder_get_bits_per_sample(decoder_); + } + + unsigned Stream::get_sample_rate() const + { + FLAC__ASSERT(is_valid()); + return ::FLAC__stream_decoder_get_sample_rate(decoder_); + } + + unsigned Stream::get_blocksize() const + { + FLAC__ASSERT(is_valid()); + return ::FLAC__stream_decoder_get_blocksize(decoder_); + } + + Stream::State Stream::init() + { + FLAC__ASSERT(is_valid()); + ::FLAC__stream_decoder_set_read_callback(decoder_, read_callback_); + ::FLAC__stream_decoder_set_write_callback(decoder_, write_callback_); + ::FLAC__stream_decoder_set_metadata_callback(decoder_, metadata_callback_); + ::FLAC__stream_decoder_set_error_callback(decoder_, error_callback_); + ::FLAC__stream_decoder_set_client_data(decoder_, (void*)this); + return State(::FLAC__stream_decoder_init(decoder_)); + } + + void Stream::finish() + { + FLAC__ASSERT(is_valid()); + ::FLAC__stream_decoder_finish(decoder_); + } + + bool Stream::flush() + { + FLAC__ASSERT(is_valid()); + return (bool)::FLAC__stream_decoder_flush(decoder_); + } + + bool Stream::reset() + { + FLAC__ASSERT(is_valid()); + return (bool)::FLAC__stream_decoder_reset(decoder_); + } + + bool Stream::process_single() + { + FLAC__ASSERT(is_valid()); + return (bool)::FLAC__stream_decoder_process_single(decoder_); + } + + bool Stream::process_until_end_of_metadata() + { + FLAC__ASSERT(is_valid()); + return (bool)::FLAC__stream_decoder_process_until_end_of_metadata(decoder_); + } + + bool Stream::process_until_end_of_stream() + { + FLAC__ASSERT(is_valid()); + return (bool)::FLAC__stream_decoder_process_until_end_of_stream(decoder_); + } + + bool Stream::skip_single_frame() + { + FLAC__ASSERT(is_valid()); + return (bool)::FLAC__stream_decoder_skip_single_frame(decoder_); + } + + ::FLAC__StreamDecoderReadStatus Stream::read_callback_(const ::FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data) + { + (void)decoder; + FLAC__ASSERT(0 != client_data); + Stream *instance = reinterpret_cast(client_data); + FLAC__ASSERT(0 != instance); + return instance->read_callback(buffer, bytes); + } + + ::FLAC__StreamDecoderWriteStatus Stream::write_callback_(const ::FLAC__StreamDecoder *decoder, const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data) + { + (void)decoder; + FLAC__ASSERT(0 != client_data); + Stream *instance = reinterpret_cast(client_data); + FLAC__ASSERT(0 != instance); + return instance->write_callback(frame, buffer); + } + + void Stream::metadata_callback_(const ::FLAC__StreamDecoder *decoder, const ::FLAC__StreamMetadata *metadata, void *client_data) + { + (void)decoder; + FLAC__ASSERT(0 != client_data); + Stream *instance = reinterpret_cast(client_data); + FLAC__ASSERT(0 != instance); + instance->metadata_callback(metadata); + } + + void Stream::error_callback_(const ::FLAC__StreamDecoder *decoder, ::FLAC__StreamDecoderErrorStatus status, void *client_data) + { + (void)decoder; + FLAC__ASSERT(0 != client_data); + Stream *instance = reinterpret_cast(client_data); + FLAC__ASSERT(0 != instance); + instance->error_callback(status); + } + + }; +}; diff --git a/Makefile b/Makefile new file mode 100644 index 00000000000..79d78f295c0 --- /dev/null +++ b/Makefile @@ -0,0 +1,6 @@ +ifeq (Windows_NT,$(OS)) +include Makefile.mgw +else +all: + @echo Building with MinGW requires Windows NT +endif diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 00000000000..af437a64d6d --- /dev/null +++ b/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = src diff --git a/Makefile.mgw b/Makefile.mgw new file mode 100644 index 00000000000..32e8a1aee49 --- /dev/null +++ b/Makefile.mgw @@ -0,0 +1,44 @@ +RELEASETARGET = zdoomgcc.exe +DEBUGTARGET = zdoomgccd.exe + +all: basetools game +debug: basetools debuggame +release: basetools game + +ifndef CONFIG + CONFIG=Release +endif + +game: basetools ccdv.exe + @$(MAKE) -f Makefile.mingw + +debuggame: basetools ccdv.exe + @$(MAKE) CONFIG=Debug -f Makefile.mingw + +$(RELEASETARGET): game +$(DEBUGTARGET): debuggame + +basetools: ccdv.exe + $(MAKE) -C tools/lemon -f Makefile.mgw + $(MAKE) -C tools/re2c -f Makefile.mgw + $(MAKE) -C wadsrc -f Makefile.mgw + $(MAKE) -C zlib -f Makefile.mgw + $(MAKE) -C flac -f Makefile.mgw + +cleanexe: + @$(MAKE) -C . -f Makefile.mingw clean + +clean: + @$(MAKE) -C tools/lemon -f Makefile.mgw clean + @$(MAKE) -C tools/re2c -f Makefile.mgw clean + @$(MAKE) -C tools/dehsupp -f Makefile.mgw clean + @$(MAKE) -C tools/makewad -f Makefile.mgw clean + @$(MAKE) -C tools/xlatcc -f Makefile.mgw clean + @$(MAKE) -C wadsrc -f Makefile.mgw clean + @$(MAKE) -C . -f Makefile.mingw clean + @$(MAKE) -C zlib -f Makefile.mgw clean + @$(MAKE) -C flac -f Makefile.mgw clean + del /q /f ccdv.exe 2>nul + +ccdv.exe: ccdv-win32.c + @gcc -Os -s -nostdlib -fomit-frame-pointer -o ccdv.exe ccdv-win32.c -lkernel32 -luser32 diff --git a/Makefile.mingw b/Makefile.mingw new file mode 100644 index 00000000000..b708f19e935 --- /dev/null +++ b/Makefile.mingw @@ -0,0 +1,434 @@ +# Sub-makefile autogenerated by premake +# And then tweaked by hand + +ifndef CC + CC=gcc +endif +ifndef CXX + CC=g++ +endif + +ifndef CONFIG + CONFIG=Release +endif + +ifndef OPTLEVEL + OPTLEVEL=2 +endif + +ifndef ARCH_TYPE + ARCH_TYPE=pentium +endif + +ifndef TUNE_TYPE + TUNE_TYPE=athlon-xp +endif + +ifndef RELEASETARGET + RELEASETARGET = zdoomgcc.exe +endif +ifndef DEBUGTARGET + DEBUGTARGE = zdoomgccd.exe +endif +DEBUGOBJDIR = debugobj +RELEASEOBJDIR = releaseobj + +CCDV = @ccdv + +FMODDIR = c:/fmods/fmodapi374win + +CPPFLAGS = -DWIN32 -D_WIN32 -D_WINDOWS -DHAVE_STRUPR -DHAVE_FILELENGTH -DI_DO_NOT_LIKE_BIG_DOWNLOADS -D__forceinline=inline -MMD -Izlib -IFLAC -Isrc -Isrc/win32 -Isrc/g_doom -Isrc/g_heretic -I src/g_hexen -Isrc/g_raven -Isrc/g_strife -Isrc/g_shared -Isrc/oplsynth -Isrc/sound +LDFLAGS += flac/libflac.a zlib/libz.a -lfmod -lwsock32 -lwinmm -lddraw -ldsound -ldxguid -ldinput8 -lole32 -luser32 -lgdi32 -lcomctl32 -lcomdlg32 -lsetupapi -lws2_32 -Wl,--subsystem,windows + +ifdef FMODDIR + CPPFLAGS += -I$(FMODDIR)/api/inc + LDFLAGS += -L$(FMODDIR)/api/lib +endif + +ifeq ($(CONFIG),Debug) + OBJDIR = $(DEBUGOBJDIR) + CFLAGS += $(CPPFLAGS) -Wall -Wno-unused -g3 + CPPFLAGS += -D_DEBUG + CXXFLAGS = $(CFLAGS) + TARGET = $(DEBUGTARGET) +endif +ifeq ($(CONFIG),Release) + OBJDIR = $(RELEASEOBJDIR) + CFLAGS += $(CPPFLAGS) -march=$(ARCH_TYPE) -mtune=$(TUNE_TYPE) -Wall -Wno-unused -O$(OPTLEVEL) -fomit-frame-pointer + CPPFLAGS += -DNDEBUG + CXXFLAGS = $(CFLAGS) + LDFLAGS += -Wl,-Map=zdoomgcc.map + TARGET = $(RELEASETARGET) +endif + +# This must be first. +OBJECTS = $(OBJDIR)/autostart.o + +OBJECTS += \ + $(OBJDIR)/am_map.o \ + $(OBJDIR)/b_bot.o \ + $(OBJDIR)/b_func.o \ + $(OBJDIR)/b_game.o \ + $(OBJDIR)/b_move.o \ + $(OBJDIR)/b_think.o \ + $(OBJDIR)/bbannouncer.o \ + $(OBJDIR)/c_bind.o \ + $(OBJDIR)/c_cmds.o \ + $(OBJDIR)/c_console.o \ + $(OBJDIR)/c_cvars.o \ + $(OBJDIR)/c_dispatch.o \ + $(OBJDIR)/c_expr.o \ + $(OBJDIR)/cmdlib.o \ + $(OBJDIR)/colormatcher.o \ + $(OBJDIR)/configfile.o \ + $(OBJDIR)/ct_chat.o \ + $(OBJDIR)/d_dehacked.o \ + $(OBJDIR)/d_main.o \ + $(OBJDIR)/d_net.o \ + $(OBJDIR)/d_netinfo.o \ + $(OBJDIR)/d_protocol.o \ + $(OBJDIR)/decallib.o \ + $(OBJDIR)/decorations.o \ + $(OBJDIR)/dobject.o \ + $(OBJDIR)/doomdef.o \ + $(OBJDIR)/doomstat.o \ + $(OBJDIR)/dsectoreffect.o \ + $(OBJDIR)/dthinker.o \ + $(OBJDIR)/empty.o \ + $(OBJDIR)/f_finale.o \ + $(OBJDIR)/f_wipe.o \ + $(OBJDIR)/farchive.o \ + $(OBJDIR)/files.o \ + $(OBJDIR)/g_game.o \ + $(OBJDIR)/g_level.o \ + $(OBJDIR)/gameconfigfile.o \ + $(OBJDIR)/gi.o \ + $(OBJDIR)/hu_scores.o \ + $(OBJDIR)/info.o \ + $(OBJDIR)/infodefaults.o \ + $(OBJDIR)/lumpconfigfile.o \ + $(OBJDIR)/m_alloc.o \ + $(OBJDIR)/m_argv.o \ + $(OBJDIR)/m_bbox.o \ + $(OBJDIR)/m_cheat.o \ + $(OBJDIR)/m_fixed.o \ + $(OBJDIR)/m_menu.o \ + $(OBJDIR)/m_misc.o \ + $(OBJDIR)/m_options.o \ + $(OBJDIR)/m_png.o \ + $(OBJDIR)/m_random.o \ + $(OBJDIR)/mus2midi.o \ + $(OBJDIR)/nodebuild.o \ + $(OBJDIR)/nodebuild_events.o \ + $(OBJDIR)/nodebuild_extract.o \ + $(OBJDIR)/nodebuild_gl.o \ + $(OBJDIR)/nodebuild_utility.o \ + $(OBJDIR)/p_acs.o \ + $(OBJDIR)/p_buildmap.o \ + $(OBJDIR)/p_ceiling.o \ + $(OBJDIR)/p_conversation.o \ + $(OBJDIR)/p_doors.o \ + $(OBJDIR)/p_effect.o \ + $(OBJDIR)/p_enemy.o \ + $(OBJDIR)/p_floor.o \ + $(OBJDIR)/p_interaction.o \ + $(OBJDIR)/p_lights.o \ + $(OBJDIR)/p_lnspec.o \ + $(OBJDIR)/p_map.o \ + $(OBJDIR)/p_maputl.o \ + $(OBJDIR)/p_mobj.o \ + $(OBJDIR)/p_pillar.o \ + $(OBJDIR)/p_plats.o \ + $(OBJDIR)/p_pspr.o \ + $(OBJDIR)/p_saveg.o \ + $(OBJDIR)/p_sectors.o \ + $(OBJDIR)/p_setup.o \ + $(OBJDIR)/p_sight.o \ + $(OBJDIR)/p_spec.o \ + $(OBJDIR)/p_switch.o \ + $(OBJDIR)/p_teleport.o \ + $(OBJDIR)/p_terrain.o \ + $(OBJDIR)/p_things.o \ + $(OBJDIR)/p_tick.o \ + $(OBJDIR)/p_trace.o \ + $(OBJDIR)/p_user.o \ + $(OBJDIR)/p_writemap.o \ + $(OBJDIR)/p_xlat.o \ + $(OBJDIR)/po_man.o \ + $(OBJDIR)/r_bsp.o \ + $(OBJDIR)/r_data.o \ + $(OBJDIR)/r_draw.o \ + $(OBJDIR)/r_drawt.o \ + $(OBJDIR)/r_main.o \ + $(OBJDIR)/r_plane.o \ + $(OBJDIR)/r_segs.o \ + $(OBJDIR)/r_sky.o \ + $(OBJDIR)/r_things.o \ + $(OBJDIR)/r_polymost.o \ + $(OBJDIR)/s_advsound.o \ + $(OBJDIR)/s_environment.o \ + $(OBJDIR)/s_playlist.o \ + $(OBJDIR)/s_sndseq.o \ + $(OBJDIR)/s_sound.o \ + $(OBJDIR)/sc_man.o \ + $(OBJDIR)/skins.o \ + $(OBJDIR)/st_stuff.o \ + $(OBJDIR)/stats.o \ + $(OBJDIR)/stringtable.o \ + $(OBJDIR)/tables.o \ + $(OBJDIR)/tempfiles.o \ + $(OBJDIR)/thingdef.o \ + $(OBJDIR)/thingdef_codeptr.o \ + $(OBJDIR)/v_collection.o \ + $(OBJDIR)/v_draw.o \ + $(OBJDIR)/v_font.o \ + $(OBJDIR)/v_palette.o \ + $(OBJDIR)/v_pfx.o \ + $(OBJDIR)/v_text.o \ + $(OBJDIR)/v_video.o \ + $(OBJDIR)/vectors.o \ + $(OBJDIR)/name.o \ + $(OBJDIR)/zstring.o \ + $(OBJDIR)/zstringpool.o \ + $(OBJDIR)/zstrformat.o \ + $(OBJDIR)/w_wad.o \ + $(OBJDIR)/wi_stuff.o \ + $(OBJDIR)/a_arachnotron.o \ + $(OBJDIR)/a_archvile.o \ + $(OBJDIR)/a_bossbrain.o \ + $(OBJDIR)/a_bruiser.o \ + $(OBJDIR)/a_cacodemon.o \ + $(OBJDIR)/a_cyberdemon.o \ + $(OBJDIR)/a_demon.o \ + $(OBJDIR)/a_doomarmor.o \ + $(OBJDIR)/a_doomartifacts.o \ + $(OBJDIR)/a_doomdecorations.o \ + $(OBJDIR)/a_doomhealth.o \ + $(OBJDIR)/a_doomimp.o \ + $(OBJDIR)/a_doomkeys.o \ + $(OBJDIR)/a_doommisc.o \ + $(OBJDIR)/a_doomplayer.o \ + $(OBJDIR)/a_doomweaps.o \ + $(OBJDIR)/a_fatso.o \ + $(OBJDIR)/a_keen.o \ + $(OBJDIR)/a_lostsoul.o \ + $(OBJDIR)/a_painelemental.o \ + $(OBJDIR)/a_possessed.o \ + $(OBJDIR)/a_revenant.o \ + $(OBJDIR)/a_scriptedmarine.o \ + $(OBJDIR)/a_spidermaster.o \ + $(OBJDIR)/doom_sbar.o \ + $(OBJDIR)/a_beast.o \ + $(OBJDIR)/a_chicken.o \ + $(OBJDIR)/a_clink.o \ + $(OBJDIR)/a_dsparil.o \ + $(OBJDIR)/a_hereticambience.o \ + $(OBJDIR)/a_hereticarmor.o \ + $(OBJDIR)/a_hereticartifacts.o \ + $(OBJDIR)/a_hereticdecorations.o \ + $(OBJDIR)/a_hereticimp.o \ + $(OBJDIR)/a_heretickeys.o \ + $(OBJDIR)/a_hereticmisc.o \ + $(OBJDIR)/a_hereticplayer.o \ + $(OBJDIR)/a_hereticweaps.o \ + $(OBJDIR)/a_ironlich.o \ + $(OBJDIR)/a_knight.o \ + $(OBJDIR)/a_mummy.o \ + $(OBJDIR)/a_snake.o \ + $(OBJDIR)/a_wizard.o \ + $(OBJDIR)/heretic_sbar.o \ + $(OBJDIR)/a_bats.o \ + $(OBJDIR)/a_bishop.o \ + $(OBJDIR)/a_blastradius.o \ + $(OBJDIR)/a_boostarmor.o \ + $(OBJDIR)/a_centaur.o \ + $(OBJDIR)/a_clericboss.o \ + $(OBJDIR)/a_clericflame.o \ + $(OBJDIR)/a_clericholy.o \ + $(OBJDIR)/a_clericmace.o \ + $(OBJDIR)/a_clericplayer.o \ + $(OBJDIR)/a_clericstaff.o \ + $(OBJDIR)/a_demons.o \ + $(OBJDIR)/a_dragon.o \ + $(OBJDIR)/a_ettin.o \ + $(OBJDIR)/a_fighteraxe.o \ + $(OBJDIR)/a_fighterboss.o \ + $(OBJDIR)/a_fighterhammer.o \ + $(OBJDIR)/a_fighterplayer.o \ + $(OBJDIR)/a_fighterquietus.o \ + $(OBJDIR)/a_firedemon.o \ + $(OBJDIR)/a_flame.o \ + $(OBJDIR)/a_flechette.o \ + $(OBJDIR)/a_fog.o \ + $(OBJDIR)/a_healingradius.o \ + $(OBJDIR)/a_heresiarch.o \ + $(OBJDIR)/a_hexenarmor.o \ + $(OBJDIR)/a_hexendecorations.o \ + $(OBJDIR)/a_hexenkeys.o \ + $(OBJDIR)/a_hexenspecialdecs.o \ + $(OBJDIR)/a_iceguy.o \ + $(OBJDIR)/a_korax.o \ + $(OBJDIR)/a_mageboss.o \ + $(OBJDIR)/a_magecone.o \ + $(OBJDIR)/a_magelightning.o \ + $(OBJDIR)/a_mageplayer.o \ + $(OBJDIR)/a_magestaff.o \ + $(OBJDIR)/a_magewand.o \ + $(OBJDIR)/a_mana.o \ + $(OBJDIR)/a_pig.o \ + $(OBJDIR)/a_puzzleitems.o \ + $(OBJDIR)/a_scriptprojectiles.o \ + $(OBJDIR)/a_serpent.o \ + $(OBJDIR)/a_speedboots.o \ + $(OBJDIR)/a_spike.o \ + $(OBJDIR)/a_summon.o \ + $(OBJDIR)/a_teleportother.o \ + $(OBJDIR)/a_weaponpiece.o \ + $(OBJDIR)/a_wraith.o \ + $(OBJDIR)/hexen_sbar.o \ + $(OBJDIR)/a_artiegg.o \ + $(OBJDIR)/a_artitele.o \ + $(OBJDIR)/a_minotaur.o \ + $(OBJDIR)/a_ravenambient.o \ + $(OBJDIR)/a_ravenartifacts.o \ + $(OBJDIR)/a_ravenhealth.o \ + $(OBJDIR)/a_acolyte.o \ + $(OBJDIR)/a_alienspectres.o \ + $(OBJDIR)/a_beggars.o \ + $(OBJDIR)/a_coin.o \ + $(OBJDIR)/a_crusader.o \ + $(OBJDIR)/a_entityboss.o \ + $(OBJDIR)/a_inquisitor.o \ + $(OBJDIR)/a_loremaster.o \ + $(OBJDIR)/a_macil.o \ + $(OBJDIR)/a_merchants.o \ + $(OBJDIR)/a_oracle.o \ + $(OBJDIR)/a_peasant.o \ + $(OBJDIR)/a_programmer.o \ + $(OBJDIR)/a_questitems.o \ + $(OBJDIR)/a_ratbuddy.o \ + $(OBJDIR)/a_reaver.o \ + $(OBJDIR)/a_rebels.o \ + $(OBJDIR)/a_sentinel.o \ + $(OBJDIR)/a_spectral.o \ + $(OBJDIR)/a_stalker.o \ + $(OBJDIR)/a_strifeammo.o \ + $(OBJDIR)/a_strifearmor.o \ + $(OBJDIR)/a_strifebishop.o \ + $(OBJDIR)/a_strifeitems.o \ + $(OBJDIR)/a_strifekeys.o \ + $(OBJDIR)/a_strifeplayer.o \ + $(OBJDIR)/a_strifestuff.o \ + $(OBJDIR)/a_strifeweapons.o \ + $(OBJDIR)/a_templar.o \ + $(OBJDIR)/a_thingstoblowup.o \ + $(OBJDIR)/a_zombie.o \ + $(OBJDIR)/strife_sbar.o \ + $(OBJDIR)/a_action.o \ + $(OBJDIR)/a_artifacts.o \ + $(OBJDIR)/a_bridge.o \ + $(OBJDIR)/a_camera.o \ + $(OBJDIR)/a_debris.o \ + $(OBJDIR)/a_decals.o \ + $(OBJDIR)/a_flashfader.o \ + $(OBJDIR)/a_fountain.o \ + $(OBJDIR)/a_hatetarget.o \ + $(OBJDIR)/a_keys.o \ + $(OBJDIR)/a_lightning.o \ + $(OBJDIR)/a_movingcamera.o \ + $(OBJDIR)/a_pickups.o \ + $(OBJDIR)/a_quake.o \ + $(OBJDIR)/a_secrettrigger.o \ + $(OBJDIR)/a_sectoraction.o \ + $(OBJDIR)/a_sharedmisc.o \ + $(OBJDIR)/a_skies.o \ + $(OBJDIR)/a_soundenvironment.o \ + $(OBJDIR)/a_spark.o \ + $(OBJDIR)/a_splashes.o \ + $(OBJDIR)/a_waterzone.o \ + $(OBJDIR)/a_weapons.o \ + $(OBJDIR)/hudmessages.o \ + $(OBJDIR)/shared_sbar.o \ + $(OBJDIR)/fmopl.o \ + $(OBJDIR)/mlkernel.o \ + $(OBJDIR)/mlopl.o \ + $(OBJDIR)/mlopl_io.o \ + $(OBJDIR)/opl_mus_player.o \ + $(OBJDIR)/altsound.o \ + $(OBJDIR)/altsoundmixer.o \ + $(OBJDIR)/fmodsound.o \ + $(OBJDIR)/i_music.o \ + $(OBJDIR)/i_sound.o \ + $(OBJDIR)/music_cd.o \ + $(OBJDIR)/music_flac.o \ + $(OBJDIR)/music_midi_midiout.o \ + $(OBJDIR)/music_midi_stream.o \ + $(OBJDIR)/music_midi_timidity.o \ + $(OBJDIR)/music_mod.o \ + $(OBJDIR)/music_mus_midiout.o \ + $(OBJDIR)/music_mus_opl.o \ + $(OBJDIR)/music_spc.o \ + $(OBJDIR)/music_stream.o \ + $(OBJDIR)/sample_flac.o \ + $(OBJDIR)/helperthread.o \ + $(OBJDIR)/i_input.o \ + $(OBJDIR)/i_net.o \ + $(OBJDIR)/eaxedit.o \ + $(OBJDIR)/i_cd.o \ + $(OBJDIR)/i_main.o \ + $(OBJDIR)/i_system.o \ + $(OBJDIR)/hardware.o \ + $(OBJDIR)/i_crash.o \ + $(OBJDIR)/i_movie.o \ + $(OBJDIR)/win32video.o \ + $(OBJDIR)/zdoom.o + +ifndef NOASM + OBJECTS += \ + $(OBJDIR)/a.o \ + $(OBJDIR)/blocks.o \ + $(OBJDIR)/misc.o \ + $(OBJDIR)/tmap.o \ + $(OBJDIR)/tmap2.o \ + $(OBJDIR)/tmap3.o + CPPFLAGS := -DUSEASM=1 $(CPPFLAGS) +else + CPPFLAGS := -DNOASM $(CPPFLAGS) +endif + +# This must be last +OBJECTS += $(OBJDIR)/autozend.o + +VPATH = src src/g_doom src/g_heretic src/g_hexen src/g_raven src/g_strife src/g_shared src/oplsynth src/sound src/win32 + + +.PHONY: clean all + +all: $(TARGET) + + +$(OBJDIR)/%.o : %.cpp + $(CCDV) $(CXX) $(CXXFLAGS) -o $@ -c $< + +$(OBJDIR)/%.o : %.nas + $(CCDV) nasmw -o $@ -f win32 $< + +$(OBJDIR)/%.o : %.rc + $(CCDV) windres --include-dir=src/win32 -o $@ -i $< + + +$(TARGET): testobjdir $(OBJECTS) + $(CCDV) $(CXX) -o $@ $(OBJECTS) $(LDFLAGS) + +clean: + -del /q /f $(RELEASETARGET) 2>nul + -del /q /f $(DEBUGTARGET) 2>nul + -del /q /f $(DEBUGOBJDIR) 2>nul + -del /q /f $(RELEASEOBJDIR) 2>nul + +testobjdir: + -@if not exist $(OBJDIR) mkdir $(OBJDIR) + +ifneq ($(MAKECMDGOALS),clean) +-include $(OBJECTS:%.o=%.d) +endif diff --git a/bootstrap b/bootstrap new file mode 100644 index 00000000000..82393dfda7a --- /dev/null +++ b/bootstrap @@ -0,0 +1,10 @@ +#! /bin/sh +# Building with autoconf and automake has not been tested in some months. +# It may or may not work. + +set -x +aclocal -I config +autoheader +automake --foreign --add-missing --copy +autoconf + diff --git a/cbuild.c b/cbuild.c new file mode 100644 index 00000000000..1ab8f7e8da0 --- /dev/null +++ b/cbuild.c @@ -0,0 +1,2194 @@ +#define foobarbaz /* +# A shell script within a source file. Ugly, but it works... + +TRGT='cbuild' +for i in $@ ; do + if [ "$i" = "--make-compiled" ] ; then + echo "Compiling '$TRGT', please wait..." + gcc -W -Wall -O2 -o $TRGT $0 + exit $? + fi +done + +gcc -W -Wall -Werror -o /tmp/$TRGT "$0" && { "/tmp/$TRGT" `for i in $@ ; do echo "$i" ; done` ; RET=$? ; rm -f "/tmp/$TRGT" ; exit $RET ; } +exit $? + +*/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef _WIN32 + +static void setenv(const char *env, const char *val, int overwrite) +{ + static char buf[128]; + if(!overwrite && getenv(env)) + return; + + snprintf(buf, sizeof(buf), "%s=%s", env, val); + _putenv(buf); +} + +static void unsetenv(const char *env) +{ + setenv(env, "", 1); +} + +#ifdef _MSC_VER +#define strcasecmp stricmp +#define strncasecmp strnicmp +#define snprintf _snprintf +#endif + +#endif /* Win32 */ + +#define INVOKE_BKP_SIZE 16 +struct { + FILE *f; + char *bkp_lbuf; + char *bkp_nextline; + int bkp_line; + int bkp_did_else; + int bkp_did_cmds; + int bkp_do_level; +} invoke_backup[INVOKE_BKP_SIZE]; + +static struct stat statbuf; +static char linebuf[64*1024]; +static char buffer[64*1024]; +static char *loaded_files; +static char *sources; +static char obj[64]; +#define SRC_PATH_SIZE 32 +static char *src_paths[SRC_PATH_SIZE]; + +/* getvar: Safely gets an environment variable, returning an empty string + * instead of NULL + */ +static const char *getvar(const char *env) +{ + const char *var; + var = getenv(env); + return (var?var:""); +} + +/* find_src: Attempts to find the named sourcefile by searching the paths + * listed in src_paths. It returns the passed string if the file exists as-is, + * or if it couldn't be found. + */ +static char *find_src(char *src) +{ + static char buf[64]; + struct stat statbuf; + int i; + + if(stat(src, &statbuf) == 0 || !src_paths[0]) + return src; + + for(i = 0;src_paths[i] && i < SRC_PATH_SIZE;++i) + { + snprintf(buf, sizeof(buf), "%s/%s", src_paths[i], src); + if(stat(buf, &statbuf) == 0) + return buf; + } + return src; +} + +/* check_obj_deps: Checks a file's dependancy list. The dependancy file is a + * file expected to be in dep_dir and with the same name, but with a different + * extension. The format of the file is simply: 'file.o: dependancies...' where + * a '\' at the end of the line can be used as a next-line continuation. If the + * dependancy file exists, none of the dependancies are missing, and none have + * a modification time after 'obj_time', the function will return 0. Otherwise + * 1 is returned denoting a rebuild may be required. + */ +static int check_obj_deps(char *src, time_t obj_time) +{ + static char dep[64]; + char *buf; + int bufsize; + + struct stat statbuf; + char *ptr = obj; + FILE *df; + size_t i; + + ptr = strrchr(src, '/'); + if(!ptr) ptr = src; + ptr = strrchr(ptr, '.'); + if(ptr) *ptr = 0; + snprintf(dep, sizeof(dep), "%s/%s%s", getvar("DEP_DIR"), src, + getvar("DEP_EXT")); + if(ptr) *ptr = '.'; + + df = fopen(dep, "r"); + if(!df) + { + if(stat(src, &statbuf) != 0 || statbuf.st_mtime > obj_time) + return 1; + return 0; + } + + fseek(df, 0, SEEK_END); + bufsize = ftell(df)+1; + buf = malloc(bufsize); + if(!buf) + { + fclose(df); + return 1; + } + fseek(df, 0, SEEK_SET); + + i = 0; + while(fgets(buf+i, bufsize-i, df) != NULL) + { + i = strlen(buf); + if(buf[i-1] != '\\') + break; + } + + fclose(df); + + ptr = strchr(buf, ':'); + if(!ptr) + { + free(buf); + return 1; + } + ++ptr; + while(1) + { + char *stp; + while(*ptr && isspace(*ptr)) + { + if(*ptr == '\n') + { + free(buf); + return 0; + } + ++ptr; + } + if(!(*ptr)) + { + free(buf); + return 0; + } + + stp = ptr; + while(*stp && !isspace(*stp)) + { + if(*stp == '\\') + memmove(stp, stp+1, strlen(stp)); + ++stp; + } + *(stp++) = 0; + + if(strcmp(ptr, "\n") != 0 && (stat(ptr, &statbuf) != 0 || + statbuf.st_mtime > obj_time)) + { + free(buf); + return 1; + } + ptr = stp; + } +} + +/* copy_file: Copies the source file 'sf' to 'df', preserving the source's + * file mode and permissions, if possible. + */ +static int copy_file(const char *sf, const char *df) +{ + struct stat statbuf; + FILE *src, *dst; + int ret, i; + int fd; + + if(stat(sf, &statbuf) != 0) + return 1; + + fd = open(df, O_WRONLY|O_TRUNC|O_CREAT, statbuf.st_mode); + if(fd < 0) + return 1; + dst = fdopen(fd, "wb"); + if(!dst) + { + close(fd); + return 1; + } + + src = fopen(sf, "rb"); + if(!src) + { + fclose(dst); + return 1; + } + + ret = 0; + do { + i = fread(buffer, 1, sizeof(buffer), src); + if(i > 0) + i = fwrite(buffer, 1, i, dst); + if(i < 0) + ret = 1; + } while(i > 0); + + fclose(src); + fclose(dst); + return ret; +} + +/* extract_word: Extract a word starting at the string pointed to by 'str'. If + * the word begins with a ' or " character, everything until that same + * character will be considered part of the word. Otherwise, the word ends at + * the first encountered whitespace. Returns the beginning of the next word, + * or the end of the string. + */ +static char *extract_word(char **str) +{ + char *end; + char c; + + c = **str; + if(c == '"' || c == '\'') + { + ++(*str); + end = *str; + while(*end) + { + if(*end == c) + break; + ++end; + } + } + else + { + end = *str; + while(!isspace(*end) && *end) + ++end; + } + if(*end) *(end++) = 0; + while(isspace(*end) && *end) + ++end; + + return end; +} + + +/* build_obj_list: Builds a list of object files from the list of sources. If + * any of the objects don't exist or have a modification time later than + * 'base_time', the variable pointed to by 'do_link' will be set non-zero. + */ +static int build_obj_list(char *buffer, size_t bufsize, time_t base_time, + int *do_link) +{ + static char buf[64]; + + struct stat statbuf; + char *next = sources; + char *ptr; + int i = 0; + + while(*(ptr=next)) + { + char *ext; + char c = ' '; + + next = extract_word(&ptr); + if(ptr > sources) + { + c = *(ptr-1); + if(c != '"' && c != '\'') + c = ' '; + } + + ext = strrchr(ptr, '/'); + if(!ext) ext = ptr; + ext = strrchr(ext, '.'); + + if(ext) *ext = 0; + snprintf(buf, sizeof(buf), "%s/%s%s", getvar("OBJ_DIR"), ptr, + getvar("OBJ_EXT")); + if(ext) *ext = '.'; + + if(!(*do_link) && (stat(buf, &statbuf) != 0 || + base_time < statbuf.st_mtime)) + *do_link = 1; + + i += snprintf(buffer+i, bufsize-i, " \"%s\"", buf); + + ptr += strlen(ptr); + if(next > ptr) + *ptr = c; + } + return i; +} + +static int libify_name(char *buf, size_t buflen, char *name) +{ + int i; + char *curr = strrchr(name, '/'); + if(curr) + { + *curr = 0; + i = snprintf(buf, buflen, "%s/%s%s%s", name, getvar("LIB_PRE"), + curr+1, getvar("LIB_EXT")); + *curr = '/'; + } + else + i = snprintf(buf, buflen, "%s%s%s", getvar("LIB_PRE"), name, + getvar("LIB_EXT")); + return i; +} + + +static char *strrpbrk(char *str, char *brk, int len) +{ + char *ptr = str+len; + + while((--ptr) >= str) + { + char *c = brk; + while(*c) + { + if(*(c++) == *ptr) + return ptr; + } + } + + return NULL; +} + + +int main(int argc, char **argv) +{ + FILE *f; + int do_level = 0, wait_for_done = 0; + int did_cmds = 0, did_else = 0; + int curr_line = 0; + char *ptr, *nextline = NULL, *nextcmd = NULL; + int ret = 0, tmp = 0, i; + int ignored_errors = 0; + int verbose = 0; + int shh; + + setenv("CC", "gcc", 0); + setenv("CXX", "g++", 0); + setenv("LD", "gcc", 0); + setenv("OUT_OPT", "-o ", 0); + setenv("SRC_OPT", "-c ", 0); + setenv("DEP_OPT", "-MMD -MF ", 0); + setenv("OBJ_EXT", ".o", 0); + setenv("OBJ_DIR", ".", 0); + setenv("DEP_EXT", ".d", 0); + setenv("DEP_DIR", ".", 0); +#ifdef _WIN32 + setenv("EXE_EXT", ".exe", 0); +#else + setenv("EXE_EXT", "", 0); +#endif + setenv("AR", "ar", 0); + setenv("AR_OPT", "", 0); + setenv("LIB_PRE", "lib", 0); + setenv("LIB_EXT", ".a", 0); + setenv("CPPFLAGS", "", 0); + setenv("CFLAGS", "", 0); + setenv("CXXFLAGS", "", 0); + setenv("LDFLAGS", "", 0); + + /* Open the default file */ + f = fopen("default.cbd", "r"); + if(!f) + { + fprintf(stderr, "\n\n\n*** Critical Error ***\n" + "Could not open 'default.cbd'!\n\n"); + exit(1); + } + +main_loop_start: + while(1) + { + int line_count, len; + int ignore_err = 0; + int in_quote = 0; + int has_do = 0; + int reverse; + + /* If we already have the next line set, go do it */ + if(nextcmd) + { + memmove(linebuf, nextcmd, strlen(nextcmd)+1); + nextcmd = NULL; + goto reparse; + } + + /* If we already have the next line set, go do it */ + if(nextline) + { + memmove(linebuf, nextline, strlen(nextline)+1); + nextline = NULL; + goto reparse; + } + + /* Grab the next line and increment the line count */ + if(fgets(linebuf, sizeof(linebuf), f) == NULL) + { + if(!invoke_backup[0].f) + break; + + /* If end of file, check if we should uninvoke and continue */ + for(i = 1;i <= INVOKE_BKP_SIZE;++i) + { + if(i == INVOKE_BKP_SIZE || !invoke_backup[i].f) + { + --i; + fclose(f); + f = invoke_backup[i].f; + invoke_backup[i].f = NULL; + + strcpy(linebuf, invoke_backup[i].bkp_lbuf); + free(invoke_backup[i].bkp_lbuf); + + if(invoke_backup[i].bkp_nextline) + { + nextline = linebuf+strlen(linebuf)+1; + strcpy(nextline, invoke_backup[i].bkp_nextline); + free(invoke_backup[i].bkp_nextline); + } + + curr_line = invoke_backup[i].bkp_line; + did_else = invoke_backup[i].bkp_did_else; + did_cmds = invoke_backup[i].bkp_did_cmds; + do_level = invoke_backup[i].bkp_do_level; + + goto main_loop_start; + } + } + break; + } + ++curr_line; + + line_count = 0; + ptr = linebuf; + do { + while((ptr=strpbrk(ptr, "$'\"#")) != NULL) + { + /* Enter in-quote mode (disables ''-quoting and #-comments) */ + if(*ptr == '\"') + { + in_quote ^= 1; + ++ptr; + continue; + } + + /* A '#' kills the rest of the line */ + if(*ptr == '#' && !in_quote) + { + char *next = strchr(ptr, '\n'); + if(next) + memmove(ptr, next, strlen(next)+1); + else + *ptr = 0; + continue; + } + + /* Jump past a hard quote (don't expand anything) */ + if(*ptr == '\'' && !in_quote) + { + int add_count = 0; + char *next = strchr(ptr+1, '\''); + /* Find the closing '. If it's not found, assume it's a + * multi-line quote */ + while(!next) + { + next = ptr+strlen(ptr); + if(sizeof(linebuf) == next-linebuf) + { + printf("!!! Error, line %d !!!\n" + "Unterminated hard quote!", curr_line); + ret = -1; + goto end; + } + + if(fgets(next, sizeof(linebuf)-(next-linebuf), f) == + NULL) + break; + next = strchr(ptr+1, '\''); + ++add_count; + } + ptr = next; + curr_line += add_count; + ++ptr; + continue; + } + + /* Apend the next line to this one */ + if(strcmp(ptr, "$\n") == 0) + { + ptr += 2; + if(fgets(ptr, sizeof(linebuf)-(ptr-linebuf), f) == NULL) + break; + ++curr_line; + continue; + } + + ++ptr; + } + if(!in_quote) + break; + ptr = linebuf+strlen(linebuf); + if(fgets(ptr, sizeof(linebuf)-(ptr-linebuf), f) == NULL) + { + printf("!!! Error, line %d !!!\n" + "Unterminated quote!", curr_line); + ret = -1; + goto end; + } + ++line_count; + } while(1); + curr_line += line_count; + + /* Check for the special '$' char, expanding variables as needed */ + do { + len = strlen(linebuf); + in_quote = 0; + tmp = 0; + ptr = linebuf; + + while((ptr=strrpbrk(linebuf, "$'\"", len)) != NULL) + { + len = ptr-linebuf; + + /* Enter in-quote mode (disables ''-quoting and #-comments) */ + if(*ptr == '\"') + { + in_quote ^= 1; + continue; + } + + /* A '#' kills the rest of the line */ + if(*ptr == '#' && !in_quote) + { + char *next = strchr(ptr, '\n'); + if(next) + memmove(ptr, next, strlen(next)+1); + else + *ptr = 0; + continue; + } + + /* Jump past a hard quote (don't expand anything) */ + if(*ptr == '\'' && !in_quote) + { + char *next; + + *ptr = 0; + next = strrchr(linebuf, '\''); + if(!next) + { + printf("!!! Error, line %d !!!\n" + "Unterminated hard quote!", curr_line); + ret = -1; + goto end; + } + *ptr = '\''; + + len = next-linebuf; + continue; + } + + ++ptr; + + /* Insert the environment var named between the {} */ + if(*ptr == '{') + { + char *end = strchr(ptr, '}'); + if(!end) + end = ptr+strlen(ptr); + else + *(end++) = 0; + *(--ptr) = 0; + snprintf(buffer, sizeof(buffer), "%s%s%s", linebuf, + getvar(ptr+2), end); + strcpy(linebuf, buffer); + tmp = 1; + continue; + } + + /* Run a special command, replacing the section */ + if(*ptr == '(') + { + char *next = strchr(ptr, ')'), *opt; + if(!next) + continue; + + tmp = 1; + *(ptr-1) = 0; + *(next++) = 0; + + ++ptr; + opt = extract_word(&ptr); + + /* Replaces the section with the specified command line + * option's value (in the format 'option=value') */ + if(strcasecmp(ptr, "getoptval") == 0) + { + const char *val = ""; + int len; + len = snprintf(buffer, sizeof(buffer), "%s=", opt); + for(i = 1;i < argc;++i) + { + if(strncasecmp(buffer, argv[i], len) == 0) + { + val = argv[i]+len; + break; + } + } + snprintf(buffer, sizeof(buffer), "%s%s%s", linebuf, + val, next); + strcpy(linebuf, buffer); + continue; + } + + /* Returns a library-style name from the specified + * filename */ + if(strcasecmp(ptr, "libname") == 0) + { + libify_name(obj, sizeof(obj), opt); + snprintf(buffer, sizeof(buffer), "%s%s%s", linebuf, + obj, next); + strcpy(linebuf, buffer); + continue; + } + + if(strcasecmp("ifeq", ptr) == 0) + { + char *var2; + char *val; + + var2 = strchr(opt, ','); + if(!var2) + { + printf("\n\n!!! Error, line %d !!!\n" + "Malformed 'ifeq' sub-command!\n\n", + curr_line); + ret = 1; + goto end; + } + *(var2++) = 0; + val = strchr(var2, ','); + if(!val) + { + printf("\n\n!!! Error, line %d !!!\n" + "Malformed 'ifeq' sub-command!\n\n", + curr_line); + ret = 1; + goto end; + } + *(val++) = 0; + if(strcmp(opt, var2) == 0) + { + char *sep = strchr(val, ','); + if(sep) *sep = 0; + } + else + { + val = strchr(val, ','); + if(val) ++val; + } + + snprintf(buffer, sizeof(buffer), "%s%s%s", linebuf, + (val?val:""), next); + strcpy(linebuf, buffer); + continue; + } + + printf("\n\n!!! Error, line %d !!!\n" + "Unknown sub-command '%s'\n\n", curr_line, ptr); + goto end; + } + } + } while(tmp); + + /* Now check for '$'-escapes */ + ptr = linebuf; + while((ptr=strpbrk(ptr, "$'\"")) != NULL) + { + if(*ptr == '"') + { + ptr = strchr(ptr+1, '"'); + if(!ptr) + break; + continue; + } + + if(*ptr == '\'' && !in_quote) + { + ptr = strchr(ptr+1, '\''); + if(!ptr) + break; + continue; + } + + ++ptr; + + /* Just a normal "escaped" character, pull the rest of the line + * back one. '$\n' will be handled later */ + if(*ptr != '\n') + memmove(ptr-1, ptr, strlen(ptr)+1); + else + ++ptr; + } + +reparse: + reverse = 0; + shh = 0; + + /* Get the next line */ + if(!nextline) + { + int in_quotes = 0; + + nextline = linebuf; + while(*nextline && *nextline != '\n') + { + if(*nextline == '"') + in_quotes ^= 1; + if(!in_quotes) + { + if(*nextline == '\'') + { + nextline = strchr(nextline+1, '\''); + if(!nextline) + break; + } + if(nextline[0] == '$' && nextline[1] == '\n') + memmove(nextline, nextline+1, strlen(nextline)); + } + ++nextline; + } + if(nextline) + { + if(*nextline) + *(nextline++) = 0; + if(!(*nextline)) + nextline = NULL; + } + } + + /* Chew up leading whitespace */ + for(i = 0;linebuf[i];++i) + { + if(!isspace(linebuf[i])) + { + if(i > 0) + { + memmove(linebuf, linebuf+i, strlen(linebuf)+1-i); + i = 0; + } + break; + } + } + if(!linebuf[i]) + continue; + + /* Find the end of the command name */ + ptr = linebuf; + while(*ptr && !isspace(*ptr)) + ++ptr; + + if(*ptr) + { + /* If found, NULL it and get the beginning of the option */ + tmp = *ptr; + *(ptr++) = 0; + while(isspace(*ptr) && *ptr) + ++ptr; + } + + /* Check for special 'level'ing commands */ + /* The 'do' command pushes us up a level, and checks for the next + * if-type command, which itself will let us know if we should start + * ignoring commands */ + if(strcasecmp("do", linebuf) == 0) + { + has_do = 1; + ++do_level; + memmove(linebuf, ptr, strlen(ptr)+1); + goto reparse; + } + /* 'else' toggles ignoring commands at the current level */ + if(strcasecmp("else", linebuf) == 0) + { + if(do_level <= 0) + { + fprintf(stderr, "\n\n!!! Error, line %d !!!\n" + "'else' statement encountered without 'do'!\n", + curr_line); + goto end; + } + + /* TODO: allow another if-type command to follow an else on the + * same level */ + if(!(wait_for_done & (1<<(do_level-1)))) + { + wait_for_done |= 1<<(do_level-1); + did_cmds |= 1<<(do_level-1); + has_do = 0; + } + + if(!(did_cmds & (1<<(do_level-1)))) + { + wait_for_done &= ~(1<<(do_level-1)); + has_do = 1; + } + + memmove(linebuf, ptr, strlen(ptr)+1); + goto reparse; + } + /* 'done' takes us down a level */ + if(strcasecmp("done", linebuf) == 0) + { + if(do_level <= 0) + { + fprintf(stderr, "\n\n!!! Error, line %d !!!\n" + "'done' statement encountered without 'do'!\n", + curr_line); + goto end; + } + wait_for_done &= ~(1<<(--do_level)); + did_else &= ~(1< loaded_files && (*(curr-1) == '\'' || + *(curr-1) == '"')) + c = *(curr-1); + + i = 0; + while(*cmd_ptr) + { + do { + nuller = strchr(cmd_ptr, '<'); + if(!nuller || (nuller[1] == '@' && nuller[2] == '>')) + break; + cmd_ptr = nuller+1; + } while(1); + if(!nuller) + break; + *nuller = 0; + + i += snprintf(buffer+i, sizeof(buffer)-i, "%s%s", cmd_ptr, + curr); + + *nuller = '<'; + cmd_ptr = nuller+3; + } + i += snprintf(buffer+i, sizeof(buffer)-i, "%s", cmd_ptr); + + if(!shh) + { + printf("%s\n", buffer); + fflush(stdout); + } + if((ret=system(buffer)) != 0) + { + tmp = 1; + if(!ignore_err) + goto end; + if(ignore_err < 2) + printf("--- Error %d ignored. ---\n\n", + ++ignored_errors); + fflush(stdout); + } + + curr += strlen(curr); + if(*next) + { + *(curr++) = c; + if(curr < next) + memmove(curr, next, strlen(next)+1); + } + } + ret = tmp; + continue; + } + + /* Prints a string to the console. If a '.' char is used at the + * beginning of string, it will be skipped */ + if(strcasecmp("echo", linebuf) == 0) + { + if(ptr[0] == '.') + ++ptr; + printf("%s\n", ptr); + fflush(stdout); + continue; + } + + /* Prints a string to the console without a newline. If a '.' char is + * used at the beginning of string, it will be skipped */ + if(strcasecmp("put", linebuf) == 0) + { + if(ptr[0] == '.') + ++ptr; + printf("%s", ptr); + fflush(stdout); + continue; + } + + /* Creates/truncates a file and writes a string to it */ + if(strcasecmp("writefile", linebuf) == 0) + { + char *str; + FILE *o; + + str = extract_word(&ptr); + o = fopen(ptr, "w"); + if(!o) + { + ret = 1; + if(!ignore_err) + { + printf("Could not create file '%s'!\n", ptr); + goto end; + } + if(ignore_err < 2) + { + printf("Could not create file '%s'!\n" + "--- Error %d ignored. ---\n\n", ptr, + ++ignored_errors); + fflush(stdout); + } + continue; + } + + if(str[0] == '.') + ++str; + fprintf(o, "%s\n", str); + fclose(o); + continue; + } + + /* Appends a string to a file */ + if(strcasecmp("appendfile", linebuf) == 0) + { + char *str; + FILE *o; + + str = extract_word(&ptr); + o = fopen(ptr, "a"); + if(!o) + { + ret = 1; + if(!ignore_err) + { + printf("Could not create file '%s'!\n", ptr); + goto end; + } + if(ignore_err < 2) + { + printf("Could not create file '%s'!\n" + "--- Error %d ignored. ---\n\n", ptr, + ++ignored_errors); + fflush(stdout); + } + continue; + } + + if(str[0] == '.') + ++str; + fprintf(o, "%s\n", str); + fclose(o); + continue; + } + + /* Jumps to the specified label. A label is denoted by a '#:' combo + * prepended to it at the beginning of a line */ + if(strcasecmp("goto", linebuf) == 0) + { + int src_line; + char *lbl; + lbl = strdup(ptr); + if(!lbl) + { + fprintf(stderr, "\n\n\n** Critical Error **\n" + "Out of memory duplicating string '%s'\n\n", + lbl); + ret = -1; + goto end; + } + + rewind(f); + src_line = curr_line; + curr_line = 0; + while(fgets(linebuf, sizeof(linebuf), f) != NULL) + { + ++curr_line; + if(linebuf[0] == '#' && linebuf[1] == ':') + { + ptr = strpbrk(linebuf, "\r\n"); + if(ptr) *ptr = 0; + if(strcasecmp(linebuf+2, lbl) == 0) + { + free(lbl); + nextline = NULL; + goto main_loop_start; + } + } + } + fprintf(stderr, "\n\n!!! Error, line %d !!!\n" + "Label target '%s' not found!\n\n", src_line, lbl); + free(lbl); + ret = -1; + goto end; + } + + + /* Stores a list of paths to look for source files in. Passing only + * '.' clears the list. */ + if(strcasecmp("src_paths", linebuf) == 0) + { + unsigned int count = 0; + char *next; + + while(src_paths[count] && count < SRC_PATH_SIZE) + { + free(src_paths[count]); + src_paths[count] = NULL; + ++count; + } + + if(strcmp(ptr, ".") == 0) + continue; + + count = 0; + while(*ptr) + { + if(count >= SRC_PATH_SIZE) + { + printf("\n\n!!! Error, line %d !!!\n" + "Too many source paths specified!\n\n", + ++curr_line); + ret = -1; + goto end; + } + + next = extract_word(&ptr); + src_paths[count] = strdup(ptr); + if(!src_paths[count++]) + { + fprintf(stderr, "\n\n\n** Critical Error **\n" + "Out of memory duplicating string " + "'%s'\n\n", ptr); + ret = -1; + goto end; + } + ptr = next; + } + continue; + } + + /* Deletes the specified executables, appending 'EXE_EXT' to the names + * as needed */ + if(strcasecmp("rmexec", linebuf) == 0) + { + char *next; + do { + next = extract_word(&ptr); + snprintf(buffer, sizeof(buffer), "%s%s", ptr, + getvar("EXE_EXT")); + + if(stat(buffer, &statbuf) == -1 && errno == ENOENT) + continue; + + if(!shh) + { + if(verbose) printf("remove(\"%s\");\n", buffer); + else printf("Deleting %s...\n", buffer); + fflush(stdout); + } + if((ret=remove(buffer)) != 0) + { + if(ignore_err < 2) + printf("!!! Could not delete file !!!\n"); + if(!ignore_err) + goto end; + if(ignore_err < 2) + printf("--- Error %d ignored. ---\n\n", + ++ignored_errors); + fflush(stdout); + } + } while(*(ptr=next)); + + continue; + } + + /* Deletes the specified libraries, prepending 'LIB_PRE' to the + * filename portions and appending with 'LIB_EXT' */ + if(strcasecmp("rmlib", linebuf) == 0) + { + char *next; + do { + next = extract_word(&ptr); + libify_name(buffer, sizeof(buffer), ptr); + + if(stat(buffer, &statbuf) == -1 && errno == ENOENT) + continue; + + if(!shh) + { + if(verbose) printf("remove(\"%s\");\n", buffer); + else printf("Deleting %s...\n", buffer); + fflush(stdout); + } + if((ret=remove(buffer)) != 0) + { + if(ignore_err < 2) + printf("!!! Could not delete file !!!\n"); + if(!ignore_err) + goto end; + if(ignore_err < 2) + printf("--- Error %d ignored. ---\n\n", + ++ignored_errors); + fflush(stdout); + } + } while(*(ptr=next)); + continue; + } + + /* Removes a list of object files and their associated dependancy + * files, replacing the extension of the named file as necesarry */ + if(strcasecmp("rmobj", linebuf) == 0) + { + char *ext; + char *next; + do { + next = extract_word(&ptr); + + ext = strrchr(ptr, '/'); + if(!ext) ext = ptr; + ext = strrchr(ext, '.'); + + if(ext) *ext = 0; + snprintf(buffer, sizeof(buffer), "%s/%s%s", getvar("OBJ_DIR"), + ptr, getvar("OBJ_EXT")); + if(ext) *ext = '.'; + + if(stat(buffer, &statbuf) == 0 || errno != ENOENT) + { + if(!shh) + { + if(verbose) printf("remove(\"%s\");\n", buffer); + else printf("Deleting %s...\n", buffer); + fflush(stdout); + } + if((ret=remove(buffer)) != 0) + { + if(ignore_err < 2) + printf("!!! Could not delete file !!!\n"); + if(!ignore_err) + goto end; + if(ignore_err < 2) + printf("--- Error %d ignored. ---\n\n", + ++ignored_errors); + } + } + + if(ext) *ext = 0; + snprintf(buffer, sizeof(buffer), "%s/%s%s", getvar("DEP_DIR"), + ptr, getvar("DEP_EXT")); + if(ext) *ext = '.'; + + if(stat(buffer, &statbuf) == -1 && errno == ENOENT) + continue; + + if(!shh) + { + if(verbose) printf("remove(\"%s\");\n", buffer); + else printf("Deleting %s...\n", buffer); + fflush(stdout); + } + if((ret=remove(buffer)) != 0) + { + if(ignore_err < 2) + printf("!!! Could not delete file !!!\n"); + if(!ignore_err) + goto end; + if(ignore_err < 2) + printf("--- Error %d ignored. ---\n\n", + ++ignored_errors); + fflush(stdout); + } + } while(*(ptr=next)); + continue; + } + + /* Removes a list of files or empty directories */ + if(strcasecmp("rm", linebuf) == 0) + { + char *next; + do { + next = extract_word(&ptr); + + if(stat(ptr, &statbuf) == -1 && errno == ENOENT) + continue; + + if(!shh) + { + if(verbose) printf("remove(\"%s\");\n", ptr); + else printf("Deleting %s...\n", ptr); + fflush(stdout); + } + if((ret=remove(ptr)) != 0) + { + if(ignore_err < 2) + printf("!!! Could not delete !!!\n"); + if(!ignore_err) + goto end; + if(ignore_err < 2) + printf("--- Error %d ignored. ---\n\n", + ++ignored_errors); + fflush(stdout); + } + } while(*(ptr=next)); + continue; + } + + /* Creates a directory (with mode 700 in Unix) */ + if(strcasecmp("mkdir", linebuf) == 0) + { + extract_word(&ptr); + + if(!shh) + { + if(!verbose) printf("Creating directory %s/...\n", ptr); +#ifdef _WIN32 + else printf("mkdir(\"%s\");\n", ptr); + fflush(stdout); + } + if((ret=mkdir(ptr)) != 0) +#else + else printf("mkdir(\"%s\", S_IRWXU);\n", ptr); + fflush(stdout); + } + if((ret=mkdir(ptr, S_IRWXU)) != 0) +#endif + { + if(ignore_err < 2) + printf("!!! Could not create directory !!!\n"); + if(!ignore_err) + goto end; + if(ignore_err < 2) + printf("--- Error %d ignored. ---\n\n", ++ignored_errors); + fflush(stdout); + } + continue; + } + + /* Enables/disables command verboseness */ + if(strcasecmp("verbose", linebuf) == 0) + { + verbose = (atoi(ptr) != 0); + continue; + } + + /* Leaves the current script, falling back to the previous if the + * current was started with the invoke command. Otherwise, it behaves + * like exit */ + if(strcasecmp("uninvoke", linebuf) == 0) + { + ret = atoi(ptr); + if(!invoke_backup[0].f) + goto end; + + for(i = 1;i <= INVOKE_BKP_SIZE;++i) + { + if(i == INVOKE_BKP_SIZE || !invoke_backup[i].f) + { + --i; + fclose(f); + f = invoke_backup[i].f; + invoke_backup[i].f = NULL; + + strcpy(linebuf, invoke_backup[i].bkp_lbuf); + free(invoke_backup[i].bkp_lbuf); + + if(invoke_backup[i].bkp_nextline) + { + nextline = linebuf+strlen(linebuf)+1; + strcpy(nextline, invoke_backup[i].bkp_nextline); + free(invoke_backup[i].bkp_nextline); + } + + curr_line = invoke_backup[i].bkp_line; + did_else = invoke_backup[i].bkp_did_else; + did_cmds = invoke_backup[i].bkp_did_cmds; + do_level = invoke_backup[i].bkp_do_level; + + break; + } + } + + if(ret != 0) + { + if(!ignore_err) + goto end; + if(ignore_err < 2) + printf("--- Error %d ignored. ---\n\n", ++ignored_errors); + fflush(stdout); + } + + continue; + } + + /* Copies a file */ + if(strcasecmp("copy", linebuf) == 0) + { + char *dfile; + + dfile = extract_word(&ptr); + if(!(*dfile)) + { + if(ignore_err < 2) + printf("\n\n!!! Error, line %d !!! \n" + "Improper arguments to 'copy'!\n", curr_line); + if(!ignore_err) + goto end; + if(ignore_err < 2) + printf("--- Error %d ignored. ---\n", ++ignored_errors); + fflush(stdout); + continue; + } + extract_word(&dfile); + if(dfile[strlen(dfile)-1] == '/') + { + char *fn = strrchr(ptr, '/'); + snprintf(obj, sizeof(obj), "%s%s", dfile, (fn?(fn+1):ptr)); + dfile = obj; + } + if(!shh) + { + if(verbose) printf("copy_file(\"%s\", \"%s\");\n", ptr, dfile); + else printf("Copying '%s' to '%s'...\n", ptr, dfile); + fflush(stdout); + } + if(copy_file(ptr, dfile) != 0) + { + if(ignore_err < 2) + printf("!!! Could not copy !!!\n"); + if(!ignore_err) + goto end; + if(ignore_err < 2) + printf("--- Error %d ignored. ---\n\n", ++ignored_errors); + fflush(stdout); + } + continue; + } + + /* Copies a library file, prepending and appending the names as + * necesarry */ + if(strcasecmp("copylib", linebuf) == 0) + { + char *dfile; + + dfile = extract_word(&ptr); + if(!(*dfile)) + { + if(ignore_err < 2) + printf("\n\n!!! Error, line %d !!! \n" + "Improper arguments to 'copylib'!\n", curr_line); + if(!ignore_err) + goto end; + if(ignore_err < 2) + printf("--- Error %d ignored. ---\n", ++ignored_errors); + fflush(stdout); + continue; + } + extract_word(&dfile); + if(dfile[strlen(dfile)-1] == '/') + { + char *fn = strrchr(ptr, '/'); + snprintf(obj, sizeof(obj), "%s%s", dfile, (fn?(fn+1):ptr)); + libify_name(buffer, sizeof(buffer), obj); + } + else + libify_name(buffer, sizeof(buffer), dfile); + + libify_name(obj, sizeof(obj), ptr); + + if(!shh) + { + if(verbose) printf("copy_file(\"%s\", \"%s\");\n", obj, buffer); + else printf("Copying '%s' to '%s'...\n", obj, buffer); + fflush(stdout); + } + if(copy_file(obj, buffer) != 0) + { + if(ignore_err < 2) + printf("!!! Could not copy !!!\n"); + if(!ignore_err) + goto end; + if(ignore_err < 2) + printf("--- Error %d ignored. ---\n\n", ++ignored_errors); + fflush(stdout); + } + continue; + } + + /* Copies an executable file, appending the names as necesarry */ + if(strcasecmp("copyexec", linebuf) == 0) + { + char *dfile; + + dfile = extract_word(&ptr); + if(!(*dfile)) + { + if(ignore_err < 2) + printf("\n\n!!! Error, line %d !!! \n" + "Improper arguments to 'copyexec'!\n", curr_line); + if(!ignore_err) + goto end; + if(ignore_err < 2) + printf("--- Error %d ignored. ---\n", ++ignored_errors); + fflush(stdout); + continue; + } + extract_word(&dfile); + if(dfile[strlen(dfile)-1] == '/') + { + char *fn = strrchr(ptr, '/'); + snprintf(obj, sizeof(obj), "%s%s", dfile, (fn?(fn+1):ptr)); + snprintf(buffer, sizeof(buffer), "%s%s", obj, + getvar("EXE_EXT")); + } + else + snprintf(buffer, sizeof(buffer), "%s%s", dfile, + getvar("EXE_EXT")); + + libify_name(obj, sizeof(obj), ptr); + snprintf(obj, sizeof(obj), "%s%s", ptr, getvar("EXE_EXT")); + + if(!shh) + { + if(verbose) printf("copy_file(\"%s\", \"%s\");\n", obj, buffer); + else printf("Copying '%s' to '%s'...\n", obj, buffer); + fflush(stdout); + } + if(copy_file(obj, buffer) != 0) + { + if(ignore_err < 2) + printf("!!! Could not copy !!!\n"); + if(!ignore_err) + goto end; + if(ignore_err < 2) + printf("--- Error %d ignored. ---\n\n", ++ignored_errors); + fflush(stdout); + } + continue; + } + + /* Exits the script with the specified exitcode */ + if(strcasecmp("exit", linebuf) == 0) + { + ret = atoi(ptr); + goto end; + } + + printf("\n\n!!! Error, line %d !!!\n" + "Unknown command '%s'\n\n", curr_line, linebuf); + break; + } + +end: + fflush(stdout); + i = 0; + while(src_paths[i] && i < SRC_PATH_SIZE) + free(src_paths[i++]); + i = 0; + while(i < INVOKE_BKP_SIZE && invoke_backup[i].f) + { + fclose(invoke_backup[i].f); + free(invoke_backup[i].bkp_lbuf); + free(invoke_backup[i].bkp_nextline); + ++i; + } + free(loaded_files); + free(sources); + fclose(f); + return ret; +} diff --git a/ccdv-win32.c b/ccdv-win32.c new file mode 100644 index 00000000000..98c6169abf0 --- /dev/null +++ b/ccdv-win32.c @@ -0,0 +1,610 @@ +/* ccdv.c */ + +/* Ported to Win32 by Randy Heit + * Maybe I got a little carried away. This is pure Win32 code without any CRT in sight. + * + * To build this, use one of these command lines: + * + * [MinGW] gcc -Os -s -nostdlib -o ccdv.exe ccdv-win32.c -lkernel32 -luser32 + * [MSC] cl -O1 ccdv-win32.c -link -subsystem:console -opt:nowin98 kernel32.lib user32.lib + * + * Rewriting this to not use any global variables can save 512 bytes when compiled with MSC + * because it allows the .data section to be ommitted, which means the header can occupy + * 512 bytes rather than 1024. With GCC, it doesn't help the size any, since GCC still has + * the separate .idata and .rdata sections. Since MSC really doesn't need this tool, + * I'm not bothering with that size optimization. + */ + +#define WIN32_LEAN_AND_MEAN +#include + +#define COLOR_SUCCESS (FOREGROUND_GREEN|FOREGROUND_INTENSITY) /* green */ +#define COLOR_FAILURE (FOREGROUND_RED|FOREGROUND_INTENSITY) /* red */ +#define COLOR_WARNING (FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_INTENSITY) /* yellow */ +#define COLOR_COMMAND (FOREGROUND_GREEN|FOREGROUND_BLUE|FOREGROUND_INTENSITY) /* cyan */ + +#define TEXT_BLOCK_SIZE 8192 +#define INDENT 2 + +PROCESS_INFORMATION gCCP; +size_t gNBufUsed, gNBufAllocated; +char *gBuf; +char *gAction; +char *gTarget; +char *gAr; +char *gArLibraryTarget; +BOOL gDumpCmdArgs; +char *gArgsStr; +int gColumns; +int gExitStatus; +HANDLE gHeap; + +HANDLE gStdOut, gStdErr; + +#ifdef __GNUC__ +#define REGPARM(x) __attribute((regparm(x))) +#else +#define REGPARM(x) +#endif + +void REGPARM(1) perror(const char *string) +{ + char *buffer; + DWORD error = GetLastError(); + DWORD len = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, error, 0, (LPTSTR)&buffer, 0, NULL); + DWORD wrote; + WriteFile (gStdErr, string, lstrlen(string), &wrote, NULL); + if(len == 0) + { + char errcode[9]; + wsprintf(errcode, "%08x", error); + WriteFile (gStdErr, ": Error ", 8, &wrote, NULL); + WriteFile (gStdErr, errcode, 8, &wrote, NULL); + } + else + { + WriteFile (gStdErr, ": ", 2, &wrote, NULL); + WriteFile (gStdErr, buffer, len, &wrote, NULL); + LocalFree(buffer); + } + WriteFile (gStdErr, "\n", 1, &wrote, NULL); +} + +static void DumpFormattedOutput() +{ + CONSOLE_SCREEN_BUFFER_INFO info; + DWORD out; + WORD color; + char *cp; + char spaces[8 + 1] = " "; + char *saved; + int curcol; + int i; + + if(!GetConsoleScreenBufferInfo(gStdOut, &info)) + { + WriteFile(gStdOut, gBuf, lstrlen(gBuf), &out, NULL); + WriteFile(gStdOut, "\n", 1, &out, NULL); + return; + } + + color = info.wAttributes & ~(FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE|FOREGROUND_INTENSITY); + curcol = 0; + saved = NULL; + if(gDumpCmdArgs) + { + SetConsoleTextAttribute(gStdOut, color | COLOR_COMMAND); + WriteConsole(gStdOut, gBuf, lstrlen(gArgsStr)+1, &out, NULL); + SetConsoleTextAttribute(gStdOut, info.wAttributes); + } + for(cp = gBuf + lstrlen(gArgsStr) + 1;; cp++) + { + if(*cp == '\0') + { + if(saved != NULL) + { + cp = saved; + saved = NULL; + } + else + break; + } + if(*cp == '\r') + continue; + if(*cp == '\t') + { + saved = cp + 1; + cp = spaces + 8 - (8 - ((curcol - INDENT - 1) % 8)); + } + if(curcol == 0) + { + for(i = INDENT; --i >= 0;) + WriteConsole(gStdOut, " " ,1, &out, NULL); + curcol = INDENT; + } + WriteConsole(gStdOut, cp, 1, &out, NULL); + if(++curcol == (gColumns - 1)) + { + WriteConsole(gStdOut, "\n", 1, &out, NULL); + curcol = 0; + } + else if(*cp == '\n') + curcol = 0; + } + HeapFree(gHeap, 0, gBuf); +} /* DumpFormattedOutput */ + +static void Wait(void) +{ + DWORD exitcode; + WaitForSingleObject(gCCP.hProcess, INFINITE); + GetExitCodeProcess(gCCP.hProcess, &exitcode); + gExitStatus = (int)exitcode; +} /* Wait */ + +static DWORD WINAPI SlurpThread(LPVOID foo) +{ + HANDLE fd = (HANDLE)foo; + char *newbuf; + DWORD ntoread; + DWORD nread; + + for(;;) + { + if(gNBufUsed == (gNBufAllocated - 1)) + { + if((newbuf = + (char *) HeapReAlloc(gHeap, 0, gBuf, + gNBufAllocated + TEXT_BLOCK_SIZE)) == NULL) + { + return 1; + } + gNBufAllocated += TEXT_BLOCK_SIZE; + gBuf = newbuf; + } + ntoread = (gNBufAllocated - gNBufUsed - 1); + if(!ReadFile(fd, gBuf + gNBufUsed, ntoread, &nread, NULL)) + { + return 2; + } + else if(nread > 0) + { + gNBufUsed += nread; + gBuf[gNBufUsed] = '\0'; + } + } + return 0; +} + +static void REGPARM(2) WriteAction(HANDLE hStdOut, const char *suffix) +{ + DWORD out; + + WriteFile(hStdOut, gAction, lstrlen(gAction), &out, NULL); + if(gTarget != NULL) + { + WriteFile(hStdOut, " ", 1, &out, NULL); + WriteFile(hStdOut, gTarget, lstrlen(gTarget), &out, NULL); + } + WriteFile(hStdOut, suffix, 3, &out, NULL); +} + +static int REGPARM(2) Slurp(HANDLE fd, HANDLE hStdOut) +{ + HANDLE handles[2]; + DWORD waitstate; + DWORD exitcode; + DWORD out; + const char *trail = "/-\\|", *trailcp; + CONSOLE_SCREEN_BUFFER_INFO info; + CONSOLE_CURSOR_INFO cursorInfo; + WORD color, colors[5]; + int ncells, i; + + trailcp = trail; + if(hStdOut != NULL) + { + WriteAction(hStdOut, "..."); + } + + handles[0] = gCCP.hProcess; + handles[1] = CreateThread(NULL, 0, SlurpThread, (LPVOID)fd, 0, NULL); + + if(handles[1] == 0) + { + perror("ccdv: CreateThread"); + return -1; + } + + if(hStdOut != NULL) + { + GetConsoleScreenBufferInfo(hStdOut, &info); + info.dwCursorPosition.X = info.dwSize.X - 9; + if(GetConsoleCursorInfo(hStdOut, &cursorInfo)) + { + cursorInfo.bVisible = FALSE; + SetConsoleCursorInfo(hStdOut, &cursorInfo); + } + else + { + cursorInfo.bVisible = TRUE; + } + } + + gExitStatus = 0xabadcafe; + while(gExitStatus == 0xabadcafe) + { + waitstate = WaitForMultipleObjects(2, handles, FALSE, 1000); + switch(waitstate) + { + case WAIT_TIMEOUT: + if(hStdOut != NULL) + { + SetConsoleCursorPosition(hStdOut, info.dwCursorPosition); + WriteConsoleA(hStdOut, trailcp, 1, &out, NULL); + if(*++trailcp == '\0') + trailcp = trail; + } + break; + + case WAIT_FAILED: + perror("ccdv: WaitForMultipleObjects"); + CloseHandle(handles[1]); + return -1; + + case WAIT_OBJECT_0: + GetExitCodeProcess(gCCP.hProcess, &exitcode); + CloseHandle(handles[1]); + gExitStatus = (int)exitcode; + break; + + case WAIT_OBJECT_0+1: + GetExitCodeThread(handles[1], &exitcode); + CloseHandle(handles[1]); + if(exitcode == 1) + { + perror("ccdv: HeapReAlloc"); + return -1; + } + else if(exitcode == 2) + { + perror("ccdv: ReadFile"); + return -1; + } + Wait(); + break; + } + } + if(hStdOut != NULL) + { + info.dwCursorPosition.X = 0; + SetConsoleCursorPosition(hStdOut, info.dwCursorPosition); + WriteAction(hStdOut, ": "); + info.dwCursorPosition.X = info.dwSize.X - 10; + if(gExitStatus == 0) + { + SetConsoleCursorPosition(hStdOut, info.dwCursorPosition); + WriteConsoleA(hStdOut, "[OK] ", 9, &out, NULL); + color = ((gNBufUsed - lstrlen(gArgsStr)) < 4) ? COLOR_SUCCESS : COLOR_WARNING; + ncells = 2; + } + else + { + SetConsoleCursorPosition(hStdOut, info.dwCursorPosition); + WriteConsoleA(hStdOut, "[ERROR] ", 9, &out, NULL); + color = COLOR_FAILURE; + ncells = 5; + gDumpCmdArgs = 1; /* print cmd when there are errors */ + } + color |= info.wAttributes & ~(FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE|FOREGROUND_INTENSITY); + for(i = 0; i < ncells; ++i) + { + colors[i] = color; + } + info.dwCursorPosition.X++; + WriteConsoleOutputAttribute(hStdOut, colors, ncells, info.dwCursorPosition, &out); + if(!cursorInfo.bVisible) + { + cursorInfo.bVisible = TRUE; + SetConsoleCursorInfo(hStdOut, &cursorInfo); + } + WriteConsole(hStdOut, "\n", 1, &out, NULL); + } + else + { + gDumpCmdArgs = (gExitStatus != 0); /* print cmd when there are errors */ + } + return (0); +} /* SlurpProgress */ + +static const char *REGPARM(2) Basename(const char *path, int len) +{ + while(len > 0) + { + len--; + if(path[len] == '/' || path[len] == '\\') + { + return path + len + 1; + } + } + return path; +} /* Basename */ + +static const char *REGPARM(2) Extension(const char *path, int len) +{ + while(len > 0) + { + len--; + if(path[len] == '.') + { + return path + len; + } + } + return ""; +} /* Extension */ + +static void Usage(void) +{ + static const char sUsage[] = "\ +Usage: ccdv /path/to/cc CFLAGS...\n\ +\n\ +I wrote this to reduce the deluge Make output to make finding actual problems\n\ +easier. It is intended to be invoked from Makefiles, like this. Instead of:\n\ +\n\ + .c.o:\n\ + $(CC) $(CFLAGS) $(DEFS) $(CPPFLAGS) $< -c\n\ +\n\ +Rewrite your rule so it looks like:\n\ +\n\ + .c.o:\n\ + @ccdv $(CC) $(CFLAGS) $(DEFS) $(CPPFLAGS) $< -c\n\ + .cpp.o:\n\ + @ccdv $(CXX) $(CFLAGS) $(DEFS) $(CPPFLAGS) $< -c\n\ +\n\ +ccdv 1.1.0 is Free under the GNU Public License. Enjoy!\n\ + -- Mike Gleason, NcFTP Software \n\ + -- John F Meinel Jr, \n\ + "; + DWORD out; + WriteFile (gStdErr, sUsage, sizeof(sUsage)-1, &out, NULL); + ExitProcess(96); +} /* Usage */ + +static BOOL REGPARM(3) StepCmdLine(char **cmdline, char **arg, int *arglen) +{ + char *gArgsStr = *cmdline; + + // Skip whitespace + while(*gArgsStr == ' ' || *gArgsStr == '\t' || *gArgsStr == '\n' || *gArgsStr == '\r') + { + gArgsStr++; + } + if(*gArgsStr == 0) + { + *cmdline = gArgsStr; + return FALSE; + } + if(*gArgsStr == '\"') + { // It's a quoted string + *arg = ++gArgsStr; + while(*gArgsStr && *gArgsStr != '\"') + { + gArgsStr++; + } + *arglen = gArgsStr - *arg; + if(*gArgsStr) + { // Ends with a quote + gArgsStr++; + } + *cmdline = gArgsStr; + return TRUE; + } + // It's a whitespace-separated string + *arg = gArgsStr; + while(*gArgsStr && *gArgsStr != ' ' && *gArgsStr != '\t' && *gArgsStr != '\n' && *gArgsStr != '\r') + { + gArgsStr++; + } + *arglen = gArgsStr - *arg; + *cmdline = gArgsStr; + return TRUE; +} + +static void REGPARM(3) SetTarget(char **target, const char *arg, int arglen) +{ + const char *base; + + if (*target) HeapFree(gHeap, 0, *target); + base = Basename(arg, arglen); + arglen = arglen - (base - arg) + 1; + *target = HeapAlloc(gHeap, 0, arglen); + lstrcpyn(*target, base, arglen); +} + +void mainCRTStartup(void) +{ + const char *ext; + char *cmdline, *arg; + int arglen, extlen; + SECURITY_ATTRIBUTES security; + STARTUPINFO siStartInfo; + HANDLE pipeRd, pipeWr, pipeRdDup; + char emerg[256]; + DWORD nread; + int cc = 0; + int yy = 0; + CONSOLE_SCREEN_BUFFER_INFO bufferInfo; + + gExitStatus = 95; + gHeap = GetProcessHeap(); + gArgsStr = cmdline = GetCommandLine(); + gStdOut = GetStdHandle(STD_OUTPUT_HANDLE); + gStdErr = GetStdHandle(STD_ERROR_HANDLE); + + if (!StepCmdLine(&cmdline, &arg, &arglen) || // Skip ccdv.exe + !StepCmdLine(&cmdline, &arg, &arglen)) // Read name of process to run + { + Usage(); + } + + // "Running *argv[1]*" + ext = Basename(arg, arglen); + extlen = arglen - (ext - arg); + gAction = HeapAlloc(gHeap, 0, 64+extlen); + lstrcpy(gAction, "Running "); + lstrcpyn(gAction+8, ext, extlen+1); + + if (extlen == 2 && lstrcmpi(gAction+8, "ar") == CSTR_EQUAL) + { + SetTarget(&gAr, arg, arglen); + } + + while(StepCmdLine(&cmdline, &arg, &arglen)) + { + if(arglen == 2 && arg[0] == '-' && arg[1] == 'o') + { + if(StepCmdLine(&cmdline, &arg, &arglen)) + { + ext = Extension(arg, arglen); + if(ext[0] != '.' || (ext[1] != 'o' && ext[1] != 'O')) + { + lstrcpy(gAction, "Linking"); + SetTarget(&gTarget, arg, arglen); + } + } + continue; + } + else if(arg[0] == '-' || arg[0] == '+' || arg[0] == '/') + { + continue; + } + ext = Extension(arg, arglen); + if(ext[0] == '.' && (ext[1] == 'C' || ext[1] == 'c')) + { + cc++; + SetTarget(&gTarget, arg, arglen); + } + else if(ext[0] == '.' && ext[1] == 'y') + { + yy++; + } + else if(CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, ".nas", 4, ext, -1) == CSTR_EQUAL) + { + lstrcpy(gAction, "Assembling"); + SetTarget(&gTarget, arg, arglen); + } + else if(gArLibraryTarget == NULL && ext[0] == '.' && ext[1] == 'a') + { + SetTarget(&gArLibraryTarget, arg, arglen); + } + } + if((gAr != NULL) && (gArLibraryTarget != NULL)) + { + lstrcpy(gAction, "Creating library"); + if(gTarget != NULL) HeapFree(gHeap, 0, gTarget); + gTarget = gArLibraryTarget; + gArLibraryTarget = NULL; + } + else if(cc > 0) + { + lstrcpy(gAction, yy == 0 ? "Compiling" : "Generating"); + } + + /* Initialize security attributes for the pipe */ + security.nLength = sizeof security; + security.lpSecurityDescriptor = NULL; + security.bInheritHandle = TRUE; + + if(!CreatePipe(&pipeRd, &pipeWr, &security, 0)) + { + perror("ccdv: pipe"); + ExitProcess(97); + } + + if (!DuplicateHandle(GetCurrentProcess(), pipeRd, + GetCurrentProcess(), &pipeRdDup , 0, + FALSE, + DUPLICATE_SAME_ACCESS)) + { + perror("ccdv: DuplicateHandle"); + } + CloseHandle(pipeRd); + + /* Initialize startup info for the child process */ + siStartInfo.cb = sizeof siStartInfo; + siStartInfo.lpReserved = NULL; + siStartInfo.lpDesktop = NULL; + siStartInfo.lpTitle = NULL; + siStartInfo.dwX = 0; + siStartInfo.dwY = 0; + siStartInfo.dwXSize = 0; + siStartInfo.dwYSize = 0; + siStartInfo.dwXCountChars = 0; + siStartInfo.dwYCountChars = 0; + siStartInfo.dwFillAttribute = 0; + siStartInfo.dwFlags = STARTF_USESTDHANDLES; + siStartInfo.wShowWindow = 0; + siStartInfo.cbReserved2 = 0; + siStartInfo.lpReserved2 = 0; + siStartInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE); + siStartInfo.hStdOutput = pipeWr; + siStartInfo.hStdError = pipeWr; + + StepCmdLine(&gArgsStr, &arg, &arglen); // Skip "ccdv" + while(*gArgsStr == ' ' || *gArgsStr == '\t' || *gArgsStr == '\n' || *gArgsStr == '\r') + gArgsStr++; + + extlen = lstrlen(gArgsStr); + gNBufAllocated = extlen + TEXT_BLOCK_SIZE; + gBuf = (char *) HeapAlloc(gHeap, 0, gNBufAllocated); + if(gBuf == NULL) + goto panic; + gNBufUsed = extlen + 1; + lstrcpy(gBuf, gArgsStr); + gBuf[extlen] = '\n'; + gBuf[extlen+1] = 0; + + if(!CreateProcessA(NULL, + gArgsStr, /* command gArgsStr */ + NULL, /* process security attributes */ + NULL, /* primary thread security attributes */ + TRUE, /* handles are inherited */ + 0, /* creation flags */ + NULL, /* use parent's environment */ + NULL, /* use parent's current directory */ + &siStartInfo, /* STARTUPINFO pointer */ + &gCCP)) /* receives PROCESS_INFORMATION */ + { + CloseHandle(pipeRdDup); + CloseHandle(pipeWr); + perror("ccdv: CreateProcess"); + gExitStatus = 98; + goto panic; + } + CloseHandle(gCCP.hThread); + + if(GetConsoleScreenBufferInfo(gStdOut, &bufferInfo)) + { + gColumns = bufferInfo.dwSize.X; + if(Slurp(pipeRdDup, gStdOut) < 0) + goto panic; + } + else + { + if(Slurp(pipeRdDup, NULL) < 0) + goto panic; + } + DumpFormattedOutput(); + ExitProcess(gExitStatus); + + panic: + gDumpCmdArgs = 1; /* print cmd when there are errors */ + DumpFormattedOutput(); + while(ReadFile(pipeRdDup, emerg, sizeof emerg, &nread, NULL) && nread > 0) + WriteFile(gStdErr, emerg, nread, &nread, NULL); + Wait(); + ExitProcess(gExitStatus); +} /* main */ + +/* eof ccdv.c */ diff --git a/configure.ac b/configure.ac new file mode 100644 index 00000000000..456aa1ef002 --- /dev/null +++ b/configure.ac @@ -0,0 +1,176 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. + +AC_PREREQ(2.57) +AC_INIT(zdoom, 2.0.63, smordak@yahoo.com) +AC_CONFIG_AUX_DIR(config) +AC_CANONICAL_TARGET +AM_INIT_AUTOMAKE(dist-bzip2) +AC_CONFIG_SRCDIR([src/r_sky.cpp]) +AC_CONFIG_HEADER(config.h) +AC_PROG_CXX + +# Checks for programs. +AC_PROG_CC +AC_PROG_INSTALL + +# Checks for header files. +AC_HEADER_DIRENT +AC_HEADER_STDC +AC_HEADER_SYS_WAIT +AC_CHECK_HEADERS([arpa/inet.h fcntl.h float.h limits.h malloc.h netdb.h netinet/in.h stddef.h stdlib.h string.h sys/ioctl.h sys/param.h sys/socket.h sys/time.h sys/timeb.h unistd.h]) + +# Checks for typedefs, structures, and compiler characteristics. +AC_HEADER_STDBOOL +AC_C_CONST +AC_C_INLINE +AC_TYPE_PID_T +AC_TYPE_SIZE_T +AC_HEADER_TIME +AC_STRUCT_TM +AC_C_VOLATILE +AC_CHECK_TYPES([ptrdiff_t]) +AC_C_BIGENDIAN + +# Checks for library functions. +AC_FUNC_ALLOCA +AC_REPLACE_FNMATCH +AC_FUNC_FORK +AC_FUNC_MALLOC +AC_FUNC_MEMCMP +AC_FUNC_REALLOC +AC_TYPE_SIGNAL +AC_FUNC_STAT +AC_FUNC_STRTOD +AC_FUNC_VPRINTF +AC_CHECK_FUNCS([atexit dup2 floor getcwd gethostbyname gettimeofday memchr memmove memset mkdir modf pow realpath socket sqrt strchr strdup strerror strrchr strstr strtol strtoul filelength strupr]) + +AC_CHECK_FUNC(stricmp, stricmp=yes, stricmp=no) +if test $stricmp = no; then + AC_CHECK_FUNC(strcasecmp, + AC_DEFINE(stricmp, strcasecmp, [Define stricmp as strcasecmp if you have one but not the other]), + AC_MSG_ERROR([Neither stricmp nor strcasecmp found]) + ) +fi + +AC_CHECK_FUNC(strnicmp, strnicmp=yes, strnicmp=no) +if test $strnicmp = no; then + AC_CHECK_FUNC(strncasecmp, + AC_DEFINE(strnicmp, strncasecmp, [Define strnicmp as strncasecmp if you have one but not the other]), + AC_MSG_ERROR([Neither strnicmp nor strncasecmp found]) + ) +fi + +# Checks for libraries. + +# Check for SDL +dnl Check for SDL +SDL_VERSION=1.2.0 +AM_PATH_SDL($SDL_VERSION, + :, + AC_MSG_ERROR([*** SDL version $SDL_VERSION not found!]) +) +CFLAGS="$CFLAGS $SDL_CFLAGS" +CXXFLAGS="$CXXFLAGS $SDL_CFLAGS" +LIBS="$LIBS $SDL_LIBS" + +# NASM is available from: http://nasm.sourceforge.net/ +# This snippet is taken from SDL's configure.in +dnl Make sure we are running on an x86 platform +case $target in + i?86*) + dnl Check for NASM (for assembly routines) + AC_ARG_ENABLE(nasm, + [ --enable-nasm use nasm routines on x86 [default=yes]], + , enable_nasm=yes) + if test x$enable_nasm = xyes; then + AC_PATH_PROG(NASM, nasm) + if test x$NASM = x -o x$NASM = x'"$NASM"'; then + CFLAGS="$CLAGS -DNOASM" + : # nasm isn't installed + else + CFLAGS="$CFLAGS -DUSEASM" + case $ARCH in + win32) + NASMFLAGS="-f win32" + ;; + openbsd) + NASMFLAGS="-f aoutb" + ;; + *) + # M_TARGET_LINUX really means "target is ELF" + NASMFLAGS="-f elf -DM_TARGET_LINUX" + ;; + esac + AC_SUBST(NASMFLAGS) + fi + else + CFLAGS="$CFLAGS -DNOASM" + fi + ;; + *) + # Nope, then NASM is definitely not available + CFLAGS="$CFLAGS -DNOASM" + ;; +esac + +# Check for FMOD, first in the path, then in ~/fomdapi +AC_MSG_CHECKING([a suitable version of FMOD]) +LIBS="$LIBS -lfmod-3.74" +AC_LINK_IFELSE( +[AC_LANG_PROGRAM([[#include ]], + [[FSOUND_Init (44100, 64, FSOUND_INIT_STREAM_FROM_MAIN_THREAD); + FMUSIC_LoadSongEx ("dummy", 0, 100, 0, (void*)0, 0); + FSOUND_Stream_Open ("dummy", 0, 0, 100);]])], + AC_MSG_RESULT([yes]), + LIBS="$LIBS -L${HOME}/fmodapi/api" + CFLAGS="$CFLAGS -I${HOME}/fmodapi/api/inc" + CXXFLAGS="$CXXFLAGS -I${HOME}/fmodapi/api/inc" + AC_LINK_IFELSE( + [AC_LANG_PROGRAM([[#include ]], + [[FSOUND_Init (44100, 64, FSOUND_INIT_STREAM_FROM_MAIN_THREAD); + FMUSIC_LoadSongEx ("dummy", 0, 100, 0, (void*)0, 0); + FSOUND_Stream_Open ("dummy", 0, 0, 100);]])], + AC_MSG_RESULT([in ~/fmodapi]), + AC_MSG_RESULT([no]) + AC_MSG_FAILURE([Could not find FMOD 3.74 or a compatible version.]))) + +# Check for zlib +AC_CHECK_LIB(z, deflate,, AC_MSG_FAILURE([You need zlib to build ZDoom. See http://www.gzip.org/zlib/])) +# Check for libFLAC and libFLAC++ +AC_CHECK_LIB(FLAC, FLAC__stream_decoder_new) + +AC_LANG_CPLUSPLUS +AC_MSG_CHECKING([libFLAC++]) +ac_save_LIBS=$LIBS +LIBS="-lFLAC++ $LIBS" +AC_LINK_IFELSE( +[AC_LANG_PROGRAM([[#include + +class TestStream : public FLAC::Decoder::Stream +{ +public: + TestStream () {} +protected: + ::FLAC__StreamDecoderReadStatus read_callback(FLAC__byte buffer[], unsigned *bytes) + { + return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE; + } + ::FLAC__StreamDecoderWriteStatus write_callback(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[]) + { + return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; + } + void metadata_callback(const ::FLAC__StreamMetadata *metadata) + { + } + void error_callback(::FLAC__StreamDecoderErrorStatus status) + { + } +};]], + [[TestStream test_it;]])], + AC_MSG_RESULT([yes]), + AC_MSG_RESULT([no]) + LIBS=$ac_save_LIBS) + +AC_CONFIG_FILES([Makefile src/Makefile]) +AC_OUTPUT diff --git a/default.cbd b/default.cbd new file mode 100644 index 00000000000..ac368ef41c8 --- /dev/null +++ b/default.cbd @@ -0,0 +1,224 @@ +do ifopt help + echo Available options are: + echo . debug - Build debug instead of release + echo . verbose - Show system commands instead of decorated messages + echo . clean - Clean temp files (use with debug to clean debug files) + echo . zdoom.wad - (Re)build just zdoom.wad, even if it already exists + echo . + echo To use with MinGW, compile cbuild.c into an executable using: + echo gcc -O2 -W -Wall -Werror -o cbuild.exe cbuild.c + echo . + echo Or if you have a sh-compatible shell, you can run the cbuild.c file + echo directly or have it automatically compile itself with GCC by passing + echo --make-compiled + echo . + exit 0 +done + +# Here's the main script. All commands are case in-sensitive. + +# 'Ifopt' will check if the following word was passed on the command line, and execute the +# rest of the line if so. The reverse, 'ifnopt', also exists. + +ifopt verbose verbose 1 +ifopt debug CONFIG = Debug + +# VAR?=foo will only set the var if it's unset. Note that if you want spaces, put '' or "" +# quotes around the value. VAR+=foo will append foo to the very end of the existing var. +# And, VAR-=foo will remove all occurences of foo from the var. +CONFIG ?= Release + +OPTLEVEL ?= 2 +ARCH_TYPE ?= pentium +TUNE_TYPE ?= athlon-xp + +RELEASETARGET ?= zdoomgcc +DEBUGTARGET ?= zdoomgccd + +DEBUGOBJDIR = debugobj +RELEASEOBJDIR = releaseobj + + +CPPFLAGS = "-DHAVE_FILELENGTH -D__forceinline=inline -Izlib -IFLAC -Isrc -Isrc/sdl -Isrc/g_doom -Isrc/g_heretic -Isrc/g_hexen -Isrc/g_raven -Isrc/g_strife -Isrc/g_shared -Isrc/oplsynth -Isrc/sound" +LDFLAGS = "-lFLAC++ -lFLAC -lz -lfmod `sdl-config --libs`" +CFLAGS = "`sdl-config --cflags` " + +do ifopt debug + OBJDIR = "${DEBUGOBJDIR}" + CFLAGS += "-Wall -Wno-unused -g3" + CPPFLAGS += " -D_DEBUG" + CXXFLAGS = "${CFLAGS}" + TARGET = "${DEBUGTARGET}" +else + OBJDIR = "${RELEASEOBJDIR}" + CFLAGS += "-march=${ARCH_TYPE} -mtune=${TUNE_TYPE} -Wall -Wno-unused -O${OPTLEVEL} -fomit-frame-pointer" + CPPFLAGS += " -DNDEBUG" + CXXFLAGS = "${CFLAGS}" + LDFLAGS += " -Wl,-Map=zdoomgcc.map" + TARGET = "${RELEASETARGET}" +done + +ifnplat win32 CPPFLAGS += " -Dstricmp=strcasecmp -Dstrnicmp=strncasecmp" + +# This is where the object and dependancy files go when compiled +OBJ_DIR = "${OBJDIR}" +DEP_DIR = "${OBJDIR}" + +do ifnopt clean + EVILCLEAN = 0 + ifnexist "${OBJ_DIR}" mkdir "${OBJ_DIR}" + + ifopt zdoom.wad goto makewad + + do if "${NOASM}"="" +# 'Loadlist' stores a list of words, and 'execlist' executes a command on each one, +# replacing <@> with the word. Unfortuantely this doesn't do dependancy checking. + loadlist 'a' 'blocks' 'misc' 'tmap' 'tmap2' 'tmap3' + do ifplat win32 execlist nasmw -o "${OBJ_DIR}/<@>${OBJ_EXT}" -f win32 "src/<@>.nas" + else ifplat unix execlist nasm -o "${OBJ_DIR}/<@>${OBJ_EXT}" -f elf -DM_TARGET_LINUX "src/<@>.nas" + else + echo . + echo Unsupported platform! + echo . + exit 1 + done + CPPFLAGS = "-DUSEASM ${CPPFLAGS}" + else + CPPFLAGS = "-DNOASM ${CPPFLAGS}" + done + +# Set the compile and link commands. 'Compile' will compile the list of sourcefiles and +# store their names until another Compile is encountered (if you wish to add to a previous +# list, use 'Compileadd'). +# +# C sources are compiled with: +# ${CC} ${CPPFLAGS} ${CFLAGS} ${DEP_OPT}${DEP_DIR}/file-sans-ext${DEP_EXT} ${OUT_OPT}${OBJ_DIR}/file-sans-ext${OBJ_EXT} ${SRC_OPT}detected-source-path/file-with-ext +# +# and for C++ sources: +# ${CXX} ${CPPFLAGS} ${CXXFLAGS} ${DEP_OPT}${DEP_DIR}/file-sans-ext${DEP_EXT} ${OUT_OPT}${OBJ_DIR}/file-sans-ext${OBJ_EXT} ${SRC_OPT}detected-source-path/file-with-ext +# +# A source file will not be compiled if the object file exists and is newer than the source. +# Or if the associated dependancy file exists, all of the object's dependancies are older +# than the object. +# +# If DEP_OPT is unset, the whole DEP_* section will be removed from the command line. Files +# with unknown extensions are silently ignored (but will still be passed to Linkexec with +# their name "object-ified"). +# +# 'Linkexec' executes: +# ${LD} ${OUT_OPT}file${EXE_EXT} ${LDFLAGS} +# +# It will not link if the target executable exists and is newer than all of the objects it's +# linking with. + + COMPILE = Compile + LINK = Linkexec + +# This is where it can find the sources. + src_paths src src/g_doom src/g_heretic src/g_hexen src/g_raven src/g_strife $ + src/g_shared src/oplsynth src/sound src/sdl + +else + +# Override the compile and link commands with rmobj and rmexec. A quick way to delete +# the objects and executables while dealing with only one list. No, rmobj will not +# delete the specified source file, but rather the object and dependancy files that would +# result from compiling the specified source. + EVILCLEAN = 1 + COMPILE = -rmobj + LINK = -rmexec + +done + +${COMPILE} autostart.cpp a.nas blocks.nas misc.nas tmap.nas tmap2.nas tmap3.nas $ + am_map.cpp b_bot.cpp b_func.cpp b_game.cpp b_move.cpp b_think.cpp bbannouncer.cpp $ + c_bind.cpp c_cmds.cpp c_console.cpp c_cvars.cpp c_dispatch.cpp c_expr.cpp $ + cmdlib.cpp colormatcher.cpp configfile.cpp ct_chat.cpp d_dehacked.cpp d_main.cpp $ + d_net.cpp d_netinfo.cpp d_protocol.cpp decallib.cpp decorations.cpp dobject.cpp $ + doomdef.cpp doomstat.cpp dsectoreffect.cpp dthinker.cpp empty.cpp f_finale.cpp $ + f_wipe.cpp farchive.cpp files.cpp g_game.cpp g_level.cpp gameconfigfile.cpp $ + gi.cpp hu_scores.cpp info.cpp infodefaults.cpp lumpconfigfile.cpp m_alloc.cpp $ + m_argv.cpp m_bbox.cpp m_cheat.cpp m_fixed.cpp m_menu.cpp m_misc.cpp m_options.cpp $ + m_png.cpp m_random.cpp mus2midi.cpp nodebuild.cpp nodebuild_events.cpp $ + nodebuild_extract.cpp nodebuild_gl.cpp nodebuild_utility.cpp p_acs.cpp $ + p_buildmap.cpp p_ceiling.cpp p_conversation.cpp p_doors.cpp p_effect.cpp $ + p_enemy.cpp p_floor.cpp p_interaction.cpp p_lights.cpp p_lnspec.cpp p_map.cpp $ + p_maputl.cpp p_mobj.cpp p_pillar.cpp p_plats.cpp p_pspr.cpp p_saveg.cpp $ + p_sectors.cpp p_setup.cpp p_sight.cpp p_spec.cpp p_switch.cpp p_teleport.cpp $ + p_terrain.cpp p_things.cpp p_tick.cpp p_trace.cpp p_user.cpp p_writemap.cpp $ + p_xlat.cpp po_man.cpp r_bsp.cpp r_data.cpp r_draw.cpp r_drawt.cpp r_main.cpp $ + r_plane.cpp r_segs.cpp r_sky.cpp r_things.cpp r_polymost.cpp s_advsound.cpp $ + s_environment.cpp s_playlist.cpp s_sndseq.cpp s_sound.cpp sc_man.cpp skins.cpp $ + st_stuff.cpp stats.cpp stringtable.cpp tables.cpp tempfiles.cpp thingdef.cpp thingdef_codeptr.cpp $ + v_collection.cpp v_draw.cpp v_font.cpp v_palette.cpp v_pfx.cpp v_text.cpp $ + v_video.cpp vectors.cpp name.cpp zstring.cpp zstringpool.cpp zstrformat.cpp $ + w_wad.cpp wi_stuff.cpp a_arachnotron.cpp a_archvile.cpp a_bossbrain.cpp $ + a_bruiser.cpp a_cacodemon.cpp a_cyberdemon.cpp a_demon.cpp $ + a_doomarmor.cpp a_doomartifacts.cpp a_doomdecorations.cpp a_doomhealth.cpp $ + a_doomimp.cpp a_doomkeys.cpp a_doommisc.cpp a_doomplayer.cpp a_doomweaps.cpp $ + a_fatso.cpp a_keen.cpp a_lostsoul.cpp a_painelemental.cpp a_possessed.cpp $ + a_revenant.cpp a_scriptedmarine.cpp a_spidermaster.cpp doom_sbar.cpp a_beast.cpp $ + a_chicken.cpp a_clink.cpp a_dsparil.cpp a_hereticambience.cpp a_hereticarmor.cpp $ + a_hereticartifacts.cpp a_hereticdecorations.cpp a_hereticimp.cpp a_heretickeys.cpp $ + a_hereticmisc.cpp a_hereticplayer.cpp a_hereticweaps.cpp a_ironlich.cpp $ + a_knight.cpp a_mummy.cpp a_snake.cpp a_wizard.cpp heretic_sbar.cpp a_bats.cpp $ + a_bishop.cpp a_blastradius.cpp a_boostarmor.cpp a_centaur.cpp a_clericboss.cpp $ + a_clericflame.cpp a_clericholy.cpp a_clericmace.cpp a_clericplayer.cpp $ + a_clericstaff.cpp a_demons.cpp a_dragon.cpp a_ettin.cpp a_fighteraxe.cpp $ + a_fighterboss.cpp a_fighterhammer.cpp a_fighterplayer.cpp a_fighterquietus.cpp $ + a_firedemon.cpp a_flame.cpp a_flechette.cpp a_fog.cpp a_healingradius.cpp $ + a_heresiarch.cpp a_hexenarmor.cpp a_hexendecorations.cpp a_hexenkeys.cpp $ + a_hexenspecialdecs.cpp a_iceguy.cpp a_korax.cpp a_mageboss.cpp a_magecone.cpp $ + a_magelightning.cpp a_mageplayer.cpp a_magestaff.cpp a_magewand.cpp a_mana.cpp $ + a_pig.cpp a_puzzleitems.cpp a_scriptprojectiles.cpp a_serpent.cpp a_speedboots.cpp $ + a_spike.cpp a_summon.cpp a_teleportother.cpp a_weaponpiece.cpp a_wraith.cpp $ + hexen_sbar.cpp a_artiegg.cpp a_artitele.cpp a_minotaur.cpp a_ravenambient.cpp $ + a_ravenartifacts.cpp a_ravenhealth.cpp a_acolyte.cpp a_alienspectres.cpp $ + a_beggars.cpp a_coin.cpp a_crusader.cpp a_entityboss.cpp a_inquisitor.cpp $ + a_loremaster.cpp a_macil.cpp a_merchants.cpp a_oracle.cpp a_peasant.cpp $ + a_programmer.cpp a_questitems.cpp a_ratbuddy.cpp a_reaver.cpp a_rebels.cpp $ + a_sentinel.cpp a_spectral.cpp a_stalker.cpp a_strifeammo.cpp a_strifearmor.cpp $ + a_strifebishop.cpp a_strifeitems.cpp a_strifekeys.cpp a_strifeplayer.cpp $ + a_strifestuff.cpp a_strifeweapons.cpp a_templar.cpp a_thingstoblowup.cpp $ + a_zombie.cpp strife_sbar.cpp a_action.cpp a_artifacts.cpp a_bridge.cpp $ + a_camera.cpp a_debris.cpp a_decals.cpp a_flashfader.cpp a_fountain.cpp $ + a_hatetarget.cpp a_keys.cpp a_lightning.cpp a_movingcamera.cpp a_pickups.cpp $ + a_quake.cpp a_secrettrigger.cpp a_sectoraction.cpp a_sharedmisc.cpp a_skies.cpp $ + a_soundenvironment.cpp a_spark.cpp a_splashes.cpp a_waterzone.cpp a_weapons.cpp $ + hudmessages.cpp shared_sbar.cpp fmopl.cpp mlkernel.cpp mlopl.cpp mlopl_io.cpp $ + opl_mus_player.cpp fmodsound.cpp i_music.cpp i_sound.cpp music_cd.cpp $ + music_flac.cpp music_midi_midiout.cpp music_midi_stream.cpp music_midi_timidity.cpp $ + music_mod.cpp music_mus_midiout.cpp music_mus_opl.cpp music_stream.cpp $ + sample_flac.cpp crashcatcher.c i_input.cpp i_net.cpp i_cd.cpp i_main.cpp $ + i_system.cpp hardware.cpp i_movie.cpp sdlvideo.cpp autozend.cpp + +${LINK} "${TARGET}" + +# If we're not cleaning and zdoom.wad exists, exit now. +if "${EVILCLEAN}"="0" ifexist zdoom.wad exit 0 +#:makewad + +LDFLAGS = '' +CFLAGS = '-Os -Wall -fomit-frame-pointer' + +src_paths tools/makewad +${COMPILE} makewad.c +${LINK} tools/makewad/makewad + +src_paths tools/xlatcc +${COMPILE} xlat-parse.tab.c gen.c +${LINK} tools/xlatcc/xlatcc + +src_paths tools/dehsupp +${COMPILE} parse.tab.c +${LINK} tools/dehsupp/dehsupp + +do if "${EVILCLEAN}"="1" + -rm "${OBJ_DIR}" + -rm "${DEP_DIR}" + -rm zdoomgcc.map + -rm zdoom.wad +else + call cd wadsrc && ../tools/makewad/makewad zdoom.lst + copy wadsrc/zdoom.wad ./ +done diff --git a/docs/BUILDLIC.TXT b/docs/BUILDLIC.TXT new file mode 100644 index 00000000000..aa7a0b2b8ff --- /dev/null +++ b/docs/BUILDLIC.TXT @@ -0,0 +1,71 @@ +BUILD SOURCE CODE LICENSE TERMS: 06/20/2000 + +[1] I give you permission to make modifications to my Build source and + distribute it, BUT: + +[2] Any derivative works based on my Build source may be distributed ONLY + through the INTERNET. + +[3] Distribution of any derivative works MUST be done completely FREE of + charge - no commercial exploitation whatsoever. + +[4] Anything you distribute which uses a part of my Build Engine source + code MUST include: + + [A] The following message somewhere in the archive: + + // "Build Engine & Tools" Copyright (c) 1993-1997 Ken Silverman + // Ken Silverman's official web site: "http://www.advsys.net/ken" + // See the included license file "BUILDLIC.TXT" for license info. + + [B] This text file "BUILDLIC.TXT" along with it. + + [C] Any source files that you modify must include this message as well: + + // This file has been modified from Ken Silverman's original release + +[5] The use of the Build Engine for commercial purposes will require an + appropriate license arrangement with me. Contact information is + on my web site. + +[6] I take no responsibility for damage to your system. + +[7] Technical support: Before contacting me with questions, please read + and do ALL of the following! + + [A] Look though ALL of my text files. There are 7 of them (including this + one). I like to think that I wrote them for a reason. You will find + many of your answers in the history section of BUILD.TXT and + BUILD2.TXT (they're located inside SRC.ZIP). + + [B] If that doesn't satisfy you, then try going to: + + "http://www.advsys.net/ken/buildsrc" + + where I will maintain a Build Source Code FAQ (or perhaps I might + just provide a link to a good FAQ). + + [C] I am willing to respond to questions, but ONLY if they come at a rate + that I can handle. + + PLEASE TRY TO AVOID ASKING DUPLICATE QUESTIONS! + + As my line of defense, I will post my current policy about + answering Build source questions (right below the E-mail address + on my web site.) You can check there to see if I'm getting + overloaded with questions or not. + + If I'm too busy, it might say something like this: + + I'm too busy to answer Build source questions right now. + Sorry, but don't expect a reply from me any time soon. + + If I'm open for Build source questions, please state your question + clearly and don't include any unsolicited attachments unless + they're really small (like less than 50k). Assume that I have + a 28.8k modem. Also, don't leave out important details just + to make your question appear shorter - making me guess what + you're asking doesn't save me time! + +---------------------------------------------------------------------------- +-Ken S. (official web site: http://www.advsys.net/ken) diff --git a/docs/README.Carmack b/docs/README.Carmack new file mode 100644 index 00000000000..cabddef7d48 --- /dev/null +++ b/docs/README.Carmack @@ -0,0 +1,283 @@ + +README - DOOM assembly code + +Okay, I add the DOS assembly module for the historically +inclined here (may rec.games.programmer suffer). If anyone +feels the urge to port these to GNU GCC; either inline or +as separate modules including Makefile support, be my guest. + +Module tmap.S includes the inner loops for texture mapping, +the interesting one being the floor/ceiling span rendering. + +There was another module in the source dump, fpfunc.S, that +had both texture mapping and fixed point functions. It +contained implementations both for i386 and M68k. For +brevity, I include only the i386 fixed point stuff below. + +//==================================================== +// tmap.S as of January 10th, 1997 + +//================ +// +// R_DrawColumn +// +//================ + + .data +loopcount .long 0 +pixelcount .long 0 + + .text + + .align 16 +.globl _R_DrawColumn +_R_DrawColumn: + + pushad + + movl ebp,[_dc_yl] + movl ebx,ebp + movl edi,[_ylookup+ebx*4] + movl ebx,[_dc_x] + addl edi,[_columnofs + ebx*4] + + movl eax,[_dc_yh] + incl eax + subl eax,ebp // pixel count + movl [pixelcount],eax // save for final pixel + js done // nothing to scale + shrl eax,1 // double pixel count + movl [loopcount],eax + + movl ecx,[_dc_iscale] + + movl eax,[_centery] + subl eax,ebp + imull ecx + movl ebp,[_dc_texturemid] + subl ebp,eax + shll ebp,9 // 7 significant bits, 25 frac + + movl esi,[_dc_source] + + + movl ebx,[_dc_iscale] + shll ebx,9 + movl eax,OFFSET patch1+2 // convice tasm to modify code... + movl [eax],ebx + movl eax,OFFSET patch2+2 // convice tasm to modify code... + movl [eax],ebx + +// eax aligned colormap +// ebx aligned colormap +// ecx,edx scratch +// esi virtual source +// edi moving destination pointer +// ebp frac + + movl ecx,ebp // begin calculating first pixel + addl ebp,ebx // advance frac pointer + shrl ecx,25 // finish calculation for first pixel + movl edx,ebp // begin calculating second pixel + addl ebp,ebx // advance frac pointer + shrl edx,25 // finish calculation for second pixel + movl eax,[_dc_colormap] + movl ebx,eax + movb al,[esi+ecx] // get first pixel + movb bl,[esi+edx] // get second pixel + movb al,[eax] // color translate first pixel + movb bl,[ebx] // color translate second pixel + + testl [pixelcount],0fffffffeh + jnz doubleloop // at least two pixels to map + jmp checklast + + .align 16 +doubleloop: + movl ecx,ebp // begin calculating third pixel +patch1: + addl ebp,12345678h // advance frac pointer + movb [edi],al // write first pixel + shrl ecx,25 // finish calculation for third pixel + movl edx,ebp // begin calculating fourth pixel +patch2: + addl ebp,12345678h // advance frac pointer + movl [edi+SCREENWIDTH],bl // write second pixel + shrl edx,25 // finish calculation for fourth pixel + movb al,[esi+ecx] // get third pixel + addl edi,SCREENWIDTH*2 // advance to third pixel destination + movb bl,[esi+edx] // get fourth pixel + decl [loopcount] // done with loop? + movb al,[eax] // color translate third pixel + movb bl,[ebx] // color translate fourth pixel + jnz doubleloop + +// check for final pixel +checklast: + testl [pixelcount],1 + jz done + movb [edi],al // write final pixel + +done: + popad + ret + + + +//================ +// +// R_DrawSpan +// +// Horizontal texture mapping +// +//================ + + + .align 16 +.globl _R_DrawSpan +_R_DrawSpan: + pushad + +// +// find loop count +// + movl eax,[_ds_x2] + incl eax + subl eax,[_ds_x1] // pixel count + movl [pixelcount],eax // save for final pixel + js hdone // nothing to scale + shrl eax,1 // double pixel count + movl [loopcount],eax + +// +// build composite position +// + movl ebp,[_ds_xfrac] + shll ebp,10 + andl ebp,0ffff0000h + movl eax,[_ds_yfrac] + shrl eax,6 + andl eax,0ffffh + orl ebp,eax + + movl esi,[_ds_source] + +// +// calculate screen dest +// + movl edi,[_ds_y] + movl edi,[_ylookup+edi*4] + movl eax,[_ds_x1] + addl edi,[_columnofs+eax*4] + +// +// build composite step +// + movl ebx,[_ds_xstep] + shll ebx,10 + andl ebx,0ffff0000h + movl eax,[_ds_ystep] + shrl eax,6 + andl eax,0ffffh + orl ebx,eax + + movl eax,OFFSET hpatch1+2 // convice tasm to modify code... + movl [eax],ebx + movl eax,OFFSET hpatch2+2 // convice tasm to modify code... + movl [eax],ebx + +// eax aligned colormap +// ebx aligned colormap +// ecx,edx scratch +// esi virtual source +// edi moving destination pointer +// ebp frac + + shldl ecx,ebp,22 // begin calculating third pixel (y units) + shldl ecx,ebp,6 // begin calculating third pixel (x units) + addl ebp,ebx // advance frac pointer + andl ecx,4095 // finish calculation for third pixel + shldl edx,ebp,22 // begin calculating fourth pixel (y units) + shldl edx,ebp,6 // begin calculating fourth pixel (x units) + addl ebp,ebx // advance frac pointer + andl edx,4095 // finish calculation for fourth pixel + movl eax,[_ds_colormap] + movl ebx,eax + movb al,[esi+ecx] // get first pixel + movb bl,[esi+edx] // get second pixel + movb al,[eax] // color translate first pixel + movb bl,[ebx] // color translate second pixel + + testl [pixelcount],0fffffffeh + jnz hdoubleloop // at least two pixels to map + jmp hchecklast + + + .align 16 +hdoubleloop: + shldl ecx,ebp,22 // begin calculating third pixel (y units) + shldl ecx,ebp,6 // begin calculating third pixel (x units) +hpatch1: + addl ebp,12345678h // advance frac pointer + movb [edi],al // write first pixel + andl ecx,4095 // finish calculation for third pixel + shldl edx,ebp,22 // begin calculating fourth pixel (y units) + shldl edx,ebp,6 // begin calculating fourth pixel (x units) +hpatch2: + addl ebp,12345678h // advance frac pointer + movb [edi+1],bl // write second pixel + andl edx,4095 // finish calculation for fourth pixel + movb al,[esi+ecx] // get third pixel + addl edi,2 // advance to third pixel destination + movb bl,[esi+edx] // get fourth pixel + decl [loopcount] // done with loop? + movb al,[eax] // color translate third pixel + movb bl,[ebx] // color translate fourth pixel + jnz hdoubleloop + +// check for final pixel +hchecklast: + testl [pixelcount],1 + jz hdone + movb [edi],al // write final pixel + +hdone: + popad + ret + + + + +//==================================================== +// fpfunc.S as of January 10th, 1997 (parts) + +#ifdef i386 + +.text + .align 4 +.globl _FixedMul +_FixedMul: + pushl %ebp + movl %esp,%ebp + movl 8(%ebp),%eax + imull 12(%ebp) + shrdl $16,%edx,%eax + popl %ebp + ret + + + .align 4 +.globl _FixedDiv2 +_FixedDiv2: + pushl %ebp + movl %esp,%ebp + movl 8(%ebp),%eax + cdq + shldl $16,%eax,%edx + sall $16,%eax + idivl 12(%ebp) + popl %ebp + ret + +#endif + diff --git a/docs/README.asm b/docs/README.asm new file mode 100644 index 00000000000..cabddef7d48 --- /dev/null +++ b/docs/README.asm @@ -0,0 +1,283 @@ + +README - DOOM assembly code + +Okay, I add the DOS assembly module for the historically +inclined here (may rec.games.programmer suffer). If anyone +feels the urge to port these to GNU GCC; either inline or +as separate modules including Makefile support, be my guest. + +Module tmap.S includes the inner loops for texture mapping, +the interesting one being the floor/ceiling span rendering. + +There was another module in the source dump, fpfunc.S, that +had both texture mapping and fixed point functions. It +contained implementations both for i386 and M68k. For +brevity, I include only the i386 fixed point stuff below. + +//==================================================== +// tmap.S as of January 10th, 1997 + +//================ +// +// R_DrawColumn +// +//================ + + .data +loopcount .long 0 +pixelcount .long 0 + + .text + + .align 16 +.globl _R_DrawColumn +_R_DrawColumn: + + pushad + + movl ebp,[_dc_yl] + movl ebx,ebp + movl edi,[_ylookup+ebx*4] + movl ebx,[_dc_x] + addl edi,[_columnofs + ebx*4] + + movl eax,[_dc_yh] + incl eax + subl eax,ebp // pixel count + movl [pixelcount],eax // save for final pixel + js done // nothing to scale + shrl eax,1 // double pixel count + movl [loopcount],eax + + movl ecx,[_dc_iscale] + + movl eax,[_centery] + subl eax,ebp + imull ecx + movl ebp,[_dc_texturemid] + subl ebp,eax + shll ebp,9 // 7 significant bits, 25 frac + + movl esi,[_dc_source] + + + movl ebx,[_dc_iscale] + shll ebx,9 + movl eax,OFFSET patch1+2 // convice tasm to modify code... + movl [eax],ebx + movl eax,OFFSET patch2+2 // convice tasm to modify code... + movl [eax],ebx + +// eax aligned colormap +// ebx aligned colormap +// ecx,edx scratch +// esi virtual source +// edi moving destination pointer +// ebp frac + + movl ecx,ebp // begin calculating first pixel + addl ebp,ebx // advance frac pointer + shrl ecx,25 // finish calculation for first pixel + movl edx,ebp // begin calculating second pixel + addl ebp,ebx // advance frac pointer + shrl edx,25 // finish calculation for second pixel + movl eax,[_dc_colormap] + movl ebx,eax + movb al,[esi+ecx] // get first pixel + movb bl,[esi+edx] // get second pixel + movb al,[eax] // color translate first pixel + movb bl,[ebx] // color translate second pixel + + testl [pixelcount],0fffffffeh + jnz doubleloop // at least two pixels to map + jmp checklast + + .align 16 +doubleloop: + movl ecx,ebp // begin calculating third pixel +patch1: + addl ebp,12345678h // advance frac pointer + movb [edi],al // write first pixel + shrl ecx,25 // finish calculation for third pixel + movl edx,ebp // begin calculating fourth pixel +patch2: + addl ebp,12345678h // advance frac pointer + movl [edi+SCREENWIDTH],bl // write second pixel + shrl edx,25 // finish calculation for fourth pixel + movb al,[esi+ecx] // get third pixel + addl edi,SCREENWIDTH*2 // advance to third pixel destination + movb bl,[esi+edx] // get fourth pixel + decl [loopcount] // done with loop? + movb al,[eax] // color translate third pixel + movb bl,[ebx] // color translate fourth pixel + jnz doubleloop + +// check for final pixel +checklast: + testl [pixelcount],1 + jz done + movb [edi],al // write final pixel + +done: + popad + ret + + + +//================ +// +// R_DrawSpan +// +// Horizontal texture mapping +// +//================ + + + .align 16 +.globl _R_DrawSpan +_R_DrawSpan: + pushad + +// +// find loop count +// + movl eax,[_ds_x2] + incl eax + subl eax,[_ds_x1] // pixel count + movl [pixelcount],eax // save for final pixel + js hdone // nothing to scale + shrl eax,1 // double pixel count + movl [loopcount],eax + +// +// build composite position +// + movl ebp,[_ds_xfrac] + shll ebp,10 + andl ebp,0ffff0000h + movl eax,[_ds_yfrac] + shrl eax,6 + andl eax,0ffffh + orl ebp,eax + + movl esi,[_ds_source] + +// +// calculate screen dest +// + movl edi,[_ds_y] + movl edi,[_ylookup+edi*4] + movl eax,[_ds_x1] + addl edi,[_columnofs+eax*4] + +// +// build composite step +// + movl ebx,[_ds_xstep] + shll ebx,10 + andl ebx,0ffff0000h + movl eax,[_ds_ystep] + shrl eax,6 + andl eax,0ffffh + orl ebx,eax + + movl eax,OFFSET hpatch1+2 // convice tasm to modify code... + movl [eax],ebx + movl eax,OFFSET hpatch2+2 // convice tasm to modify code... + movl [eax],ebx + +// eax aligned colormap +// ebx aligned colormap +// ecx,edx scratch +// esi virtual source +// edi moving destination pointer +// ebp frac + + shldl ecx,ebp,22 // begin calculating third pixel (y units) + shldl ecx,ebp,6 // begin calculating third pixel (x units) + addl ebp,ebx // advance frac pointer + andl ecx,4095 // finish calculation for third pixel + shldl edx,ebp,22 // begin calculating fourth pixel (y units) + shldl edx,ebp,6 // begin calculating fourth pixel (x units) + addl ebp,ebx // advance frac pointer + andl edx,4095 // finish calculation for fourth pixel + movl eax,[_ds_colormap] + movl ebx,eax + movb al,[esi+ecx] // get first pixel + movb bl,[esi+edx] // get second pixel + movb al,[eax] // color translate first pixel + movb bl,[ebx] // color translate second pixel + + testl [pixelcount],0fffffffeh + jnz hdoubleloop // at least two pixels to map + jmp hchecklast + + + .align 16 +hdoubleloop: + shldl ecx,ebp,22 // begin calculating third pixel (y units) + shldl ecx,ebp,6 // begin calculating third pixel (x units) +hpatch1: + addl ebp,12345678h // advance frac pointer + movb [edi],al // write first pixel + andl ecx,4095 // finish calculation for third pixel + shldl edx,ebp,22 // begin calculating fourth pixel (y units) + shldl edx,ebp,6 // begin calculating fourth pixel (x units) +hpatch2: + addl ebp,12345678h // advance frac pointer + movb [edi+1],bl // write second pixel + andl edx,4095 // finish calculation for fourth pixel + movb al,[esi+ecx] // get third pixel + addl edi,2 // advance to third pixel destination + movb bl,[esi+edx] // get fourth pixel + decl [loopcount] // done with loop? + movb al,[eax] // color translate third pixel + movb bl,[ebx] // color translate fourth pixel + jnz hdoubleloop + +// check for final pixel +hchecklast: + testl [pixelcount],1 + jz hdone + movb [edi],al // write final pixel + +hdone: + popad + ret + + + + +//==================================================== +// fpfunc.S as of January 10th, 1997 (parts) + +#ifdef i386 + +.text + .align 4 +.globl _FixedMul +_FixedMul: + pushl %ebp + movl %esp,%ebp + movl 8(%ebp),%eax + imull 12(%ebp) + shrdl $16,%edx,%eax + popl %ebp + ret + + + .align 4 +.globl _FixedDiv2 +_FixedDiv2: + pushl %ebp + movl %esp,%ebp + movl 8(%ebp),%eax + cdq + shldl $16,%eax,%edx + sall $16,%eax + idivl 12(%ebp) + popl %ebp + ret + +#endif + diff --git a/docs/README.gl b/docs/README.gl new file mode 100644 index 00000000000..82949461ad7 --- /dev/null +++ b/docs/README.gl @@ -0,0 +1,149 @@ + +README: glDOOM + +I never got around to do anything with respect to +a Linux glDOOM port except for assembling a Linux3Dfx +HOWTO (which, at that time, was a prerequisite +to get permission to publicly distribute the +already finished LinuxGlide port by Daryll Strauss). + +Linux q2test (and soon LinuxQuake2) demonstrate that +Mesa with the MesaVoodoo driver is quite up to the +requirements for a glDOOM port. If anybody wants to +get into Linux glDOOM, please drop me a line. + +There is a Win32 GLDOOM port in the works, by Jim Dose. +Quoting a recent posting by him: + +"I haven't had as much time lately to really work on +the conversion. I currently have the renderer drawing +the walls and floors as texture spans as the are in +the software renderer. There's lighting on the walls, +but not the floors, and sprites are being drawn, but +not with the right texture. I figure that this is one +nights work to get the game looking "normal". I haven't +tested the game on less than a p200, so I'm not sure +how it will perform under the average machine, but I +don't expect it to be blindingly fast because of the +number of spans that have to be drawn each frame. +Rendering as polys is definitely the way to go. + +The reason I chose to do spans first was because it +left the base renderer intact and I could concentrate +on ironing out any Windows compatibility problems. +Actually, the first version I had running was simply +a blit of the 320x200 game screen through Open GL. +Surprisingly, this actually was very playable, but +certainly wasn't taking any advantage of 3D acceleration. +Once the game was running, I started converting all +the span routines over." + +Comment: for merging Linuxdoom with Win32, this is +probably the best source for getting the Win32 +environment done - before more significant changes +occur. + +"One problem with drawing spans is that the engine +doesn't calculate the texture coordinates with +fractional accuracy, so the bilinear filtering works +vertically, but not horizontally on the walls. I may +try to fix this, but since I plan to use polys for +the final version, it's not really high priority. +Also, spans don't really allow for looking up and +down." + +Comment: true looking up/down vs. Heretic-style +y-shearing seems to require either a strange kind +of transofrmation matrix (he probably does not use +the OpenGL transformation at all), or rendering +all the spans as textured rectangular slices +instead of using glDrawBitmap. No, polys are the +way to go. + +"When I tackle the conversion to polys, one big problem +I'll encounter is drawing floors. Since the world is +stored in a 2D bsp tree, there is no information on +the shape of the floors. In fact the floors can be +concave and may include holes (typically, most renderers +break concave polys down into a collection of convex +polys or triangles). In software, the floors are actually +drawn using an algorithm that's similar to a flood fill +(except that a list of open spans is kept instead of a +buffer of pixels). This makes drawing the floors as +polys fairly difficult." + +A polygon based approach will require significant changes +to the data structures used in the refresh module. I +recommend either separating a libref_soft.so first (a +Quake2 like approach), and creating libref_gl afterwards, +or abandoning the software rendering entirely. + +John Carmack wrote once upon a time: +"... the U64 DOOM engine is much more what I would consider +The Right Thing now -- it turns the subsector boundaries +into polygons for the floors and ceilings ahead of time, +then for rendering it walks the BSP front to back, doing +visibility determination of subsectors by the one dimensional +occlusion buffer and clipping sprites into subsectors, then +it goes backwards through the visible subsectors, drawing +floors, ceilings, walls, then sorted internal sprite fragments. +It's a ton simpler and a ton faster, although it does suffer +some overdraw when a high subsector overlooks a low one (but +that is more than made up for by the simplicity of everything +else)." + +Well, IMO compiling a separate list of floor/ceiling polygons +after having read the WAD file, and thus introducing this as +a completely separate data structure to the current code base +might be the easiest thing to do. Jim Dose writes: + +"One method I may use to draw the floors as polys was suggested +by Billy Zelsnack of Rebel Boat Rocker when we were working +at 3D Realms together a few years ago. Basically, Billy was +designing an engine that dealt with the world in a 2D portal +format similar to the one that Build used, except that it had +true looking up and down (no shearing). Since floors were +basically implicit and could be concave, Billy drew them as +if the walls extended downwards to infinity, but fixed the +texture coordinates to appear that they were on the plane of +the floor. The effect was that you could look up and down and +there were no gaps or overdraw. It's a fairly clever method +and allows you to store the world in a simpler data format. +Had perspective texture mapping been fast enough back then, +both Build and Doom could have done this in software." + +Perhaps the above is sufficient to get you started. +Other Issues: + +1. Occlusion +DOOM uses a per-column lookup (top/bottom index) to do HLHSR. +This works fine with span based rendering (well, getting +horizontal spans of floors/ceilings into the picture is a +separate story). It isn't really mindboggling with polygon +based rendering. GLDOOM should abandon that. + +2. Precalculated Visibility +DOOM has the data used by Quake's PVS - in REJECT. +During Quake development, lots of replacements for the +occlusion buffer were tried, and PVS turned out to be best. +I suggest usind the REJECT as PVS. + +There have been special effects using a utility named RMB. +REJECT is a lump meant for enemy AI LoS calculation - a +nonstandard REJECT will not work as a PVS, and introduce +rendering errors. I suggest looking for a PVS lump in the +WAD, and using REJECT if none is found. That way, it might +be feasible to eat the cake and keep it. + +3. Mipmaps +DOOM does not have mipmapping. As we have 8bit palettized +textures, OpenGL mipmapping might not give the desired +results. Plus, composing textures from patches at runtime +would require runtime mipmapping. Precalculated mipmaps +in the WAD? + +4. Sprites +Partly transparent textures and sprites impose another +problem related to mipmapping. Without alpha channel, +this could give strange results. Precalculated, valid +sprite mipmaps (w/o alpha)? diff --git a/docs/classes.txt b/docs/classes.txt new file mode 100644 index 00000000000..682d3229616 --- /dev/null +++ b/docs/classes.txt @@ -0,0 +1,303 @@ +ZDoom 1.19 offers a partial conversion of the Doom code to C++. As such, some +functions and classes have been encapsulated in classes. This document tries +to give an overview of those classes and how to use them. + +Command line parameters +======================= + +Previous versions of ZDoom kept the command line in the myargv and myargc +global variables. This version uses a single variable, Args, of type DArgs. +This class is defined in m_argv.h and implemented in m_argv.cpp. The three +most important functions are: + + int DArgs::CheckParm (const char *check) const; + + Checks to see if a parameter exists. If it does, it's index number is + returned. Use the GetArg() method to retrieve an arguments specified + after it. + + char *DArgs::CheckValue (const char *check) const; + + This is similar to CheckParm(), but it returns the value of the argument + immediately following parameter. If the parameter is not present, or it + has no argument, NULL is returned. + + char *DArgs::GetArg (int index) const; + + Retrieves the value of an argument. This is similar to argv[index]. + +For the other functions, check the implementation in m_argv.cpp to see what +they do. + +Error messages +============== + +There are two functions for reporting error conditions: I_Error() and +I_FatalError(). Use the first for errors that can be recovered from. It will +drop the user to the fullscreen console and print the message. Use the +second for error conditions that are much harder to recover from. It will +terminate the program and display the message. + +Console commands +================ + +Adding new console commands is now very simple, compared to previous +versions of ZDoom. Registration is now completely automatic if you use the +BEGIN_COMMAND and END_COMMAND macros defined in c_dispatch.h. A simple +command could be implemented like this: + + #include "c_dispatch.h" + + BEGIN_COMMAND(hello) + { + Printf (PRINT_HIGH, "Hello, world!\n"); + } + END_COMMAND(hello) + +The parameter to the BEGIN_COMMAND and END_COMMAND macros is the name of +the command, as typed at the console (in this case, "hello"). You should use +the same name for both BEGIN_ and END_. You can access the arguments to the +command using argc and argv. If you want to know who activated the command, +m_Instigator is a pointer to the actor of the player who called it. + +Console variables +================= + +Adding new console variables is also similar. The c_cvars.h file contains +four macros related to using cvars: + + CVAR (name, default, flags) + + Declares a new console variable with the name "name" and default + value "default" and flags "flags". (See c_cvars.h for the different + flags). An example: + + CVAR (var_friction, "1", CVAR_SERVERINFO); + + EXTERN_CVAR (name) + + Imports a cvar defined elsewhere. This just generates the code + "extern cvar_t name;", but you should still use this macro. + + BEGIN_CUSTOM_CVAR (name, default, flags) + END_CUSTOM_CVAR (name) + + Declares a cvar that performs some special action each time its value + changes. You should use a compound statement between the BEGIN_ and + END_ macros, just like with commands above. Any code between these + two macros can use "var" to access the associated cvar. Example: + + BEGIN_CUSTOM_CVAR (splashfactor, "1.0", CVAR_SERVERINFO) + { + if (var.value <= 0.0f) + var.Set (1.0f); + else + selfthrustscale = 1.0f / var.value; + } + END_CUSTOM_CVAR (splashfactor) + + This example also illustrates bounds checking for cvars. The basic + idea is: + + if (variable is within range) + + else + + + Calling Set() will automatically execute the code block again, so you + must make sure that you do nothing but reset the value of the cvar if + it's out of range. The code block will also be executed at program + startup when the cvar is constructed. + +The DObject class hierarchy +=========================== + +Most classes in ZDoom 1.18 are descendants of the DObject class. This class +provides basic typechecking and serialization functionality. In a future +version of ZDoom, it will also provide a means to interface C++ code with +DoomScript. If you want to be able to perform type-checking on a class, save +it to disk, or access it from DoomScript (in a later version), it should be +a descendant of DObject. + +The basic features of DObject require that you use some of the macros in +dobject.h: DECLARE_CLASS, IMPLEMENT_CLASS, DECLARE_SERIAL, and +IMPLEMENT_SERIAL. For a class that won't be saved to disk, do this: + + class MyClass : public DObject + { + DECLARE_CLASS (MyClass, DObject) + public: + ... + Rest of class definition + ... + } + + Then someplace else, where you define the class, add this line: + + IMPLEMENT_CLASS (MyClass, DObject) + + (You should be sure to replace MyClass with the actual name of your class + and DObject with the name of your class's superclass.) + + For a class that can be saved to disk (ie, a serializable class), use + DECLARE_SERIAL and IMPLEMENT_SERIAL instead. Serializable classes require + default constructors. If you don't want anybody to be able to create an + instance of the class using the default constructor, you can hide it + inside the private portion of the class definition: + + ... + private: + MyClass () {} + ... + + Serializable classes also require that you define a Serialize() method. + This function should call the superclass's Serialize() method and then + either store or extract the fields for the class. (Whenever you change + the contents of a class, be sure to change its accompanying Serialize() + method.) A generic Serialize() looks like this: + + void MyClass::Serialize (FArchive &arc) + { + Super::Serialize (arc); + if (arc.IsStoring ()) + { + arc << m_field1 << m_field2 << m_field3 << ... ; + } + else + { + arc >> m_field1 >> m_field2 >> m_field3 >> ... ; + } + } + + There are also some structs that use some serialization code that you + should be sure to change if you change the structs. The code for + serializing sector_t and line_t can be found in P_SerializeWorld() in + p_saveg.cpp. The code for serializing player_t is in p_user.cpp as + player_s::Serialize(). + + To determine the type of an object, you can use the IsA() and IsKindOf() + methods of DObject. IsA() tests if the object is an instance of a + specific type of class, and is probably not what you want. IsKindOf() + checks if an object is a specific type of class or one of its + descendants. Example: Suppose anActor points to an instance of AActor. + (anActor->IsA (RUNTIME_CLASS(DThinker))) will return false because AActor + is not the same as DThinker, but (anActor->IsKindOf + (RUNTIME_CLASS(DThinker))) will return true because AActor is a + descendant of DThinker. + +Pointer cleanup +=============== + +Whenever an object is destroyed, ZDoom will attempt to NULL any pointers that +pointed to that object. This eliminates various anomalies caused by trying to +reference stale pointers. This mechanism is not entirely transparent and +requires some work on your part. When you create a subclass of DObject that +contains pointers, you should use the IMPLEMENT_POINTY_SERIAL or +IMPLEMENT_POINTY_CLASS macros instead of IMPLEMENT_SERIAL or IMPLEMENT_CLASS. +Following the macro, you list each element of the class that points to a +DObject (or a subclass of it). If the pointer points to something that is not +a DObject (such as a char *), you do not need to include it in this list. +After you list all the pointers, use the END_POINTERS macro. + +The implementation for the AActor class looks like this: + +IMPLEMENT_POINTY_SERIAL (AActor, DThinker) + DECLARE_POINTER (target) + DECLARE_POINTER (lastenemy) + DECLARE_POINTER (tracer) + DECLARE_POINTER (goal) +END_POINTERS + +If you add pointers to any class, you need to update this list accordingly. +The player class uses a hack, because it is not derived from DObject, to +clear pointers. See player_s::FixPointers() in p_user.cpp if you add any +pointers to player_s. + +When you want to destroy any object derived from DThinker (this includes all +actors), call that object's Destroy() method. Do not use delete, because it +is not guaranteed to perform all necessary cleanup. If the object is not +derived from DThinker, however, you can safely call delete on it. + +As an example, if you have an instance of AActor called actor, and you want +to get rid of it, use: + actor->Destroy (); + +If you have an instance of DCanvas called canvas and want to get rid of it, +either of the following will work (but not both): + canvas->Destroy (); or + delete canvas; + +Thinkers +======== + +Almost everything that can affect the appearance of the world is implemented +as a subclass of DThinker. The important base classes are: + + DPolyAction + + A polyobject that is doing something (DRotatePoly, DMovePoly, or + DPolyDoor). + + DSectorEffect + + An effect that occurs inside a certain sector. This is further broken + up into DLighting (for lighting changes) and DMover (for floor/ + ceiling movement). DMover is also subclassed into DMovingFloor (for + moving floors only) and DMovingCeiling (for moving ceilings only). + For effects that move both the floor and ceiling, subclass DMover + and have a look at either DPillar or DElevator. + + AActor + + This is probably the most important. All players, monsters, items, + ammo, weapons, and anything else that appears as a sprite in the + world is an instance of AActor. This is nowhere near as encapsulated + as I would like it to be because of the necessity to maintain + compatibility with DeHackEd patches until DoomScript is done. This + means that there is no easy way to subclass AActor and spawn an + instance of the subclass in the map. I don't like it, but it's a step + in the right direction. + +To find all instances of a specific type of thinker in a map, you can use the +TThinkerIterator template class. It's usage is simple: + + TThinkerIterator iterator; + TypeOfClass *object; + + while ( (object = iterator.Next ()) ) + { + // do something with the object + } + +AActor methods +============== + +A few of the functions that operate on actors have been moved inside the +AActor class: + + P_ClearTidHashes() -> AActor::ClearTIDHashes() + P_AddMobjToHash() -> AActor::AddToHash() + P_RemoveMobjFromHash() -> AActor::RemoveFromHash() + P_FindMobjByTid() -> AActor::FindByTID() + P_FindGoal() -> AActor::FindGoal() + + P_UnsetThingPosition() -> AActor::UnlinkFromWorld() + P_SetThingPosition() -> AActor::LinkToWorld() + +AActor::SetOrigin() has also been introduced. It simply moves the actor to +a specific location on the map without performing any collision detection. + +A bit more on serialization +=========================== + +The serialization mechanism is a fairly standard, yet powerful, framework +that can save a bunch of objects to disk and properly maintain pointers +between them. When you store a pointer to an object, the object will also be +stored to disk if it hasn't been already. When you read the pointer, the +object it points to will also be read from disk if it hasn't been already. +This allows pointers to objects to be preserved without any extra effort on +your part. Pointers to something other than a DObject or one of its +descendents need to be implemented specially by overloading operator << (see +info.h for a few of these). If you're not sure how serialization works, take +a look at some of the serialization functions for the existing classes by +grepping through the source for "::Serialize" (without the quotes). diff --git a/docs/colors.txt b/docs/colors.txt new file mode 100644 index 00000000000..b4c43c72f8b --- /dev/null +++ b/docs/colors.txt @@ -0,0 +1,756 @@ +! $XConsortium: rgb.txt,v 10.41 94/02/20 18:39:36 rws Exp $ + +255 250 250 snow +248 248 255 ghost white +248 248 255 GhostWhite +245 245 245 white smoke +245 245 245 WhiteSmoke +220 220 220 gainsboro +255 250 240 floral white +255 250 240 FloralWhite +253 245 230 old lace +253 245 230 OldLace +250 240 230 linen +250 235 215 antique white +250 235 215 AntiqueWhite +255 239 213 papaya whip +255 239 213 PapayaWhip +255 235 205 blanched almond +255 235 205 BlanchedAlmond +255 228 196 bisque +255 218 185 peach puff +255 218 185 PeachPuff +255 222 173 navajo white +255 222 173 NavajoWhite +255 228 181 moccasin +255 248 220 cornsilk +255 255 240 ivory +255 250 205 lemon chiffon +255 250 205 LemonChiffon +255 245 238 seashell +240 255 240 honeydew +245 255 250 mint cream +245 255 250 MintCream +240 255 255 azure +240 248 255 alice blue +240 248 255 AliceBlue +230 230 250 lavender +255 240 245 lavender blush +255 240 245 LavenderBlush +255 228 225 misty rose +255 228 225 MistyRose +255 255 255 white + 0 0 0 black + 47 79 79 dark slate gray + 47 79 79 DarkSlateGray + 47 79 79 dark slate grey + 47 79 79 DarkSlateGrey +105 105 105 dim gray +105 105 105 DimGray +105 105 105 dim grey +105 105 105 DimGrey +112 128 144 slate gray +112 128 144 SlateGray +112 128 144 slate grey +112 128 144 SlateGrey +119 136 153 light slate gray +119 136 153 LightSlateGray +119 136 153 light slate grey +119 136 153 LightSlateGrey +190 190 190 gray +190 190 190 grey +211 211 211 light grey +211 211 211 LightGrey +211 211 211 light gray +211 211 211 LightGray + 25 25 112 midnight blue + 25 25 112 MidnightBlue + 0 0 128 navy + 0 0 128 navy blue + 0 0 128 NavyBlue +100 149 237 cornflower blue +100 149 237 CornflowerBlue + 72 61 139 dark slate blue + 72 61 139 DarkSlateBlue +106 90 205 slate blue +106 90 205 SlateBlue +123 104 238 medium slate blue +123 104 238 MediumSlateBlue +132 112 255 light slate blue +132 112 255 LightSlateBlue + 0 0 205 medium blue + 0 0 205 MediumBlue + 65 105 225 royal blue + 65 105 225 RoyalBlue + 0 0 255 blue + 30 144 255 dodger blue + 30 144 255 DodgerBlue + 0 191 255 deep sky blue + 0 191 255 DeepSkyBlue +135 206 235 sky blue +135 206 235 SkyBlue +135 206 250 light sky blue +135 206 250 LightSkyBlue + 70 130 180 steel blue + 70 130 180 SteelBlue +176 196 222 light steel blue +176 196 222 LightSteelBlue +173 216 230 light blue +173 216 230 LightBlue +176 224 230 powder blue +176 224 230 PowderBlue +175 238 238 pale turquoise +175 238 238 PaleTurquoise + 0 206 209 dark turquoise + 0 206 209 DarkTurquoise + 72 209 204 medium turquoise + 72 209 204 MediumTurquoise + 64 224 208 turquoise + 0 255 255 cyan +224 255 255 light cyan +224 255 255 LightCyan + 95 158 160 cadet blue + 95 158 160 CadetBlue +102 205 170 medium aquamarine +102 205 170 MediumAquamarine +127 255 212 aquamarine + 0 100 0 dark green + 0 100 0 DarkGreen + 85 107 47 dark olive green + 85 107 47 DarkOliveGreen +143 188 143 dark sea green +143 188 143 DarkSeaGreen + 46 139 87 sea green + 46 139 87 SeaGreen + 60 179 113 medium sea green + 60 179 113 MediumSeaGreen + 32 178 170 light sea green + 32 178 170 LightSeaGreen +152 251 152 pale green +152 251 152 PaleGreen + 0 255 127 spring green + 0 255 127 SpringGreen +124 252 0 lawn green +124 252 0 LawnGreen + 0 255 0 green +127 255 0 chartreuse + 0 250 154 medium spring green + 0 250 154 MediumSpringGreen +173 255 47 green yellow +173 255 47 GreenYellow + 50 205 50 lime green + 50 205 50 LimeGreen +154 205 50 yellow green +154 205 50 YellowGreen + 34 139 34 forest green + 34 139 34 ForestGreen +107 142 35 olive drab +107 142 35 OliveDrab +189 183 107 dark khaki +189 183 107 DarkKhaki +240 230 140 khaki +238 232 170 pale goldenrod +238 232 170 PaleGoldenrod +250 250 210 light goldenrod yellow +250 250 210 LightGoldenrodYellow +255 255 224 light yellow +255 255 224 LightYellow +255 255 0 yellow +255 215 0 gold +238 221 130 light goldenrod +238 221 130 LightGoldenrod +218 165 32 goldenrod +184 134 11 dark goldenrod +184 134 11 DarkGoldenrod +188 143 143 rosy brown +188 143 143 RosyBrown +205 92 92 indian red +205 92 92 IndianRed +139 69 19 saddle brown +139 69 19 SaddleBrown +160 82 45 sienna +205 133 63 peru +222 184 135 burlywood +245 245 220 beige +245 222 179 wheat +244 164 96 sandy brown +244 164 96 SandyBrown +210 180 140 tan +210 105 30 chocolate +178 34 34 firebrick +165 42 42 brown +233 150 122 dark salmon +233 150 122 DarkSalmon +250 128 114 salmon +255 160 122 light salmon +255 160 122 LightSalmon +255 165 0 orange +255 140 0 dark orange +255 140 0 DarkOrange +255 127 80 coral +240 128 128 light coral +240 128 128 LightCoral +255 99 71 tomato +255 69 0 orange red +255 69 0 OrangeRed +255 0 0 red +255 105 180 hot pink +255 105 180 HotPink +255 20 147 deep pink +255 20 147 DeepPink +255 192 203 pink +255 182 193 light pink +255 182 193 LightPink +219 112 147 pale violet red +219 112 147 PaleVioletRed +176 48 96 maroon +199 21 133 medium violet red +199 21 133 MediumVioletRed +208 32 144 violet red +208 32 144 VioletRed +255 0 255 magenta +238 130 238 violet +221 160 221 plum +218 112 214 orchid +186 85 211 medium orchid +186 85 211 MediumOrchid +153 50 204 dark orchid +153 50 204 DarkOrchid +148 0 211 dark violet +148 0 211 DarkViolet +138 43 226 blue violet +138 43 226 BlueViolet +160 32 240 purple +147 112 219 medium purple +147 112 219 MediumPurple +216 191 216 thistle +255 250 250 snow1 +238 233 233 snow2 +205 201 201 snow3 +139 137 137 snow4 +255 245 238 seashell1 +238 229 222 seashell2 +205 197 191 seashell3 +139 134 130 seashell4 +255 239 219 AntiqueWhite1 +238 223 204 AntiqueWhite2 +205 192 176 AntiqueWhite3 +139 131 120 AntiqueWhite4 +255 228 196 bisque1 +238 213 183 bisque2 +205 183 158 bisque3 +139 125 107 bisque4 +255 218 185 PeachPuff1 +238 203 173 PeachPuff2 +205 175 149 PeachPuff3 +139 119 101 PeachPuff4 +255 222 173 NavajoWhite1 +238 207 161 NavajoWhite2 +205 179 139 NavajoWhite3 +139 121 94 NavajoWhite4 +255 250 205 LemonChiffon1 +238 233 191 LemonChiffon2 +205 201 165 LemonChiffon3 +139 137 112 LemonChiffon4 +255 248 220 cornsilk1 +238 232 205 cornsilk2 +205 200 177 cornsilk3 +139 136 120 cornsilk4 +255 255 240 ivory1 +238 238 224 ivory2 +205 205 193 ivory3 +139 139 131 ivory4 +240 255 240 honeydew1 +224 238 224 honeydew2 +193 205 193 honeydew3 +131 139 131 honeydew4 +255 240 245 LavenderBlush1 +238 224 229 LavenderBlush2 +205 193 197 LavenderBlush3 +139 131 134 LavenderBlush4 +255 228 225 MistyRose1 +238 213 210 MistyRose2 +205 183 181 MistyRose3 +139 125 123 MistyRose4 +240 255 255 azure1 +224 238 238 azure2 +193 205 205 azure3 +131 139 139 azure4 +131 111 255 SlateBlue1 +122 103 238 SlateBlue2 +105 89 205 SlateBlue3 + 71 60 139 SlateBlue4 + 72 118 255 RoyalBlue1 + 67 110 238 RoyalBlue2 + 58 95 205 RoyalBlue3 + 39 64 139 RoyalBlue4 + 0 0 255 blue1 + 0 0 238 blue2 + 0 0 205 blue3 + 0 0 139 blue4 + 30 144 255 DodgerBlue1 + 28 134 238 DodgerBlue2 + 24 116 205 DodgerBlue3 + 16 78 139 DodgerBlue4 + 99 184 255 SteelBlue1 + 92 172 238 SteelBlue2 + 79 148 205 SteelBlue3 + 54 100 139 SteelBlue4 + 0 191 255 DeepSkyBlue1 + 0 178 238 DeepSkyBlue2 + 0 154 205 DeepSkyBlue3 + 0 104 139 DeepSkyBlue4 +135 206 255 SkyBlue1 +126 192 238 SkyBlue2 +108 166 205 SkyBlue3 + 74 112 139 SkyBlue4 +176 226 255 LightSkyBlue1 +164 211 238 LightSkyBlue2 +141 182 205 LightSkyBlue3 + 96 123 139 LightSkyBlue4 +198 226 255 SlateGray1 +185 211 238 SlateGray2 +159 182 205 SlateGray3 +108 123 139 SlateGray4 +202 225 255 LightSteelBlue1 +188 210 238 LightSteelBlue2 +162 181 205 LightSteelBlue3 +110 123 139 LightSteelBlue4 +191 239 255 LightBlue1 +178 223 238 LightBlue2 +154 192 205 LightBlue3 +104 131 139 LightBlue4 +224 255 255 LightCyan1 +209 238 238 LightCyan2 +180 205 205 LightCyan3 +122 139 139 LightCyan4 +187 255 255 PaleTurquoise1 +174 238 238 PaleTurquoise2 +150 205 205 PaleTurquoise3 +102 139 139 PaleTurquoise4 +152 245 255 CadetBlue1 +142 229 238 CadetBlue2 +122 197 205 CadetBlue3 + 83 134 139 CadetBlue4 + 0 245 255 turquoise1 + 0 229 238 turquoise2 + 0 197 205 turquoise3 + 0 134 139 turquoise4 + 0 255 255 cyan1 + 0 238 238 cyan2 + 0 205 205 cyan3 + 0 139 139 cyan4 +151 255 255 DarkSlateGray1 +141 238 238 DarkSlateGray2 +121 205 205 DarkSlateGray3 + 82 139 139 DarkSlateGray4 +127 255 212 aquamarine1 +118 238 198 aquamarine2 +102 205 170 aquamarine3 + 69 139 116 aquamarine4 +193 255 193 DarkSeaGreen1 +180 238 180 DarkSeaGreen2 +155 205 155 DarkSeaGreen3 +105 139 105 DarkSeaGreen4 + 84 255 159 SeaGreen1 + 78 238 148 SeaGreen2 + 67 205 128 SeaGreen3 + 46 139 87 SeaGreen4 +154 255 154 PaleGreen1 +144 238 144 PaleGreen2 +124 205 124 PaleGreen3 + 84 139 84 PaleGreen4 + 0 255 127 SpringGreen1 + 0 238 118 SpringGreen2 + 0 205 102 SpringGreen3 + 0 139 69 SpringGreen4 + 0 255 0 green1 + 0 238 0 green2 + 0 205 0 green3 + 0 139 0 green4 +127 255 0 chartreuse1 +118 238 0 chartreuse2 +102 205 0 chartreuse3 + 69 139 0 chartreuse4 +192 255 62 OliveDrab1 +179 238 58 OliveDrab2 +154 205 50 OliveDrab3 +105 139 34 OliveDrab4 +202 255 112 DarkOliveGreen1 +188 238 104 DarkOliveGreen2 +162 205 90 DarkOliveGreen3 +110 139 61 DarkOliveGreen4 +255 246 143 khaki1 +238 230 133 khaki2 +205 198 115 khaki3 +139 134 78 khaki4 +255 236 139 LightGoldenrod1 +238 220 130 LightGoldenrod2 +205 190 112 LightGoldenrod3 +139 129 76 LightGoldenrod4 +255 255 224 LightYellow1 +238 238 209 LightYellow2 +205 205 180 LightYellow3 +139 139 122 LightYellow4 +255 255 0 yellow1 +238 238 0 yellow2 +205 205 0 yellow3 +139 139 0 yellow4 +255 215 0 gold1 +238 201 0 gold2 +205 173 0 gold3 +139 117 0 gold4 +255 193 37 goldenrod1 +238 180 34 goldenrod2 +205 155 29 goldenrod3 +139 105 20 goldenrod4 +255 185 15 DarkGoldenrod1 +238 173 14 DarkGoldenrod2 +205 149 12 DarkGoldenrod3 +139 101 8 DarkGoldenrod4 +255 193 193 RosyBrown1 +238 180 180 RosyBrown2 +205 155 155 RosyBrown3 +139 105 105 RosyBrown4 +255 106 106 IndianRed1 +238 99 99 IndianRed2 +205 85 85 IndianRed3 +139 58 58 IndianRed4 +255 130 71 sienna1 +238 121 66 sienna2 +205 104 57 sienna3 +139 71 38 sienna4 +255 211 155 burlywood1 +238 197 145 burlywood2 +205 170 125 burlywood3 +139 115 85 burlywood4 +255 231 186 wheat1 +238 216 174 wheat2 +205 186 150 wheat3 +139 126 102 wheat4 +255 165 79 tan1 +238 154 73 tan2 +205 133 63 tan3 +139 90 43 tan4 +255 127 36 chocolate1 +238 118 33 chocolate2 +205 102 29 chocolate3 +139 69 19 chocolate4 +255 48 48 firebrick1 +238 44 44 firebrick2 +205 38 38 firebrick3 +139 26 26 firebrick4 +255 64 64 brown1 +238 59 59 brown2 +205 51 51 brown3 +139 35 35 brown4 +255 140 105 salmon1 +238 130 98 salmon2 +205 112 84 salmon3 +139 76 57 salmon4 +255 160 122 LightSalmon1 +238 149 114 LightSalmon2 +205 129 98 LightSalmon3 +139 87 66 LightSalmon4 +255 165 0 orange1 +238 154 0 orange2 +205 133 0 orange3 +139 90 0 orange4 +255 127 0 DarkOrange1 +238 118 0 DarkOrange2 +205 102 0 DarkOrange3 +139 69 0 DarkOrange4 +255 114 86 coral1 +238 106 80 coral2 +205 91 69 coral3 +139 62 47 coral4 +255 99 71 tomato1 +238 92 66 tomato2 +205 79 57 tomato3 +139 54 38 tomato4 +255 69 0 OrangeRed1 +238 64 0 OrangeRed2 +205 55 0 OrangeRed3 +139 37 0 OrangeRed4 +255 0 0 red1 +238 0 0 red2 +205 0 0 red3 +139 0 0 red4 +255 20 147 DeepPink1 +238 18 137 DeepPink2 +205 16 118 DeepPink3 +139 10 80 DeepPink4 +255 110 180 HotPink1 +238 106 167 HotPink2 +205 96 144 HotPink3 +139 58 98 HotPink4 +255 181 197 pink1 +238 169 184 pink2 +205 145 158 pink3 +139 99 108 pink4 +255 174 185 LightPink1 +238 162 173 LightPink2 +205 140 149 LightPink3 +139 95 101 LightPink4 +255 130 171 PaleVioletRed1 +238 121 159 PaleVioletRed2 +205 104 137 PaleVioletRed3 +139 71 93 PaleVioletRed4 +255 52 179 maroon1 +238 48 167 maroon2 +205 41 144 maroon3 +139 28 98 maroon4 +255 62 150 VioletRed1 +238 58 140 VioletRed2 +205 50 120 VioletRed3 +139 34 82 VioletRed4 +255 0 255 magenta1 +238 0 238 magenta2 +205 0 205 magenta3 +139 0 139 magenta4 +255 131 250 orchid1 +238 122 233 orchid2 +205 105 201 orchid3 +139 71 137 orchid4 +255 187 255 plum1 +238 174 238 plum2 +205 150 205 plum3 +139 102 139 plum4 +224 102 255 MediumOrchid1 +209 95 238 MediumOrchid2 +180 82 205 MediumOrchid3 +122 55 139 MediumOrchid4 +191 62 255 DarkOrchid1 +178 58 238 DarkOrchid2 +154 50 205 DarkOrchid3 +104 34 139 DarkOrchid4 +155 48 255 purple1 +145 44 238 purple2 +125 38 205 purple3 + 85 26 139 purple4 +171 130 255 MediumPurple1 +159 121 238 MediumPurple2 +137 104 205 MediumPurple3 + 93 71 139 MediumPurple4 +255 225 255 thistle1 +238 210 238 thistle2 +205 181 205 thistle3 +139 123 139 thistle4 + 0 0 0 gray0 + 0 0 0 grey0 + 3 3 3 gray1 + 3 3 3 grey1 + 5 5 5 gray2 + 5 5 5 grey2 + 8 8 8 gray3 + 8 8 8 grey3 + 10 10 10 gray4 + 10 10 10 grey4 + 13 13 13 gray5 + 13 13 13 grey5 + 15 15 15 gray6 + 15 15 15 grey6 + 18 18 18 gray7 + 18 18 18 grey7 + 20 20 20 gray8 + 20 20 20 grey8 + 23 23 23 gray9 + 23 23 23 grey9 + 26 26 26 gray10 + 26 26 26 grey10 + 28 28 28 gray11 + 28 28 28 grey11 + 31 31 31 gray12 + 31 31 31 grey12 + 33 33 33 gray13 + 33 33 33 grey13 + 36 36 36 gray14 + 36 36 36 grey14 + 38 38 38 gray15 + 38 38 38 grey15 + 41 41 41 gray16 + 41 41 41 grey16 + 43 43 43 gray17 + 43 43 43 grey17 + 46 46 46 gray18 + 46 46 46 grey18 + 48 48 48 gray19 + 48 48 48 grey19 + 51 51 51 gray20 + 51 51 51 grey20 + 54 54 54 gray21 + 54 54 54 grey21 + 56 56 56 gray22 + 56 56 56 grey22 + 59 59 59 gray23 + 59 59 59 grey23 + 61 61 61 gray24 + 61 61 61 grey24 + 64 64 64 gray25 + 64 64 64 grey25 + 66 66 66 gray26 + 66 66 66 grey26 + 69 69 69 gray27 + 69 69 69 grey27 + 71 71 71 gray28 + 71 71 71 grey28 + 74 74 74 gray29 + 74 74 74 grey29 + 77 77 77 gray30 + 77 77 77 grey30 + 79 79 79 gray31 + 79 79 79 grey31 + 82 82 82 gray32 + 82 82 82 grey32 + 84 84 84 gray33 + 84 84 84 grey33 + 87 87 87 gray34 + 87 87 87 grey34 + 89 89 89 gray35 + 89 89 89 grey35 + 92 92 92 gray36 + 92 92 92 grey36 + 94 94 94 gray37 + 94 94 94 grey37 + 97 97 97 gray38 + 97 97 97 grey38 + 99 99 99 gray39 + 99 99 99 grey39 +102 102 102 gray40 +102 102 102 grey40 +105 105 105 gray41 +105 105 105 grey41 +107 107 107 gray42 +107 107 107 grey42 +110 110 110 gray43 +110 110 110 grey43 +112 112 112 gray44 +112 112 112 grey44 +115 115 115 gray45 +115 115 115 grey45 +117 117 117 gray46 +117 117 117 grey46 +120 120 120 gray47 +120 120 120 grey47 +122 122 122 gray48 +122 122 122 grey48 +125 125 125 gray49 +125 125 125 grey49 +127 127 127 gray50 +127 127 127 grey50 +130 130 130 gray51 +130 130 130 grey51 +133 133 133 gray52 +133 133 133 grey52 +135 135 135 gray53 +135 135 135 grey53 +138 138 138 gray54 +138 138 138 grey54 +140 140 140 gray55 +140 140 140 grey55 +143 143 143 gray56 +143 143 143 grey56 +145 145 145 gray57 +145 145 145 grey57 +148 148 148 gray58 +148 148 148 grey58 +150 150 150 gray59 +150 150 150 grey59 +153 153 153 gray60 +153 153 153 grey60 +156 156 156 gray61 +156 156 156 grey61 +158 158 158 gray62 +158 158 158 grey62 +161 161 161 gray63 +161 161 161 grey63 +163 163 163 gray64 +163 163 163 grey64 +166 166 166 gray65 +166 166 166 grey65 +168 168 168 gray66 +168 168 168 grey66 +171 171 171 gray67 +171 171 171 grey67 +173 173 173 gray68 +173 173 173 grey68 +176 176 176 gray69 +176 176 176 grey69 +179 179 179 gray70 +179 179 179 grey70 +181 181 181 gray71 +181 181 181 grey71 +184 184 184 gray72 +184 184 184 grey72 +186 186 186 gray73 +186 186 186 grey73 +189 189 189 gray74 +189 189 189 grey74 +191 191 191 gray75 +191 191 191 grey75 +194 194 194 gray76 +194 194 194 grey76 +196 196 196 gray77 +196 196 196 grey77 +199 199 199 gray78 +199 199 199 grey78 +201 201 201 gray79 +201 201 201 grey79 +204 204 204 gray80 +204 204 204 grey80 +207 207 207 gray81 +207 207 207 grey81 +209 209 209 gray82 +209 209 209 grey82 +212 212 212 gray83 +212 212 212 grey83 +214 214 214 gray84 +214 214 214 grey84 +217 217 217 gray85 +217 217 217 grey85 +219 219 219 gray86 +219 219 219 grey86 +222 222 222 gray87 +222 222 222 grey87 +224 224 224 gray88 +224 224 224 grey88 +227 227 227 gray89 +227 227 227 grey89 +229 229 229 gray90 +229 229 229 grey90 +232 232 232 gray91 +232 232 232 grey91 +235 235 235 gray92 +235 235 235 grey92 +237 237 237 gray93 +237 237 237 grey93 +240 240 240 gray94 +240 240 240 grey94 +242 242 242 gray95 +242 242 242 grey95 +245 245 245 gray96 +245 245 245 grey96 +247 247 247 gray97 +247 247 247 grey97 +250 250 250 gray98 +250 250 250 grey98 +252 252 252 gray99 +252 252 252 grey99 +255 255 255 gray100 +255 255 255 grey100 +169 169 169 dark grey +169 169 169 DarkGrey +169 169 169 dark gray +169 169 169 DarkGray +0 0 139 dark blue +0 0 139 DarkBlue +0 139 139 dark cyan +0 139 139 DarkCyan +139 0 139 dark magenta +139 0 139 DarkMagenta +139 0 0 dark red +139 0 0 DarkRed +144 238 144 light green +144 238 144 LightGreen + + diff --git a/docs/commands.txt b/docs/commands.txt new file mode 100644 index 00000000000..cb510959873 --- /dev/null +++ b/docs/commands.txt @@ -0,0 +1,1742 @@ +This document lists all commands and cvars supported by the current version +of ZDoom (1.22) and a short description of each. There are a total of 130 +commands and 141 cvars. +=========================================================================== + +There are five types of cvars: + +boolean: This is a number that can be either "0" or "1". "0" indicates no/ + false, and "1" indicates yes/true. + + color: This is a series of three hexadecimal numbers representing the + amounts of red, green, and blue (in that order) in a color. For + example, pure redwould be represented as "ffff 0000 0000". The + setcolor command can be used to set one of these cvars using a + color name instead of numbers. (See the description of the + setcolor command below.) + + number: This is an ordinary number. + + integer: This is an ordinary that doesn't take fractional values. + + string: This is a series of text characters enclosed in quotes. + + +Some commands also take parameters. Any parameters that are required are +enclosed in < >, and those that are optional are enclosed in [ ]. + + +ACTION COMMANDS +=============== +NOTE: As in Quake, all action commands come in pairs. When prefixed by a +'+', they activate the corresponding action, and when prefixed by a '-', +they deactivate that action. + + ++attack, -attack + While active, causes the player to fire his active weapon. + ++back, -back + While active, causes the player to move backward. +See also: +forward + ++forward, -forward + While active, causes the player to move forward. +See also: +back + ++jump, -jump + Causes the player to jump. When underwater, the player will swim upward + instead. +See also: +moveup + ++klook, -klook + While active, causes +forward and +back to act like +lookup and +lookdown + instead. +See also: +mlook, +lookup, +lookdown, +forward, +back + ++left, -left + While active, normally causes the player to turn to the left. However, as + long as +strafe is active, this will cause the player to move to the left + instead. +See also: +right, +strafe, +moveleft + ++lookdown, -lookdown + While active, causes the player to look down. +See also: +lookup, +klook + ++lookup, -lookup + While active, causes the player to look up. +See also: +lookdown, +klook + ++mlook, -mlook + While active, causes movement along the mouse's vertical axis to tilt the + player's view up or down instead of moving the player forward or backward. +See also: +klook, freelook, invertmouse, lookspring + ++movedown, -movedown + Moves the player down if swimming or flying. +See also: +moveup + ++moveleft, -moveleft + While active, causes the player to move to the left. +See also: +moveright, +left, +strafe + ++moveright, -moveright + While active, causes the player to move to the right. +See also: +moveleft, +right, +strafe + ++moveup, -moveup + Moves the player up if swimming or flying. +See also: +movedown + ++right, -right + While active, normally causes the player to turn to the right. However, as + long as +strafe is active, this will cause the player to move to the right + instead. +See alse: +left, +strafe, +moveright + ++showscores, -showscores + While this action is active and you are playing a deathmatch game, a list + of the frags made by all players will be displayed on the screen. In + deathmatch games, this list will also automatically be display when you + are dead. + ++speed, -speed + While active, all player movements occur at a rate faster than normal. +See also: cl_run + ++strafe, -strafe + While active, causes all +left and +right commands to act like +moveleft + and +moveright instead. +See also: +left, +right, +moveleft, +moveright + ++use, -use + While active, causes the player to attempt to use any usable items in + front of him/her (such as a door). + + +OTHER COMMANDS AND CVARS +======================== +addbot [name] +(command) + Spawns a bot. If a name is given, the corresponding bot in bots.cfg will be + spawned. Otherwise, a bot will be picked at random from bots.cfg. +See also: listbots, removebots + +alias +(command) + If specified with no parameters, will display a list of all current + aliases. If only is specified, it will be removed from the + list of aliases. If is also specified, it will be added + to the list of aliases as . For example, to create a new + command to kill the monsters on the level, you can use the command: + + alias massacre kill monsters + + Then, you can use the newly created massacre command to kill all the + monsters on the level. + +alwaysapplydmflags +(cvar: boolean) +default: 0 + Normally, some dmflags are only used in deathmatch. If alwaysapplydmflags + is 1, then they will also be used in single-player and co-op games. +See also: dmflags + +am_backcolor +(cvar: color) +default: "6c 54 40" (a light tan) + The color of the automap background. Changes to this cvar take effect the + next time the automap is activated. +See also: all the am_* cvars + +am_cdwallcolor +(cvar: color) +default: "4c 38 20" (a dark tan) + The color of two-sided lines that have a different ceiling height on each + side. Changes to this cvar take effect the next time the automap is + activated. +See also: all the am_* cvars + +am_fdwallcolor +(cvar: color) +default: "88 70 58" (a lighter tan) + The color of two-sided lines that have a different floor height on each + side. Changes to this cvar take effect the next time the automap is + activated. +See also: all the am_* cvars + +am_gridcolor +(cvar: color) +default: "8b 5a 2b" (tan4) + The color of the automap grid. Changes to this cvar take effect the next + time the automap is activated. +See also: all the am_* cvars + +am_interlevelcolor +(cvar: color) +default: "ff 00 00" (red) + The color of inter-level teleporters. These are teleporters that teleport + you to a different map. Changes to this cvar take effect the next time the + automap is activated. +See also: all the am_* cvars + +am_intralevelcolor +(cvar: color) +default: "00 00 ff" (blue) + The color of intra-level teleporters. These are teleporters that teleport + you to a different location on the same map. Changes to this cvar take + effect the next time the automap is activated. +See also: all the am_* cvars + +am_lockedcolor +(cvar: color) +default: "00 00 98" (a blue) + The color of lines that open locked doors. Changes to this cvar take + effetc the next time the automap is activated. +See also: all the am_* cvars + +am_notseencolor +(cvar: color) +default: "6c 6c 6c" (somewhat dark gray) + The color of lines on the automap that haven't yet been seen. Visible with + a computer area map. Changes to this cvar take effect the next time the + automap is activated. +See also: all the am_* cvars + +am_overlay +(cvar: boolean) +default: 0 + Normally, the togglemap command switches the automap between fully off and + fully on. Setting this cvar to "1" will cause togglemap to draw the + automap on top of the player's view before it draws the automap + fullscreen. (Bad description, I know. Just try it) +See also: am_rotate, togglemap + +am_ovotherwallscolor +(cvar: color) +default: "00 88 44" (a dark blueish-green) + The color of passable lines on the automap when the map is overlayed. + Changes to this cvar take effect the next time the automap is activated. +See also: all the am_* cvars + +ov_telecolor +(cvar: color) +default: "ff ff 00" (a bright green) + The color of teleports on the overlayed automap. Changes to this cvar take + effect the next time the automap is activated. +See also: all the am_* cvars + +am_ovthingcolor +(cvar: color) +default: "e8 88 00" (an orange) + The color of things visible with the automap cheat when the map is + overlayed. Changes to this cvar take effect the next time the automap is + activated. +See also: all the am_* cvars + +am_ovunseencolor +(cvar: color) +default: "00 22 6e" (a dark greenish-blue) + The color of unseen lines on the automap when the map is overlayed. + Changes to this cvar take effect the next time the automap is activated. +See also: all the am_* cvars + +am_ovwallcolor +(cvar: color) +default: "00 ff 00" (a bright green) + The color of impassable walls when the automap is overlayed. Changes to + this cvar take effect the next time the automap is activated. +See also: all the am_* cvars + +am_ovyourcolor +(cvar: color) +default: "fc e8 d8" (a very light orange--almost white) + The color of the arrow representing the player in single player games when + the map is overlayed. Changes to this cvar take effect the next time the + automap is activated. +See also: all the am_* cvars + +am_rotate +(cvar: boolean) +default: 0 + Normally, the automap is always drawn such that north is at the top of the + screen. Setting this cvar to "1" causes the automap to be drawn so that + lines toward the top of the screen are always directly in front of the + player's view. Changes to this cvar take effect immediately, unlike most + of the other am_* cvars. This can be particularly useful when the automap + is overlayed. +See also: am_overlay + +am_showmonsters +(cvar: boolean) +default: 1 + When true, the fullscreen automap will display a count of the number of + monsters that have been killed in the current level and the total number + of monsters in the level. +See also: am_showtime, am_showsecrets + +am_showsecrets +(cvar: boolean) +default: 1 + When true, the fullscreen automap will display a count of the number of + secrets that have been found in the current level and the total number of + secrets in the level. +See also: am_showmonsters, am_showtime + +am_showtime +(cvar: boolean) +default: 1 + When true, the fullscreen automap will display the total amount of time + you have been in a level (excluding time that has been paused). +See also: am_showmonsters, am_showsecrets + +am_thingcolor +(cvar: color) +default: "fcfc fcfc fcfc" (almost white) + The color of things revealed with the map cheat. Changes to this cvar take + effect the next time the automap is activated. +See also: all the am_* cvars + +am_tswallcolor +(cvar: color) +default: "8888 8888 8888" (gray) + The color of two-sided lines that don't have any difference in floor or + ceiling heights on either side. Only seen using map cheat. Changes to this + cvar take effect the next time the automap is activated. +See also: all the am_* cvars + +am_usecustomcolors +(cvar: boolean) +default: 1 + When true, the automap uses the colors specified by the am_* cvars, + otherwise it uses the standard DOOM automap colors. Changes to this cvar + take effect the next time the automap is activated. +See also: all the am_* cvars + +am_wallcolor +(cvar: color) +default: "2c2c 1818 0808" (a dark brown) + The color of one-sided and secret walls in the automap. Changes to this + cvar take effect the next time the automap is activated. +See also: all the am_* cvars + +am_xhaircolor +(cvar: color) +default: "8080 8080 8080" (gray) + The color of the "crosshair" dot in the center of the automap. Changes to + this cvar take effect the next time the automap is activated. +See also: all the am_* cvars + +am_yourcolor +(cvar: color) +default: "fcfc e8e8 d8d8" (a very light orange--almost white) + The color of the arrow representing the player in single player games. + Changes to this cvar take effect the next time the automap is activated. +See also: all the am_* cvars + +autoaim +(cvar: number) +default: 5000 + This represents the vertical distance from an object that the player's + sight must be before that object is aimed at. Setting this cvar to "0" + disables autoaiming, while large values such as "5000" will reproduce the + original DOOM behavior of always autoaiming. +See also: color, name + +autoexec +(cvar: string) +default: "/autoexec.cfg" + This is a file that will be automatically executed by ZDoom each time it + starts. This file is executed immediately after the config file is loaded. + It should contain a series of console commands. C++ style comments are + also supported. Comments begin with // and anything after them until the + end of the line will be ignored. + + represents the directory that ZDoom is in and will naturally + vary depending on where you put it. + +bind [key [command string]] +(command) + If no parameters are specified, the entire list of bound keys will be + printed to the console. If only [key] is specified, the binding for that + specific key will be printed. If both [key] and [command string] are + specified, [command string] will be bound to [key]. +See also: doublebind, unbind, unbindall, undoublebind + +binddefaults +(command) + Binds all keys to their default commands. This will not unbind any keys + that do not have any default bindings, so if you want to properly restore + the default controls, you need to use unbindall first. +See also: unbindall, bind + +bot_allowspy +(cvar: boolean) +default: 0 + Allows you to see through the eyes of bots during botmatch games. + +bot_next_color +(cvar: number) +default: 11 + Theoretically, a number representing the color of the next bot to be + spawned. In practice, it doesn't do anything. + +bot_observer +(cvar: boolean) +default: 0 + When set to 1, the player will experience minimal interaction with the + world, and bots will ignore him. + +bumpgamma +(command) + Increases the current gamma level by 0.1. If the new gamma level would be + greater than 3.0, it wraps the gamma around to 1.0 +See also: gamma + +centerview +(command) + Causes the player to look straight ahead. +See also: +lookup, +lookdown + +changemap +(command) + Exits the current level and continues the game on the specified map. + Unlike the map and idclev commands, this command *will* work properly + during network games and is recorded in demos. Unfortunately, it has + occasionally resulted in some problems. It should, however, be safe + enough to use most of the time. +See also: idclev, map + +changemus +(command) + Changes the currently playing music. should be the name of a music + lump or file on disk (which need not have been specified with the -file + parameter). +See also: dir, idmus + +chase +(command) + Turns the chasecom on and off. This command also works while watching + demos, so you can bind it to a key and watch demos in the third person. +See also: chase_dist, chase_height, chasedemo + +chase_dist +(cvar: number) +default: 90 + This is how far away from the player the chasecam likes to be, but it will + get closer as necessary to avoid going inside walls. +See also: chase, chase_height + +chase_height +(cvar: number) +default: -8 + This is the base height above the top of the player's head that the + chasecam will be positioned at. Looking up and down will move the camera + in the opposite direction so that the player stays at approximately the + same height on the screen. Large values of this cvar (either positive or + negative) will produce strange output. +See also: chase, chase_dist + +chasedemo +(cvar: boolean) +default: 0 + If this cvar is true, then demos will automatically start with the + chasecam active. +See also: chase + +chatmacro0 +chatmacro1 +chatmacro2 +chatmacro3 +chatmacro4 +chatmacro5 +chatmacro6 +chatmacro7 +chatmacro8 +chatmacro9 +(cvar: string) + These are all strings programmable to the function keys during a netgame. + To use these, enter chat mode with the messagemode command, and then hold + down Alt and press one of the number keys. The string stored in the + corresponding chatmacro cvar will be sent as if you had typed it yourself. + +cl_bloodtype +(cvar: number) +default: 0 + Controls how blood is drawn. Supported values are: + 0: Blood is drawn as sprites + 1: Blood is drawn as both sprites and particles + 2: Blood is drawn as particles + +cl_pufftype +(cvar: number) +default: 0 + Controls how bullet puffs are drawn. Supported values are: + 0: Puffs are drawn as sprites. + 1: Puffs are drawn as particles. + +cl_rockettrails +(cvar: boolean) +default: 1 + Controls whether or not rockets leave trails of smoke behind them. + +cl_run +(cvar: boolean) +default: 0 + When non-zero, the game will always treat movement commands as if +speed + is active. +See also: +speed + +clear +(command) + Clears the console of all text. + +cmdlist +(command) + Lists all commands currently supported by ZDoom. +See also: cvarlist + +color +(cvar: color) +default: "4040 cfcf 0000" (Mostly green) + This is the color of your player's suit. +See also: gender, name, skin, team + +con_midtime +(cvar: number) +default: 3 + This is the number of seconds that messages in the middle of the screen + will be displayed before they dispapper. +See also: con_notifytime + +con_notifytime +(cvar: number) +default: 3 + This is the number of seconds that new messages will stay at the top of + the screen before they start scrolling away. +See also: con_midtime + +con_scaletext +(cvar: boolean) +default: 0 + If this cvar is true, then message text will be scaled to larger sizes + depending on the screen resolution so that it will stay approximately the + same size it would be on a 320x200 screen. + +configver +(cvar: number) +default: "116" + This cvar is used to keep track of which version of ZDoom was used to write + the current config file and adjust for differences that may have been + introduced between versions. Changing it has no effect, since it will + always be changed to reflect the current game version before the config + file is saved. + +crosshair +(cvar: number) +default: 0 + If this cvar is non-zero, it draws a crosshair. If this cvar is negative, + the crosshair is translucent, otherwise it is opaque. The specific + crosshair drawn depends on the value of this cvar. + +cvarlist +(command) + Lists the values of all currently defined cvars. Each cvar can also be + prefaced by multiple flags. These are: + + A Cvar gets saved in the config file. + U Cvar contains user info. + S Cvar contains server info. + - Cvar can only be changed from the command line. + L Changes to cvar's contents don't take effect until the next game. + C Cvar has an internal callback. + * Cvar was created by the user and is meaningless to the game. + +See also: cmdlist, get, set + +deathmatch +(cvar: boolean) +default: 0 + When true, deathmatch rules are used for the game. + +def_patch +(cvar: string) +default: "" + This is the name of a DeHackEd patch file to automatically apply each time + the game is run. It will only be used if the following conditions are met: + + a) def_patch is not "", and the file exists. + b) No loaded WAD files contain a DEHACKED lump. + c) No patch is specified with the -deh command line parameter. + +developer +(cvar: boolean) +default: 0 + When true, prints various debugging messages to the console. + +dimamount +(cvar: number) +default: 1 + This is the amount of dimcolor to mix with the background when a menu is + displayed. The available values are: + 0: Do not dim the background. + 1: Mix 25% of dimcolor with the background. + 2: Mix 50% of dimcolor with the background. + 3: Mix 75% of dimcolor with the background. +See also: dimcolor + +dimcolor +(cvar: color) +default: "ffff d7d7 0000" (gold) + This is the color to mix with the background when a menu is displayed. +See also: dimamount, setcolor + +dir [[path/][pattern]] +(command) + This command lists the contents of a directory. It supports wildcards (but + will not recurse into multiple directories). If [path] is not specified, + it will display the contents of the directory the game was run from. + +deathmatch +(cvar: boolean) +default: 0 + When set to true, the game is treated as a deathmatch. When the game is + started with -altdeath or -deathmatch, this cvar is automatically set to 1. + +dmflags +(cvar: number) +default: 0 + This cvar controls the behavior of several aspects of gameplay. To + determine what value to store in this cvar, select the desired features + from the table below and add their values together. If a feature is + marked with (DM), then that feature will only be active during a + deathmatch game. + + Value Description + ------ ----------------------------------------------------------------- + 1 Do not spawn health items (DM) + 2 Do not spawn powerups (DM) + 4 Leave weapons around after pickup (DM) + 8 Falling too far hurts + 16 Players cannot hurt teammates (friendly fire avoidance) + 64 Stay on the same map when someone exits (DM) + 128 Spawn players as far as possible from other players (DM) + 256 Automatically respawn dead players (DM) + 512 Do not spawn armor (DM) + 1024 Kill anyone who tries to exit the level (DM) + 2048 Don't use any ammo when firing + 4096 Don't spawn monsters + 8192 Monsters respawn sometime after their death + 16384 Powerups other than invulnerability and invisibilty respawn + 32768 Monsters are fast + 65536 Don't allow jumping + 131072 Don't allow freelook + 262144 Invulnerability and invisibility respawn + +See also: menu_gameplay, teamplay + +doublebind [key [command string]] +(command) + If no parameters are specified, the entire list of doublebound keys will be + printed to the console. If only [key] is specified, the doublebinding for + that specific key will be printed. If both [key] and [command string] are + specified, [command string] will be doublebound to [key]. (Doublebindings + are commands that are executed when a key is pressed twice quickly--such as + double cliking a mouse button.) +See also: bind, unbind, unbindall, undoublebind + +dumpheap +(command) + Prints detailed information about the heap. Probably not very useful to + the average user. +See also: mem + +echo +(command) + Prints to the console. + +endgame +(command) + Ends the current single player game and drops the console down to cover the + screen. +See also: menu_endgame + +error +(command) + Simulates an error by killing the current game and falling back to the + fullscreen console with the specified message. + +exec