Updated WavPack decoder to 5.2.0

CQTexperiment
Christopher Snowhill 2020-03-22 00:15:45 -07:00
parent 3e6d599452
commit 9ca13ad471
42 changed files with 4192 additions and 3043 deletions

View File

@ -1,3 +1,11 @@
David Bryant <david@wavpack.com>
Sebastian Dröge <slomo@circular-chaos.org>
Joachim Henke <j-o@users.sourceforge.net>
Joël R. Langlois <joel.r.langlois@gmail.com>
Alexis Ballier <aballier@gentoo.org>
Stephen <stephengroat@users.noreply.github.com>
Phil Eichinger <phil@zankapfel.net>
Sebastian Ramacher <sramacher@debian.org>
luxagen <hello@luxagen.com>
Martin Koegler <martin.koegler@chello.at>
nu774 <honeycomb77@gmail.com>

View File

@ -1,630 +1,366 @@
-------------------------------
Release 4.80.0 - March 28, 2016
-------------------------------
WavPack Library Source Code - 4.80.0
wavpack.exe (command-line encoder) - 4.80.0
wvunpack.exe (command-line decoder) - 4.80.0
wvgain.exe (command-line ReplayGain scanner) - 4.80.0
-----------------------------------------------------
added: full Unicode support on Windows platform
added: new option --pre-quantize to truncate high-resolution files
to a reasonable depth (e.g., 20-bit) for better compression
fixed: Debian bug #793320 (executable stack)
fixed: LargeAddressAware problem reported on HA
fixed: several "fuzz test" failures reported on GitHub
fixed: repack blocks after possible arithmetic overflows
improved: faster assembly code for mono packing
improved: portability for various platforms
wvtest.exe (command-line libwavpack test suite) - 4.80.0
--------------------------------------------------------
added: exhaustive test for WavpackSeekSample() API
in_wv.dll (winamp plugin) - 2.8.0.1
CoreWavPack DirectShow Filters - 1.3.0.0
AmioWavpack.amio (Adobe Audition Plugins) - 1.5
cool_wv4.flt (CoolEdit / Audition filter) - 2.14
------------------------------------------------
updated: see 4.80.0 library changes
--------------------------------
Release 4.75.2 - October 1, 2015
--------------------------------
WavPack Library Source Code - 4.75.2
------------------------------------
fixed: corrupt mono or multichannel files created with assembly code (rare)
fixed: building on Clang systems like Darwin and FreeBSD (req. Clang 3.5+)
fixed: explicitly sign-extend audio data (< 4-byte) to avoid corrupt files
fixed: rare decoding errors due to integer overflow (ARM assembly code)
added: assembly optimizations for "extra" mode on mono or multichannel
wvtest.exe (command-line libwavpack test suite) - 4.75.2
--------------------------------------------------------
all new program to stress-test libwavpack (requires Pthreads)
wavpack.exe (command-line encoder) - 4.75.2
wvunpack.exe (command-line decoder) - 4.75.2
wvgain.exe (command-line ReplayGain scanner) - 4.75.2
-----------------------------------------------------
fixed: corrupt mono or multichannel files created with assembly code (rare)
added: assembly optimizations for "extra" mode on mono or multichannel
improved: flush stderr after all writes
cool_wv4.flt (CoolEdit / Audition filter) - 2.13
AmioWavpack.amio (Adobe Audition Plugins) - 1.4
------------------------------------------------
fixed: corrupt mono or multichannel files (rare)
-----------------------------
Release 4.75.0 - May 25, 2015
-----------------------------
WavPack Library Source Code - 4.75.0
------------------------------------
improved: reorganization for modularity and to improve linking
added: assembly optimizations for encode/decode on x86 and x64
added: assembly optimizations for decoding on ARMv7 (Linux)
improved: several minor speed optimizations using intrinsics
fixed: wavpack.pc.in not working correctly on some Linux distros
fixed: memcpy() issue causing abort() on OpenBSD
wavpack.exe (command-line encoder) - 4.75.0
wvunpack.exe (command-line decoder) - 4.75.0
wvgain.exe (command-line ReplayGain scanner) - 4.75.0
-----------------------------------------------------
changed: writing to console title default is off (Linux only, -z1 to enable)
fixed: wvgain crashes on bad file arguments (Debian bug #716478)
cool_wv4.flt (CoolEdit / Audition filter) - 2.12
------------------------------------------------
improved: performance (from assembly optimizations)
-------------------------
Update - December 7, 2013
-------------------------
CoreWavPack DirectShow Filters - 1.2.0.2
----------------------------------------
imported: latest filter sources from Christophe Paris and CoreCodec
updated: port to VS 2008 and add 64-bit build platform with installer
added: decode streams with full headers (tested with LAV splitter)
fixed: issues with 7.1 and non-standard channel configurations
fixed: problems with 12-bit, 20-bit, and 32-bit integer audio
fixed: crashing bug related to hybrid files with DNS
fixed: custom sampling rates being ignored
---------------------------------
Release 4.70.0 - October 19, 2013
---------------------------------
wavpack.exe (command-line encoder) - 4.70.0
-------------------------------------------
added: transcoding from existing WavPack files (with tag copy)
added: option to verify WavPack file integrity on creation (-v)
added: use temporary files for safer overwriting
added: detect UTF-16LE encoding for tag text files (mostly a Windows thing)
added: --version command to write machine-parsable value
added: option to allow up to 16 MB APEv2 tag data (--allow-huge-tags)
added: allow channel-order specification on WAV files with zeroed channel mask
added: several Windows features to Linux (clean ^C handling, console title)
added: 4GB file support on 32-bit Linux targets
WavPack Library Source Code - 4.70.0
------------------------------------
fixed: seeking to last block failure (after finishing file)
fixed: memcpy() not always used correctly (Linux targets)
fixed: unsigned char issue (ARM targets)
fixed: add binary tag functions to Windows DLL exports (forgot on 4.60)
added: read-only access to APEv2 tags that come at the beginning of files
improved: switched to Microsoft Visual Studio 2008 (win32 only)
wvunpack.exe (command-line decoder) - 4.70.0
--------------------------------------------
added: use temporary files for safer overwriting
added: --version command to write machine-parsable value
added: new command (-f) for getting machine-parsable WavPack file info
added: option (-n) to suppress audio decoding (useful for extracting only tags)
wvgain.exe (command-line ReplayGain scanner) - 4.70.0
-----------------------------------------------------
fixed: the -q (quiet) option would cause the -c (clean) option to fail
added: version command (-v) to write machine-parsable value
in_wv.dll (winamp plugin) - 2.8
-------------------------------
fixed: settings could not be saved on newer Windows versions (7 & 8)
fixed: installation issue caused by including manifest in build
added: dialog to installer suggesting "Winamp Essentials Pack"
AmioWavpack.amio (Adobe Audition Plugin) - 1.0
----------------------------------------------
all new plugin for Audition 4.0 (CS5.5) and later (including Audition CC)
--------------------------
Update - December 23, 2009
--------------------------
in_wv.dll (winamp plugin) - 2.8a
--------------------------------
fixed: crashes in winamp 5.57 when playing tracks that have "genre" tag
----------------------------------
Release 4.60.1 - November 29, 2009
----------------------------------
WavPack Library Source Code - 4.60.1
------------------------------------
fixed: filename specs in tag extractions failed in batch operations
fixed: prevent creation of APEv2 tags > 1 MB (which we can't read)
fixed: crash when decoding old WavPack files (pre version 4.0)
added: man pages to build system and updated with newer options
added: versioning info to Windows DLL
improved: build compatibility (eliminated uchar, ushort types)
wavpack.exe (command-line encoder) - 4.60.1
-------------------------------------------
fixed: don't allow user to attempt to place over 1 MB into APEv2 tags
in_wv.dll (winamp plugin) - 2.7
-------------------------------
added: read-only support for displaying cover art (thanks Benski!)
wvunpack.exe (command-line decoder) - 4.60.1
wvgain.exe (command-line ReplayGain scanner) - 4.60.1
cool_wv4.flt (CoolEdit / Audition filter) - 2.11
-----------------------------------------------------
(see library changes)
---------------------------------
Release 4.60 - September 27, 2009
---------------------------------
WavPack Library Source Code - 4.60
----------------------------------
added: API for reading & writing binary fields in APEv2 tags
fixed: recognize APEv2 tags with footers but no headers
fixed: playback of files with 8 streams (15-16 channels)
fixed: playback and seeking failed on certain rare correction files
fixed: handle case where library makes RIFF header but app adds RIFF trailer
improved: channel count limit now virtually unlimited (tested to 256)
improved: move all tag functions into new module (tags.c)
wavpack.exe (command-line encoder) - 4.60
-----------------------------------------
added: --write-binary-tag command for embedded cover art
added: --no-utf8-convert command to skip Unicode character conversions
added: --raw-pcm command to specify raw PCM data (samplerate, bitdepth, num chans)
added: --channel-order accepts "..." to specify unassigned channels
added: --pair-unassigned-chans command to put unassigned channels into stereo pairs
wvunpack.exe (command-line decoder) - 4.60
------------------------------------------
added: -x (and -xx) commands for extracting arbitrary tag fields to stdout (and files)
added: --no-utf8-convert command to skip Unicode character conversions
changed: -ss command no longer dumps multiline tags (use -x instead)
improved: formatting of -ss command, also shows information on binary tags
wvgain.exe (command-line ReplayGain scanner) - 4.60
---------------------------------------------------
added: -n option for processing new files only (those without ReplayGain info)
improved: increase maximum gain value generated from +24 to +64 dB
in_wv.dll (winamp plugin) - 2.6
cool_wv4.flt (CoolEdit / Audition filter) - 2.10
------------------------------------------------
(see library changes)
-------------------------
Update - January 23, 2009
-------------------------
in_wv.dll (winamp plugin) - 2.6b
--------------------------------
added: "lossless" and "category" to metadata keywords that we handle in winamp plugin
added: internationalization support to facilitate inclusion in Winamp Essentials Pack
-----------------------------
Release 4.50.1 - July 3, 2008
-----------------------------
WavPack Library Source Code - 4.50.1
------------------------------------
fixed: alignment fault when manipulating APEv2 tags (non-x86 only)
fixed: build on UNIX via elimination of non-standard strnlen()
wavpack.exe (command-line encoder) - 4.50.1
wvunpack.exe (command-line decoder) - 4.50.1
--------------------------------------------
fixed: checking return value of iconv_open() prevents core dump on Solaris
----------------------------
Release 4.50 - June 13, 2008
----------------------------
WavPack Library Source Code - 4.50
----------------------------------
added: dynamic noise shaping for improved hybrid quality
added: option to merge blocks of similar redundancy
added: ability to store and retrieve extra mode level
fixed: alignment fault on some big-endian machines
fixed: compiling with enable-mmx on gcc 4.3.x (thanks Joachim)
improved: allow bitrate to be calculated for files down to 1/10 second
improved: decoding of corrupt files (prevents heap overrun crashes)
wavpack.exe (command-line encoder) - 4.50
-----------------------------------------
added: dynamic noise shaping for improved hybrid quality
added: --channel-order option to reorder nonconforming multichannel files
added: --merge-blocks option to optimize storage of LossyWAV output files
added: ignore -o on Windows for compatibility with Linux version
fixed: alignment fault on some big-endian machines
improved: reformatted and expanded --help display
wvunpack.exe (command-line decoder) - 4.50
------------------------------------------
fixed: don't ignore fractions of seconds in --skip option
added: show extra level and dns status for newer files (-s command)
added: ignore -o on Windows for compatibility with Linux version
improved: decoding of corrupt files (prevents heap overrun crashes)
improved: display bitrate for files down to 1/10 second
in_wv.dll (winamp plugin) - 2.5
-------------------------------
added: transcoding API (allows CD burning, format conversion, ReplayGain calc, etc.)
added: metadata writing API (for Auto-Tag, etc.)
added: full Unicode support for info box (older Winamps) and media library
added: standard Winamp metadata display & edit for newer Winamps
added: option to pass multichannel audio
added: option to pass all audio as 16-bit (for better compatibility)
added: option to output 24-bit audio when ReplayGain is active
added: genre display to info box (older Winamps)
fixed: seek bar sometimes vacillates when moved
fixed: crash when winamp is opened with files in playlist moved or deleted
improved: hi-res audio now output as 24-bit (not 32-bit) for better compatibility (EQ, etc.)
improved: performance of adding tracks to library, especially from network drives
improved: decoding of corrupt files (prevents heap overrun crashes)
cool_wv4.flt (CoolEdit / Audition filter) - 2.9
-----------------------------------------------
added: about box
added: dynamic noise shaping for improved hybrid quality
improved: display bitrate for files as short as 1/10 second
improved: decoding of corrupt files (prevents heap overrun crashes)
improved: replace "extra processing" switch with a slider (0-6)
--------------------------
Release 4.41 - May 6, 2007
--------------------------
WavPack Library Source Code - 4.41
----------------------------------
added: create wavpackdll.dll for Windows (not used yet)
fixed: corrupt floating-point audio on big-endian machines
fixed: put MSVC projects in their own subdir (fixed build problems)
fixed: limit RIFF data buffering to 16 MB to prevent out-of-memory crash
improved: attempt to mute errors when decoding corrupt legacy WavPack files
improved: overall performance enhancements of 10% to 30% (depending on mode)
added: MMX intrinsics for 24-bit (and higher) stereo encoding (thanks to
Joachim Henke)
wavpack.exe (command-line encoder) - 4.41
-----------------------------------------
fixed: corrupt floating-point audio on big-endian machines
improved: refuse to encode WAV files over 4 GB or with over 16 MB RIFF data
improved: overall performance enhancements of 10% to 30% (depending on mode)
added: MMX intrinsics for 24-bit (and higher) stereo encoding (thanks to
Joachim Henke)
wvunpack.exe (command-line decoder) - 4.41
------------------------------------------
fixed: corrupt floating-point audio on big-endian machines
fixed: restore files mistakenly encoded with huge RIFF chunks
improved: attempt to mute errors when decoding corrupt legacy WavPack files
improved: overall performance enhancements of 10% to 30% (depending on mode)
added: --skip and --until commands to unpack specified range of audio data
added: MMX intrinsics for 24-bit (and higher) stereo encoding (thanks to
Joachim Henke)
wvgain.exe (command-line ReplayGain scanner) - 4.41
---------------------------------------------------
improved: overall performance enhancements of 10% to 30% (depending on mode)
added: MMX intrinsics for 24-bit (and higher) stereo encoding (thanks to
Joachim Henke)
cool_wv4.flt (CoolEdit / Audition filter) - 2.8
-----------------------------------------------
fixed: read all RIFF metadata from files created in other applications
improved: attempt to mute errors when decoding corrupt legacy WavPack files
improved: overall performance enhancements of 10% to 30% (depending on mode)
added: MMX intrinsics for 24-bit (and higher) stereo encoding (thanks to
Joachim Henke)
-------------------------------
Release 4.40 - December 3, 2006
-------------------------------
WavPack Library Source Code - 4.40
----------------------------------
added: new hardware-friendly "high" mode that compresses almost as well as
old "high" mode but decodes significantly faster; old "high" mode
now available as "very high"
added: option added to improve compression of mono material in stereo files
(requires at least version 4.3 decoder)
added: function to obtain channel mapping information on decoding
added: function to get trailing wrapper info (RIFF) without decoding file
improved: "extra" mode levels 1-3 completely revamped, fast enough for use
improved: reorganized to create a standard library that should more easily
integrate into other applications; eliminated namespace issues
improved: more robust handling of corrupt files
wavpack.exe (command-line encoder) - 4.40
-----------------------------------------
added: accepts long option names including --help for full usage info
added: new hardware-friendly "high" mode that compresses almost as well as
old "high" mode but decodes significantly faster; old "high" mode
now available as "very high" (-hh)
added: --optimize-mono option added to improve compression of mono material
in stereo files (requires at least version 4.3 decoder)
improved: "extra" mode levels 1-3 completely revamped, fast enough for use
improved: switched to Microsoft Visual Studio 2005 (win32 only)
removed: support for Windows 95
wvunpack.exe (command-line decoder) - 4.40
------------------------------------------
added: cuesheet extraction (to .cue file or stdout)
added: wav header generation on decode for files with missing RIFF
information, or forced with -w option
added: more summary info (wrapper info + channel assignments)
improved: more robust handling of corrupt files
improved: separate options for raw (-r) and blind stream decoding (-b)
improved: switched to Microsoft Visual Studio 2005 (win32 only)
removed: support for Windows 95
wvgain.exe (command-line ReplayGain scanner) - 4.40
---------------------------------------------------
improved: switched to Microsoft Visual Studio 2005 (win32 only)
removed: support for Windows 95
wvselfx.exe (self-extraction stub) - 4.40
------------------------------------------
added: automatic cuesheet extraction (if present in APEv2 tag)
in_wv.dll (winamp plugin) - 2.4
-------------------------------
fixed: quietly skips deleted files in playlist
improved: more robust handling of corrupt files
improved: APEv2 tags are read even if followed by ID3v1 tag
cool_wv4.flt (CoolEdit / Audition filter) - 2.7
-----------------------------------------------
added: new hardware-friendly "high" mode that compresses almost as well as
old "high" mode but decodes significantly faster; old "high" mode
now available as "v. high"
improved: more robust handling of corrupt files
----------------------
Update - April 5, 2006
----------------------
WavPack Library Source Code - 4.32
wavpack.exe (command-line encoder) - 4.32
-----------------------------------------
fixed: generating RIFF headers on big-endian machines caused crash
--------------------------
Update - December 10, 2005
--------------------------
wavpack.exe (command-line encoder) - 4.31
wvunpack.exe (command-line decoder) - 4.31
------------------------------------------
fixed: detect debug mode in all cases (win32 only)
improved: use latest service pack and SDK for building (win32 only)
improved: better directory choice for logging file (win32 only)
improved: allow shell to expand wildcards (*nix only)
added: option (-o) to specify output directory or path (*nix only)
added: option (-t) to copy timestamp (*nix only)
wvgain.exe (command-line ReplayGain scanner) - 4.31
---------------------------------------------------
new
WavPack Library Source Code - 4.31
----------------------------------
fixed: failing seek with some files that had been played to the end
fixed: small memory leak when opening hybrid lossless files
improved: signed characters no longer must be default
improved: APEv2 tags are read even if followed by ID3v1 tag
improved: limited APEv2 tag editing capability
------------------------------
Release 4.3 - November 1, 2005
------------------------------
wavpack.exe (command-line encoder) - 4.3
----------------------------------------
fixed: bug causing termination error with very wide screen widths
added: command-line option (-l) to use low priority for batch operation
added: command-line option (-r) to generate a fresh RIFF header
added: debug mode (rename to wavpack_debug.exe)
added: automatically detect lower resolution data even without -x1
added: src and dst dirs are searched also for tag source files (handy for EAC)
added: wildcard accepted for tag source files (handy for EAC)
added: handle non-standard sampling rates
improved: returns error status for any error
improved: use longer blocks in multichannel files (better "high" compression)
wvunpack.exe (command-line decoder) - 4.3
-----------------------------------------
fixed: very rare decoding bug causing overflow with hi-res files
fixed: bug causing termination error with very wide screen widths
fixed: formatting error in duration display
added: command-line option (-ss) to include tags in summary dump
added: command-line option (-l) to use low priority for batch operation
added: debug mode (rename to wvunpack_debug.exe)
improved: returns error status for any error
improved: more robust decoding of damaged (or invalid) files
in_wv.dll (winamp plugin) - 2.3
nxWavPack.dll (Nero plugin) - 1.2
WavPack_Apollo.dll (Apollo plugin) - 1.3
cool_wv4.flt (CoolEdit / Audition filter) - 2.6
-----------------------------------------------
fixed: very rare decoding bug causing overflow with hi-res files
improved: handle ID3v1.1 tags (now includes track number)
improved: more robust decoding of damaged (or invalid) files
added: handle non-standard sampling rates
foo_wavpack.dll (foobar plugin) - 2.3
-----------------------------------------------
fixed: any error during WavPack file open caused crash if wvc file present
fixed: very rare decoding bug causing overflow with hi-res files
improved: more robust decoding of damaged (or invalid) files
added: handle non-standard sampling rates
WavPack Library Source Code - 4.3
---------------------------------
fixed: very rare decoding bug causing overflow with hi-res files
added: automatic generation of RIFF wav header during encoding
added: new functions to access tags by index (instead of item name)
added: automatically detect lower resolution data during encoding
added: handle non-standard sampling rates
improved: more robust decoding of damaged (or invalid) files
improved: use longer blocks in multichannel files (better "high" compression)
improved: two structures renamed to avoid namespace conflict
removed: legacy code for Borland compiler
--------------------------
Update - September 1, 2005
--------------------------
wavpack.exe (command-line encoder) - 4.22
cool_wv4.flt (CoolEdit / Audition filter) - 2.5
-----------------------------------------------
fixed: possible corrupt files written (24 or 32-bit + "extra" mode)
---------------------------
Release 4.2 - April 2, 2005
---------------------------
wavpack.exe (command-line encoder) - 4.2
----------------------------------------
fixed: handling of wav files larger than 2 gig
improved: stereo lossless encoding speed (including "extra" mode)
added: -i option to ignore length specified in wav header
added: -w option to write APEv2 tags directly from command line
wvunpack.exe (command-line decoder) - 4.2
-----------------------------------------
improved: decoding speed
in_wv.dll (winamp plugin) - 2.2
-------------------------------
added: winamp media library support
improved: decoding speed
foo_wavpack.dll (foobar plugin) - 2.2
-------------------------------------
improved: decoding speed
nxWavPack.dll (Nero plugin) - 1.1
Cool_wv4.flt (CoolEdit / Audition filter) - 2.4
-----------------------------------------------
fixed: handling of wav files larger than 2 gig
improved: encoding and decoding speed
WavPack Library Source Code - 4.2
---------------------------------
improved: encoding and decoding speed
fixed: works correctly with 64-bit compilers
added: mode bit to open files in "streaming" mode
--------------------------
Update - December 12, 2004
--------------------------
WavPack_Apollo.dll (Apollo plugin) - 1.2
----------------------------------------
fixed: crash when Apollo opened and WavPack plugin can't find config file
--------------------------------
Release 4.1 - September 14, 2004
--------------------------------
wavpack.exe (command-line encoder) - 4.1
----------------------------------------
fixed: hybrid mode + "extra" mode + very low bitrates making corrupt files
fixed: mono or multichannel files causing crash (no corruption possible)
added: third name specification for "correction" file (EAC specific)
added: -t option to preserve timestamps
added: error summary for batch mode
wvunpack.exe (command-line decoder) - 4.1
-----------------------------------------
fixed: hybrid mode decoding bugs (very obscure situations)
added: -s option to dump file summary to stdout
added: -t option to preserve timestamps
added: error summary for batch mode
wvselfx.exe (self-extraction stub) - 4.1
----------------------------------------
fixed: hybrid mode decoding bugs (very obscure situations)
in_wv.dll (winamp plugin) - 2.1
-------------------------------
fixed: international characters in tags display properly (UTF-8 to Ansi)
added: maximum tag data field width changed from 64 chars to 128 chars
added: new infobox items including encoder version & modes, track #, md5
foo_wavpack.dll (foobar plugin) - 2.1
-------------------------------------
added: new database items including encoder version & modes and md5
WavPack_Apollo.dll (Apollo plugin) - 1.1
----------------------------------------
fixed: international characters in tags display properly (UTF-8 to Ansi)
Cool_wv4.flt (CoolEdit / Audition filter) - 2.2
-----------------------------------------------
fixed: hybrid mode + "extra" mode + very low bitrates making corrupt files
fixed: saving mono file causing crash (no corruption possible)
fixed: hybrid mode decoding bugs (very obscure situations)
fixed: partial saves (with "Cancel") have incorrect RIFF header if unpacked
nxWavPack.dll (Nero plugin) - 1.0
---------------------------------
new
WavPack Library Source Code - 4.1
---------------------------------
fixed: hybrid mode + "extra" mode + very low bitrates making corrupt files
fixed: mono or multichannel files causing crash (no corruption possible)
fixed: hybrid mode decoding bugs (very obscure situations)
added: mode bits for determining additional encode info (extra, sfx)
added: function to return total compressed file length (including wvc)
added: function to return encoder version (1, 2, 3, or 4)
added: ability to obtain MD5 sum before decoding file (requires seek to end)
added: mode bit for determining tag type (for proper character translation)
added: ability to encode WavPack files without knowing length in advance
added: option for small "information only" version of library
2019-12-14 David Bryant <david@wavpack.com>
* cli/wvunpack.c
-s option: add "5.1 surround side" and "7.1 surround" to reported channel configurations
2019-12-13 David Bryant <david@wavpack.com>
* cli/riff[_write].c, cli/wave64[_write].c, cli/caff[_write].c, cli/dsf[_write].c, cli/dsdiff[_write].c:
split header readers & writers so that wvunpack doesn't link libwavpack encoder
2019-12-12 David Bryant <david@wavpack.com>
* cli/riff.c, cli/wave64.c, cli/caff.c:
-i option: display warning when dropping PCM samples from end of file
2019-12-11 David Bryant <david@wavpack.com>
* cli/wavpack.c:
fix a WAV header if user specified -i (to ignore length) and we can make it valid
2019-12-08 David Bryant <david@wavpack.com>
* fuzzing/fuzzer.cc, fuzzing/fuzzer_seed_corpus.zip, etc...:
add fuzzing directory with corpus and other files for oss-fuzz
2019-12-08 David Bryant <david@wavpack.com>
* src/open_utils.c:
fix possible memory leak on opening corrupted files
2019-12-08 David Bryant <david@wavpack.com>
* src/common_utils.c, src/pack_dsd.c, src/unpack_dsd.c, src/wavpack_local.h:
- fix potential memory leak when seeking in DSD files
- simplify DSD fast mode lookup buffer allocations
2019-12-08 David Bryant <david@wavpack.com>
* src/unpack.c, src/unpack_dsd.c, src/unpack_seek.c:
seeking fixes:
- fix crash during seek to corrupted block
- check header size before malloc()
- fix overlapping memcpy()
2019-11-30 David Bryant <david@wavpack.com>
* src/pack.c:
- provide more configuration sanity checks to aid application debugging
- force max_blocksize even so bitstream buffer overflow detection works
2019-04-09 David Bryant <david@wavpack.com>
* cli/import_id3.c:
issue #69: add TPUB (Publisher) to accepted ID3v2 tag fields
2019-03-05 David Bryant <david@wavpack.com>
* cli/wave64.c:
issue #68: clear WaveHeader at start to prevent uninitialized read
2019-03-05 David Bryant <david@wavpack.com>
* cli/dsdiff.c:
issue #67: make sure sample rate is specified and non-zero in DFF files
2019-03-04 David Bryant <david@wavpack.com>
* cli/caff.c:
issue #66: make sure CAF files have a "desc" chunk
2019-03-02 David Bryant <david@wavpack.com>
* cli/dsdiff.c:
issue #65: makre sure DSDIFF files have a valid channel count
2018-12-23 evpobr <evpobr@gmail.com>
* include/wavpack.h src/wavpack_local.h:
remove duplication so that wavpack_local.h can include wavpack.h
2018-12-16 evpobr <evpobr@gmail.com>
* Makefile.am, CMakeLists.txt
add CMake project
2018-12-09 orbea <orbea@fredslev.dk>
* cli/Makefile.am:
fix command-line builds with slibtool
2018-12-08 Ørjan Malde <foxyred333@gmail.com>
* src/extra[12].c, src/pack.c, src/pack_x64.S, src/unpack.c, src/unpack_x64.S, src/wavpack_local.h:
x64 ASM support for midipix
2018-11-29 David Bryant <david@wavpack.com>
* src/pack_utils.c:
issue #53: error on zero sample rate
- CVE-2018-19840
2018-11-29 David Bryant <david@wavpack.com>
* src/open_utils.c:
issue #54: fix potential out-of-bounds heap read
- CVE-2018-19841
2018-11-29 David Bryant <david@wavpack.com>
* src/open_filename.c:
Windows only: use wvc file when verifying encode when source is stdin
2018-09-03 Mike Tzou <Chocobo1@users.noreply.github.com>
* cli/import_id3.c, cli/wvgain.c, cli/open_raw.c, cli/wvparser.c, cli/wvunpack.c, winamp/in_wv.c:
printf() format specifiers
memory leaks
2018-08-26 David Bryant <david@wavpack.com>
* cli/dsdiff.c, cli/dsf.c, cli/caff.c:
issue #41 issue #42 issue #43: sanitize input files to prevent crashes
2018-06-02 David Bryant <david@wavpack.com>
* src/unpack_armv7.S:
fix thumb interworking on ARM by adding .type for assembly functions
2018-04-30 David Bryant <david@wavpack.com>
* cli/import_id3.c, cli/wavpack.c:
allow ID3v2.3 tag import from any file type (not just DSF)
2018-04-29 David Bryant <david@wavpack.com>
* cli/import_id3.c:
handle ID3v2.3 TXXX tags using description for APEv2 item name (w/ case formatting)
2018-04-24 David Bryant <david@wavpack.com>
* cli/riff.c, cli/wave64.c:
issue #30 issue #31 issue #32: no multiple format chunks in WAV or W64
- CVE-2018-10536
- CVE-2018-10537
* cli/dsdiff.c, cli/riff.c, cli/wave64.c:
issue #33, sanitize size of unknown chunks before malloc()
- CVE-2018-10538
- CVE-2018-10539
- CVE-2018-10540
2018-04-17 David Bryant <david@wavpack.com>
* cli/import_id3.c:
add a bunch more ID3v2.3 tag entries
make ImportID3v2() more robust (e.g. always set bytes_used)
2018-04-08 David Bryant <david@wavpack.com>
* src/common_utils.c:
fix memory leaks
2018-02-11 David Bryant <david@wavpack.com>
* cli/caff.c:
issue #26, fix buffer overflows and bad allocs on corrupt CAF files
- CVE-2018-7254
2018-02-10 David Bryant <david@wavpack.com>
* cli/dsdiff.c:
issue #28, do not overwrite heap on corrupt DSDIFF file
- CVE-2018-7253
2018-02-04 David Bryant <david@wavpack.com>
* cli/riff.c:
issue #27, do not overwrite stack on corrupt RF64 file
- CVE-2018-6767
2017-10-29 David Bryant <david@wavpack.com>
* src/read_words.c:
issue #24, another C++ compiler fix, this time for _BitScanForward()
2017-10-28 David Bryant <david@wavpack.com>
* Makefile.am:
add README.md to extra distribution files
2017-10-20 Joël R. Langlois <joel.r.langlois@gmail.com>
* README, README.md:
Updated README to Markdown format.
2017-10-12 Joël R. Langlois <joel.r.langlois@gmail.com>
* src/decorr_utils.c, src/entropy_utils.c, src/open_legacy.c,
src/open_utils.c, src/tag_utils.c, src/tags.c, src/unpack3.c,
src/unpack3_open.c, src/unpack_dsd.c, src/unpack_seek.c,
src/unpack_utils.c:
Fixed errors when compiling using a C++ compiler.
2017-09-30 David Bryant <david@wavpack.com>
* cli/import_id3.c:
experimental fix to handle ID3v2.3 tags that [incorrectly] use synchsafe for the frame size
2017-08-31 David Bryant <david@wavpack.com>
* cli/wavpack.c
briefly describe other utilities in help displays for wavpack
2017-07-24 David Bryant <david@wavpack.com>
* cli/md5.h
do not try to use libcrypto on OS X
2017-07-23 David Bryant <david@wavpack.com>
* cli/md5.c, cli/md5.h, cli/wavpack.c, cli/wvtest.c, cli/wvunpack.c, configure.ac:
use Alexander Peslyak's MD5 implementation (or libcrypto if present) to fix
unaligned access coredump on OpenBSD/sparc64 (reported on openbsd-ports)
2017-03-19 David Bryant <david@wavpack.com>
* src/write_words.c:
improve quality of scan_word() results on very short blocks (via multiple passes)
2017-03-01 David Bryant <david@wavpack.com>
* cli/wavpack.c, cli/wvgain.c, cli/wvtag.c, cli/wvunpack.c:
add required parens to correct precedence error/warning
2017-02-26 David Bryant <david@wavpack.com>
* cli/wavpack.c, cli/wvgain.c, cli/wvtag.c, cli/wvunpack.c:
refactor debug logging mode so that we can turn on a forced arg dump
* src/common_utils.c, src/wavpack_local.h:
provide for a "close" callback to be installed for dumping accumulated statistics
* configure.ac, src/unpack_armv7.S:
SSAT instruction required armv6, now we should work on all ARMs using a pair of shifts instead
2017-02-18 Alexis Ballier <aballier@gentoo.org>
* configure.ac:
configure: Restrict arm assembly to armv7 only.
ARM assembly in wavpack is armv7 only it seems.
I have reports this causes build failures on armv5: https://bugs.gentoo.org/show_bug.cgi?id=609168
2017-02-16 David Bryant <david@wavpack.com>
* cli/import_id3.c, cli/wvtag.c:
fix GitHub issue #19 (new dependency on wchar_t) by removing dependency
2017-01-22 David Bryant <david@wavpack.com>
* .travis.yml:
do more exhaustive testing for Travis (but should be faster)
2017-01-22 Stephen <stephengroat@users.noreply.github.com>
* .travis.yml:
enable travis ci build and testing (#17)
Create .travis.yml
fix for running tests
limit to smaller test suite
add quotes to get spaces in arg
remove linux clang builds
move to trusty for clang
2017-01-18 David Bryant <david@wavpack.com>
* ChangeLog:
refine change log and add updated plugins
* audition/cool_wv4.c, audition/readme.odt, audition/readme.pdf:
update Cool Edit / Audition filter to 3.1
* COPYING, license.txt, winamp/in_wv.c, winamp/installer/WavPackPlugin1.nsi:
update winamp to 2.8.0.3 and license dates
2017-01-17 David Bryant <david@wavpack.com>
* ChangeLog:
first pass at 5.1.0 changelog
* cli/Makefile.am, cli/import_id3.c, cli/wavpack.c:
fix Darwin build (iconv) and ptr warnings
improve --import-id3 console messaging
2017-01-16 David Bryant <david@wavpack.com>
* wavpackdll/wavpackdll.rc, wavpackexe/wavpack.vcproj, winamp/in_wv.c:
bump DLL version and fix MSVC build
* cli/utils.h, cli/wavpack.c, cli/wvgain.c, cli/wvtag.c, cli/wvunpack.c,
configure.ac, src/wavpack_version.h:
update version to 5.1.0 and bump some copyright dates
* src/pack.c:
do not write data in NEW_CONFIG_BLOCK for "do not care" bits in qmode
* src/unpack_dsd.c:
shorter DSD decimation filter with less HF rolloff and lower CPU use
2017-01-15 David Bryant <david@wavpack.com>
* doc/wavpack_doc.html:
update user manual for 5.1.0 and wvtag
2017-01-14 David Bryant <david@wavpack.com>
* cli/wvtag.c:
allow multiple files on Windows, update "help"
* man/Makefile.am, man/wavpack.1, man/wavpack.xml, man/wvgain.1, man/wvgain.xml,
man/wvtag.1, man/wvtag.xml, man/wvunpack.1, man/wvunpack.xml:
add man page for wvtag and update the other man pages (--import-id3)
2017-01-13 David Bryant <david@wavpack.com>
* cli/Makefile.am, cli/wavpack.c:
add --import-id3 option to wavpack executable
(works with original DSF files and when transcoding)
* cli/import_id3.c, cli/wvtag.c:
refactor ID3 import code to calculate the total number of bytes being imported
- allow total size and item count to be returned even on dry runs
- plug a memory leak in the dry run
2017-01-11 David Bryant <david@wavpack.com>
* src/pack.c, src/unpack.c:
fix issue where noise-shaping falsely triggers lossy muting
- only in very rare cases (detected with pathological testing)
- also fix (again) macro that disables lossy muting
2017-01-08 David Bryant <david@wavpack.com>
* src/pack_utils.c:
fix regression causing non-byte-aligned audio (e.g., 12-bit)
to lose the actual reduced bit-depth indication (although
there was no effect on integrity or compression ratio)
2017-01-07 David Bryant <david@wavpack.com>
* cli/import_id3.c, cli/wvtag.c, wavpack.sln, wvtagexe/wvtag.vcproj:
add wvtag to MSVC build and fix warnings (and one mistake)
* src/open_filename.c:
fix MSVC build (broken by portability enhancements...sigh)
2017-01-06 David Bryant <david@wavpack.com>
* cli/Makefile.am, cli/import_id3.c, cli/wvtag.c:
new cli tool "wvtag" to manipulate APEv2 tags on existing WavPack files
(includes new facility to import ID3v2.3 tag items from Sony DSF files)
* cli/wavpack.c:
add --pre-quantize-round to settings tag
* cli/wvgain.c, cli/wvunpack.c:
copy TextToUTF8() BOM fix into other modules that use it for filename lists

View File

@ -0,0 +1,717 @@
---------------------------------
Release 5.2.0 - December 15, 2019
---------------------------------
WavPack Library Source Code - 5.2.0
wavpack.exe (command-line encoder) - 5.2.0
wvunpack.exe (command-line decoder) - 5.2.0
wvgain.exe (command-line ReplayGain scanner) - 5.2.0
wvtag.exe (command-line tagging utility) - 5.2.0
----------------------------------------------------
fixed: potential security issues including the following CVEs:
CVE-2018-19840 CVE-2018-19841 CVE-2018-10536
CVE-2018-10537 CVE-2018-10538 CVE-2018-10539
CVE-2018-10540 CVE-2018-7254 CVE-2018-7253
CVE-2018-6767
added: support for CMake, Travis CI, and Google's OSS-fuzz
fixed: use correction file for encode verify (pipe input, Windows)
fixed: correct WAV header with actual length (pipe input, -i option)
fixed: thumb interworking and not needing v6 architecture (ARM asm)
added: handle more ID3v2.3 tag items and from all file types
fixed: coredump on Sparc64 (changed MD5 implementation)
fixed: handle invalid ID3v2.3 tags from sacd-ripper
fixed: several corner-case memory leaks
--------------------------------
Release 5.1.0 - January 18, 2017
--------------------------------
WavPack Library Source Code - 5.1.0
wavpack.exe (command-line encoder) - 5.1.0
wvunpack.exe (command-line decoder) - 5.1.0
wvgain.exe (command-line ReplayGain scanner) - 5.1.0
wvtag.exe (command-line tagging utility) - 5.1.0
----------------------------------------------------
added: all new command-line tagging utility (wvtag)
added: option to import ID3v2.3 tags from Sony DSF files
fixed: fuzz test failures from AFL reported on SourceForge
improved: DSD decimation filter (less HF rolloff & CPU use)
fixed: non-byte audio depths (12-bit, 20-bit) not showing
fixed: rare case of noise-shaping triggering a lossy mute
fixed: recognize UTF-8 BOM when reading text files
fixed: a few portability issues
in_wv.dll (winamp plugin) - 2.8.0.3
CoreWavPack DirectShow Filters - 1.5.1.0
AmioWavpack.amio (Adobe Audition Plugins) - 2.1
cool_wv4.flt (Cool Edit / Audition filter) - 3.1
------------------------------------------------
updated: see 5.1.0 library changes
--------------------------------
Release 5.0.0 - December 6, 2016
--------------------------------
WavPack Library Source Code - 5.0.0
wavpack.exe (command-line encoder) - 5.0.0
wvunpack.exe (command-line decoder) - 5.0.0
wvgain.exe (command-line ReplayGain scanner) - 5.0.0
----------------------------------------------------
added: multiple input formats, including RF64, Wave64, and CAF
added: lossless DSD audio in Philips DSDIFF and Sony DSF files
fixed: seeking in > 2GB WavPack files (new stream reader)
fixed: accept > 4GB source audio files (all formats)
improved: increase maximum samples from 2^32 to 2^40
added: block checksums for robustness to corruption
added: support for non-standard channel identities
removed: support for legacy WavPack files (< 4.0)
added: block decoder for streaming applications
fixed: many small fixes and improvements
added: all new pdf documentation
AmioWavpack.amio (Adobe Audition Plugins) - 2.0
-----------------------------------------------
improved: all new dialog for WavPack settings
fixed: handle unlimited audio file size
fixed: save all Amio channel identities
added: save/restore APEv2 tags
in_wv.dll (winamp plugin) - 2.8.0.2
CoreWavPack DirectShow Filters - 1.5.0.0
cool_wv4.flt (Cool Edit / Audition filter) - 3.0
------------------------------------------------
updated: see 5.0.0 library changes
-------------------------------
Release 4.80.0 - March 28, 2016
-------------------------------
WavPack Library Source Code - 4.80.0
wavpack.exe (command-line encoder) - 4.80.0
wvunpack.exe (command-line decoder) - 4.80.0
wvgain.exe (command-line ReplayGain scanner) - 4.80.0
-----------------------------------------------------
added: full Unicode support on Windows platform
added: new option --pre-quantize to truncate high-resolution files
to a reasonable depth (e.g., 20-bit) for better compression
fixed: Debian bug #793320 (executable stack)
fixed: LargeAddressAware problem reported on HA
fixed: several "fuzz test" failures reported on GitHub
fixed: repack blocks after possible arithmetic overflows
improved: faster assembly code for mono packing
improved: portability for various platforms
wvtest.exe (command-line libwavpack test suite) - 4.80.0
--------------------------------------------------------
added: exhaustive test for WavpackSeekSample() API
in_wv.dll (winamp plugin) - 2.8.0.1
CoreWavPack DirectShow Filters - 1.3.0.0
AmioWavpack.amio (Adobe Audition Plugins) - 1.5
cool_wv4.flt (CoolEdit / Audition filter) - 2.14
------------------------------------------------
updated: see 4.80.0 library changes
--------------------------------
Release 4.75.2 - October 1, 2015
--------------------------------
WavPack Library Source Code - 4.75.2
------------------------------------
fixed: corrupt mono or multichannel files created with assembly code (rare)
fixed: building on Clang systems like Darwin and FreeBSD (req. Clang 3.5+)
fixed: explicitly sign-extend audio data (< 4-byte) to avoid corrupt files
fixed: rare decoding errors due to integer overflow (ARM assembly code)
added: assembly optimizations for "extra" mode on mono or multichannel
wvtest.exe (command-line libwavpack test suite) - 4.75.2
--------------------------------------------------------
all new program to stress-test libwavpack (requires Pthreads)
wavpack.exe (command-line encoder) - 4.75.2
wvunpack.exe (command-line decoder) - 4.75.2
wvgain.exe (command-line ReplayGain scanner) - 4.75.2
-----------------------------------------------------
fixed: corrupt mono or multichannel files created with assembly code (rare)
added: assembly optimizations for "extra" mode on mono or multichannel
improved: flush stderr after all writes
cool_wv4.flt (CoolEdit / Audition filter) - 2.13
AmioWavpack.amio (Adobe Audition Plugins) - 1.4
------------------------------------------------
fixed: corrupt mono or multichannel files (rare)
-----------------------------
Release 4.75.0 - May 25, 2015
-----------------------------
WavPack Library Source Code - 4.75.0
------------------------------------
improved: reorganization for modularity and to improve linking
added: assembly optimizations for encode/decode on x86 and x64
added: assembly optimizations for decoding on ARMv7 (Linux)
improved: several minor speed optimizations using intrinsics
fixed: wavpack.pc.in not working correctly on some Linux distros
fixed: memcpy() issue causing abort() on OpenBSD
wavpack.exe (command-line encoder) - 4.75.0
wvunpack.exe (command-line decoder) - 4.75.0
wvgain.exe (command-line ReplayGain scanner) - 4.75.0
-----------------------------------------------------
changed: writing to console title default is off (Linux only, -z1 to enable)
fixed: wvgain crashes on bad file arguments (Debian bug #716478)
cool_wv4.flt (CoolEdit / Audition filter) - 2.12
------------------------------------------------
improved: performance (from assembly optimizations)
-------------------------
Update - December 7, 2013
-------------------------
CoreWavPack DirectShow Filters - 1.2.0.2
----------------------------------------
imported: latest filter sources from Christophe Paris and CoreCodec
updated: port to VS 2008 and add 64-bit build platform with installer
added: decode streams with full headers (tested with LAV splitter)
fixed: issues with 7.1 and non-standard channel configurations
fixed: problems with 12-bit, 20-bit, and 32-bit integer audio
fixed: crashing bug related to hybrid files with DNS
fixed: custom sampling rates being ignored
---------------------------------
Release 4.70.0 - October 19, 2013
---------------------------------
wavpack.exe (command-line encoder) - 4.70.0
-------------------------------------------
added: transcoding from existing WavPack files (with tag copy)
added: option to verify WavPack file integrity on creation (-v)
added: use temporary files for safer overwriting
added: detect UTF-16LE encoding for tag text files (mostly a Windows thing)
added: --version command to write machine-parsable value
added: option to allow up to 16 MB APEv2 tag data (--allow-huge-tags)
added: allow channel-order specification on WAV files with zeroed channel mask
added: several Windows features to Linux (clean ^C handling, console title)
added: 4GB file support on 32-bit Linux targets
WavPack Library Source Code - 4.70.0
------------------------------------
fixed: seeking to last block failure (after finishing file)
fixed: memcpy() not always used correctly (Linux targets)
fixed: unsigned char issue (ARM targets)
fixed: add binary tag functions to Windows DLL exports (forgot on 4.60)
added: read-only access to APEv2 tags that come at the beginning of files
improved: switched to Microsoft Visual Studio 2008 (win32 only)
wvunpack.exe (command-line decoder) - 4.70.0
--------------------------------------------
added: use temporary files for safer overwriting
added: --version command to write machine-parsable value
added: new command (-f) for getting machine-parsable WavPack file info
added: option (-n) to suppress audio decoding (useful for extracting only tags)
wvgain.exe (command-line ReplayGain scanner) - 4.70.0
-----------------------------------------------------
fixed: the -q (quiet) option would cause the -c (clean) option to fail
added: version command (-v) to write machine-parsable value
in_wv.dll (winamp plugin) - 2.8
-------------------------------
fixed: settings could not be saved on newer Windows versions (7 & 8)
fixed: installation issue caused by including manifest in build
added: dialog to installer suggesting "Winamp Essentials Pack"
AmioWavpack.amio (Adobe Audition Plugin) - 1.0
----------------------------------------------
all new plugin for Audition 4.0 (CS5.5) and later (including Audition CC)
--------------------------
Update - December 23, 2009
--------------------------
in_wv.dll (winamp plugin) - 2.8a
--------------------------------
fixed: crashes in winamp 5.57 when playing tracks that have "genre" tag
----------------------------------
Release 4.60.1 - November 29, 2009
----------------------------------
WavPack Library Source Code - 4.60.1
------------------------------------
fixed: filename specs in tag extractions failed in batch operations
fixed: prevent creation of APEv2 tags > 1 MB (which we can't read)
fixed: crash when decoding old WavPack files (pre version 4.0)
added: man pages to build system and updated with newer options
added: versioning info to Windows DLL
improved: build compatibility (eliminated uchar, ushort types)
wavpack.exe (command-line encoder) - 4.60.1
-------------------------------------------
fixed: don't allow user to attempt to place over 1 MB into APEv2 tags
in_wv.dll (winamp plugin) - 2.7
-------------------------------
added: read-only support for displaying cover art (thanks Benski!)
wvunpack.exe (command-line decoder) - 4.60.1
wvgain.exe (command-line ReplayGain scanner) - 4.60.1
cool_wv4.flt (CoolEdit / Audition filter) - 2.11
-----------------------------------------------------
(see library changes)
---------------------------------
Release 4.60 - September 27, 2009
---------------------------------
WavPack Library Source Code - 4.60
----------------------------------
added: API for reading & writing binary fields in APEv2 tags
fixed: recognize APEv2 tags with footers but no headers
fixed: playback of files with 8 streams (15-16 channels)
fixed: playback and seeking failed on certain rare correction files
fixed: handle case where library makes RIFF header but app adds RIFF trailer
improved: channel count limit now virtually unlimited (tested to 256)
improved: move all tag functions into new module (tags.c)
wavpack.exe (command-line encoder) - 4.60
-----------------------------------------
added: --write-binary-tag command for embedded cover art
added: --no-utf8-convert command to skip Unicode character conversions
added: --raw-pcm command to specify raw PCM data (samplerate, bitdepth, num chans)
added: --channel-order accepts "..." to specify unassigned channels
added: --pair-unassigned-chans command to put unassigned channels into stereo pairs
wvunpack.exe (command-line decoder) - 4.60
------------------------------------------
added: -x (and -xx) commands for extracting arbitrary tag fields to stdout (and files)
added: --no-utf8-convert command to skip Unicode character conversions
changed: -ss command no longer dumps multiline tags (use -x instead)
improved: formatting of -ss command, also shows information on binary tags
wvgain.exe (command-line ReplayGain scanner) - 4.60
---------------------------------------------------
added: -n option for processing new files only (those without ReplayGain info)
improved: increase maximum gain value generated from +24 to +64 dB
in_wv.dll (winamp plugin) - 2.6
cool_wv4.flt (CoolEdit / Audition filter) - 2.10
------------------------------------------------
(see library changes)
-------------------------
Update - January 23, 2009
-------------------------
in_wv.dll (winamp plugin) - 2.6b
--------------------------------
added: "lossless" and "category" to metadata keywords that we handle in winamp plugin
added: internationalization support to facilitate inclusion in Winamp Essentials Pack
-----------------------------
Release 4.50.1 - July 3, 2008
-----------------------------
WavPack Library Source Code - 4.50.1
------------------------------------
fixed: alignment fault when manipulating APEv2 tags (non-x86 only)
fixed: build on UNIX via elimination of non-standard strnlen()
wavpack.exe (command-line encoder) - 4.50.1
wvunpack.exe (command-line decoder) - 4.50.1
--------------------------------------------
fixed: checking return value of iconv_open() prevents core dump on Solaris
----------------------------
Release 4.50 - June 13, 2008
----------------------------
WavPack Library Source Code - 4.50
----------------------------------
added: dynamic noise shaping for improved hybrid quality
added: option to merge blocks of similar redundancy
added: ability to store and retrieve extra mode level
fixed: alignment fault on some big-endian machines
fixed: compiling with enable-mmx on gcc 4.3.x (thanks Joachim)
improved: allow bitrate to be calculated for files down to 1/10 second
improved: decoding of corrupt files (prevents heap overrun crashes)
wavpack.exe (command-line encoder) - 4.50
-----------------------------------------
added: dynamic noise shaping for improved hybrid quality
added: --channel-order option to reorder nonconforming multichannel files
added: --merge-blocks option to optimize storage of LossyWAV output files
added: ignore -o on Windows for compatibility with Linux version
fixed: alignment fault on some big-endian machines
improved: reformatted and expanded --help display
wvunpack.exe (command-line decoder) - 4.50
------------------------------------------
fixed: don't ignore fractions of seconds in --skip option
added: show extra level and dns status for newer files (-s command)
added: ignore -o on Windows for compatibility with Linux version
improved: decoding of corrupt files (prevents heap overrun crashes)
improved: display bitrate for files down to 1/10 second
in_wv.dll (winamp plugin) - 2.5
-------------------------------
added: transcoding API (allows CD burning, format conversion, ReplayGain calc, etc.)
added: metadata writing API (for Auto-Tag, etc.)
added: full Unicode support for info box (older Winamps) and media library
added: standard Winamp metadata display & edit for newer Winamps
added: option to pass multichannel audio
added: option to pass all audio as 16-bit (for better compatibility)
added: option to output 24-bit audio when ReplayGain is active
added: genre display to info box (older Winamps)
fixed: seek bar sometimes vacillates when moved
fixed: crash when winamp is opened with files in playlist moved or deleted
improved: hi-res audio now output as 24-bit (not 32-bit) for better compatibility (EQ, etc.)
improved: performance of adding tracks to library, especially from network drives
improved: decoding of corrupt files (prevents heap overrun crashes)
cool_wv4.flt (CoolEdit / Audition filter) - 2.9
-----------------------------------------------
added: about box
added: dynamic noise shaping for improved hybrid quality
improved: display bitrate for files as short as 1/10 second
improved: decoding of corrupt files (prevents heap overrun crashes)
improved: replace "extra processing" switch with a slider (0-6)
--------------------------
Release 4.41 - May 6, 2007
--------------------------
WavPack Library Source Code - 4.41
----------------------------------
added: create wavpackdll.dll for Windows (not used yet)
fixed: corrupt floating-point audio on big-endian machines
fixed: put MSVC projects in their own subdir (fixed build problems)
fixed: limit RIFF data buffering to 16 MB to prevent out-of-memory crash
improved: attempt to mute errors when decoding corrupt legacy WavPack files
improved: overall performance enhancements of 10% to 30% (depending on mode)
added: MMX intrinsics for 24-bit (and higher) stereo encoding (thanks to
Joachim Henke)
wavpack.exe (command-line encoder) - 4.41
-----------------------------------------
fixed: corrupt floating-point audio on big-endian machines
improved: refuse to encode WAV files over 4 GB or with over 16 MB RIFF data
improved: overall performance enhancements of 10% to 30% (depending on mode)
added: MMX intrinsics for 24-bit (and higher) stereo encoding (thanks to
Joachim Henke)
wvunpack.exe (command-line decoder) - 4.41
------------------------------------------
fixed: corrupt floating-point audio on big-endian machines
fixed: restore files mistakenly encoded with huge RIFF chunks
improved: attempt to mute errors when decoding corrupt legacy WavPack files
improved: overall performance enhancements of 10% to 30% (depending on mode)
added: --skip and --until commands to unpack specified range of audio data
added: MMX intrinsics for 24-bit (and higher) stereo encoding (thanks to
Joachim Henke)
wvgain.exe (command-line ReplayGain scanner) - 4.41
---------------------------------------------------
improved: overall performance enhancements of 10% to 30% (depending on mode)
added: MMX intrinsics for 24-bit (and higher) stereo encoding (thanks to
Joachim Henke)
cool_wv4.flt (CoolEdit / Audition filter) - 2.8
-----------------------------------------------
fixed: read all RIFF metadata from files created in other applications
improved: attempt to mute errors when decoding corrupt legacy WavPack files
improved: overall performance enhancements of 10% to 30% (depending on mode)
added: MMX intrinsics for 24-bit (and higher) stereo encoding (thanks to
Joachim Henke)
-------------------------------
Release 4.40 - December 3, 2006
-------------------------------
WavPack Library Source Code - 4.40
----------------------------------
added: new hardware-friendly "high" mode that compresses almost as well as
old "high" mode but decodes significantly faster; old "high" mode
now available as "very high"
added: option added to improve compression of mono material in stereo files
(requires at least version 4.3 decoder)
added: function to obtain channel mapping information on decoding
added: function to get trailing wrapper info (RIFF) without decoding file
improved: "extra" mode levels 1-3 completely revamped, fast enough for use
improved: reorganized to create a standard library that should more easily
integrate into other applications; eliminated namespace issues
improved: more robust handling of corrupt files
wavpack.exe (command-line encoder) - 4.40
-----------------------------------------
added: accepts long option names including --help for full usage info
added: new hardware-friendly "high" mode that compresses almost as well as
old "high" mode but decodes significantly faster; old "high" mode
now available as "very high" (-hh)
added: --optimize-mono option added to improve compression of mono material
in stereo files (requires at least version 4.3 decoder)
improved: "extra" mode levels 1-3 completely revamped, fast enough for use
improved: switched to Microsoft Visual Studio 2005 (win32 only)
removed: support for Windows 95
wvunpack.exe (command-line decoder) - 4.40
------------------------------------------
added: cuesheet extraction (to .cue file or stdout)
added: wav header generation on decode for files with missing RIFF
information, or forced with -w option
added: more summary info (wrapper info + channel assignments)
improved: more robust handling of corrupt files
improved: separate options for raw (-r) and blind stream decoding (-b)
improved: switched to Microsoft Visual Studio 2005 (win32 only)
removed: support for Windows 95
wvgain.exe (command-line ReplayGain scanner) - 4.40
---------------------------------------------------
improved: switched to Microsoft Visual Studio 2005 (win32 only)
removed: support for Windows 95
wvselfx.exe (self-extraction stub) - 4.40
------------------------------------------
added: automatic cuesheet extraction (if present in APEv2 tag)
in_wv.dll (winamp plugin) - 2.4
-------------------------------
fixed: quietly skips deleted files in playlist
improved: more robust handling of corrupt files
improved: APEv2 tags are read even if followed by ID3v1 tag
cool_wv4.flt (CoolEdit / Audition filter) - 2.7
-----------------------------------------------
added: new hardware-friendly "high" mode that compresses almost as well as
old "high" mode but decodes significantly faster; old "high" mode
now available as "v. high"
improved: more robust handling of corrupt files
----------------------
Update - April 5, 2006
----------------------
WavPack Library Source Code - 4.32
wavpack.exe (command-line encoder) - 4.32
-----------------------------------------
fixed: generating RIFF headers on big-endian machines caused crash
--------------------------
Update - December 10, 2005
--------------------------
wavpack.exe (command-line encoder) - 4.31
wvunpack.exe (command-line decoder) - 4.31
------------------------------------------
fixed: detect debug mode in all cases (win32 only)
improved: use latest service pack and SDK for building (win32 only)
improved: better directory choice for logging file (win32 only)
improved: allow shell to expand wildcards (*nix only)
added: option (-o) to specify output directory or path (*nix only)
added: option (-t) to copy timestamp (*nix only)
wvgain.exe (command-line ReplayGain scanner) - 4.31
---------------------------------------------------
new
WavPack Library Source Code - 4.31
----------------------------------
fixed: failing seek with some files that had been played to the end
fixed: small memory leak when opening hybrid lossless files
improved: signed characters no longer must be default
improved: APEv2 tags are read even if followed by ID3v1 tag
improved: limited APEv2 tag editing capability
------------------------------
Release 4.3 - November 1, 2005
------------------------------
wavpack.exe (command-line encoder) - 4.3
----------------------------------------
fixed: bug causing termination error with very wide screen widths
added: command-line option (-l) to use low priority for batch operation
added: command-line option (-r) to generate a fresh RIFF header
added: debug mode (rename to wavpack_debug.exe)
added: automatically detect lower resolution data even without -x1
added: src and dst dirs are searched also for tag source files (handy for EAC)
added: wildcard accepted for tag source files (handy for EAC)
added: handle non-standard sampling rates
improved: returns error status for any error
improved: use longer blocks in multichannel files (better "high" compression)
wvunpack.exe (command-line decoder) - 4.3
-----------------------------------------
fixed: very rare decoding bug causing overflow with hi-res files
fixed: bug causing termination error with very wide screen widths
fixed: formatting error in duration display
added: command-line option (-ss) to include tags in summary dump
added: command-line option (-l) to use low priority for batch operation
added: debug mode (rename to wvunpack_debug.exe)
improved: returns error status for any error
improved: more robust decoding of damaged (or invalid) files
in_wv.dll (winamp plugin) - 2.3
nxWavPack.dll (Nero plugin) - 1.2
WavPack_Apollo.dll (Apollo plugin) - 1.3
cool_wv4.flt (CoolEdit / Audition filter) - 2.6
-----------------------------------------------
fixed: very rare decoding bug causing overflow with hi-res files
improved: handle ID3v1.1 tags (now includes track number)
improved: more robust decoding of damaged (or invalid) files
added: handle non-standard sampling rates
foo_wavpack.dll (foobar plugin) - 2.3
-----------------------------------------------
fixed: any error during WavPack file open caused crash if wvc file present
fixed: very rare decoding bug causing overflow with hi-res files
improved: more robust decoding of damaged (or invalid) files
added: handle non-standard sampling rates
WavPack Library Source Code - 4.3
---------------------------------
fixed: very rare decoding bug causing overflow with hi-res files
added: automatic generation of RIFF wav header during encoding
added: new functions to access tags by index (instead of item name)
added: automatically detect lower resolution data during encoding
added: handle non-standard sampling rates
improved: more robust decoding of damaged (or invalid) files
improved: use longer blocks in multichannel files (better "high" compression)
improved: two structures renamed to avoid namespace conflict
removed: legacy code for Borland compiler
--------------------------
Update - September 1, 2005
--------------------------
wavpack.exe (command-line encoder) - 4.22
cool_wv4.flt (CoolEdit / Audition filter) - 2.5
-----------------------------------------------
fixed: possible corrupt files written (24 or 32-bit + "extra" mode)
---------------------------
Release 4.2 - April 2, 2005
---------------------------
wavpack.exe (command-line encoder) - 4.2
----------------------------------------
fixed: handling of wav files larger than 2 gig
improved: stereo lossless encoding speed (including "extra" mode)
added: -i option to ignore length specified in wav header
added: -w option to write APEv2 tags directly from command line
wvunpack.exe (command-line decoder) - 4.2
-----------------------------------------
improved: decoding speed
in_wv.dll (winamp plugin) - 2.2
-------------------------------
added: winamp media library support
improved: decoding speed
foo_wavpack.dll (foobar plugin) - 2.2
-------------------------------------
improved: decoding speed
nxWavPack.dll (Nero plugin) - 1.1
Cool_wv4.flt (CoolEdit / Audition filter) - 2.4
-----------------------------------------------
fixed: handling of wav files larger than 2 gig
improved: encoding and decoding speed
WavPack Library Source Code - 4.2
---------------------------------
improved: encoding and decoding speed
fixed: works correctly with 64-bit compilers
added: mode bit to open files in "streaming" mode
--------------------------
Update - December 12, 2004
--------------------------
WavPack_Apollo.dll (Apollo plugin) - 1.2
----------------------------------------
fixed: crash when Apollo opened and WavPack plugin can't find config file
--------------------------------
Release 4.1 - September 14, 2004
--------------------------------
wavpack.exe (command-line encoder) - 4.1
----------------------------------------
fixed: hybrid mode + "extra" mode + very low bitrates making corrupt files
fixed: mono or multichannel files causing crash (no corruption possible)
added: third name specification for "correction" file (EAC specific)
added: -t option to preserve timestamps
added: error summary for batch mode
wvunpack.exe (command-line decoder) - 4.1
-----------------------------------------
fixed: hybrid mode decoding bugs (very obscure situations)
added: -s option to dump file summary to stdout
added: -t option to preserve timestamps
added: error summary for batch mode
wvselfx.exe (self-extraction stub) - 4.1
----------------------------------------
fixed: hybrid mode decoding bugs (very obscure situations)
in_wv.dll (winamp plugin) - 2.1
-------------------------------
fixed: international characters in tags display properly (UTF-8 to Ansi)
added: maximum tag data field width changed from 64 chars to 128 chars
added: new infobox items including encoder version & modes, track #, md5
foo_wavpack.dll (foobar plugin) - 2.1
-------------------------------------
added: new database items including encoder version & modes and md5
WavPack_Apollo.dll (Apollo plugin) - 1.1
----------------------------------------
fixed: international characters in tags display properly (UTF-8 to Ansi)
Cool_wv4.flt (CoolEdit / Audition filter) - 2.2
-----------------------------------------------
fixed: hybrid mode + "extra" mode + very low bitrates making corrupt files
fixed: saving mono file causing crash (no corruption possible)
fixed: hybrid mode decoding bugs (very obscure situations)
fixed: partial saves (with "Cancel") have incorrect RIFF header if unpacked
nxWavPack.dll (Nero plugin) - 1.0
---------------------------------
new
WavPack Library Source Code - 4.1
---------------------------------
fixed: hybrid mode + "extra" mode + very low bitrates making corrupt files
fixed: mono or multichannel files causing crash (no corruption possible)
fixed: hybrid mode decoding bugs (very obscure situations)
added: mode bits for determining additional encode info (extra, sfx)
added: function to return total compressed file length (including wvc)
added: function to return encoder version (1, 2, 3, or 4)
added: ability to obtain MD5 sum before decoding file (requires seek to end)
added: mode bit for determining tag type (for proper character translation)
added: ability to encode WavPack files without knowing length in advance
added: option for small "information only" version of library

View File

@ -1,113 +0,0 @@
////////////////////////////////////////////////////////////////////////////
// **** WAVPACK **** //
// Hybrid Lossless Wavefile Compressor //
// Copyright (c) 1998 - 2016 David Bryant. //
// All Rights Reserved. //
// Distributed under the BSD Software License (see license.txt) //
////////////////////////////////////////////////////////////////////////////
This package contains all the source code required to build the WavPack
library (libwavpack) and the command-line programs and it has been tested
on many platforms. Assembly language optimizations are provided for x86
and x86-64 (AMD64) processors (encoding and decoding) and ARMv7 (decoding
only). The x86 assembly code includes a runtime check for MMX capability,
so it will work on legacy i386 processors.
On Windows there are solution and project files for Visual Studio 2008 and
additional sourcecode to build the CoolEdit/Audition plugin and the winamp
plugin. The CoolEdit/Audition plugin provides a good example for using the
library to both read and write WavPack files and the winamp plugin makes
extensive use of APEv2 tag reading and writing. Both 32-bit and 64-bit
platforms are provided.
Visual Studio 2008 does not support projects with x64 assembly very well. I
have provided a copy of the edited masm.rules file that works for me, but I
can't provide support if your build does not work. Please make a copy of
your masm.rules file first. On my system it lives here:
C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\VCProjectDefaults
To build everything on Linux, type:
1. ./configure [--disable-asm] [--enable-man] [--enable-rpath] [--enable-tests]
2. make
3. make install (optionally, to install into /usr/local/bin)
If you are using the code directly from Git (rather than a distribution)
then you will need to do a ./autogen.sh instead of the configure step. If
assembly optimizations are available for your processor they will be
automatically enabled, but if there is a problem with them then use the
--disable-asm option to revert to pure C. For Clang-based build systems
(Darwin, FreeBSD, etc.) Clang version 3.5 or higher is required.
If you get a WARNING about unexpected libwavpack version when you run the
command-line programs, you might try using --enable-rpath to hardcode the
library location in the executables, or simply force static linking with
--disable-shared.
There is now a cli program to do a full suite of stress tests for libwavpack,
and this is particularly useful for packagers to make sure that the assembly
language optimizations are working correctly on various platforms. It is
built with the configure option --enable-tests and requires Pthreads (it
worked out-of-the-box on all the platforms I tried it on). There are lots of
options, but the default test suite (consisting of 192 tests) is executed
with "wvtest --default". On Windows a third-party Pthreads library is
required, so I am not including this in the build for now.
Notes:
1. There are three documentation files contained in the distribution:
doc/wavpack_doc.html contains user-targeted documentation for the
command-line programs
doc/library_use.txt contains a detailed description of the API provided
by WavPack library appropriate for read and writing
WavPack files and manipulating APEv2 tags
doc/file_format.txt contains a description of the WavPack file format,
including details needed for parsing WavPack blocks
and interpreting the block header and flags
There is also a description of the WavPack algorithms in the forth edition
of David Salomon's book "Data Compression: The Complete Reference". The
section on WavPack can be found here:
www.wavpack.com/WavPack.pdf
2. This code is designed to be easy to port to other platforms. It is endian-
agnostic and usually uses callbacks for I/O, although there's a convenience
function for reading files that accepts filename strings and automatically
handles correction files (and on Windows there is now an option to select
UTF-8 instead of ANSI).
To maintain compatibility on various platforms, the following conventions
are used: the "char" type must be 8-bits (signed or unsigned), a "short"
must be 16-bits and the "int" and "long" types must be at least 32-bits.
3. The code's modules are organized in such a way that if major chunks of the
functionality are not referenced (for example, creating WavPack files) then
link-time dependency resolution should provide optimum binary sizes.
However, some functionality could not be easily excluded in this way and so
there are additional macros that may be used to further reduce the size of
the binary. Note that these must be defined for all modules:
VER4_ONLY to only handle WavPack files from version 4.0 onward
(this is highly recommended for most applications
because pre-4.0 WavPack files are very old)
NO_SEEKING to not allow seeking to a specific sample index
(for applications that always read entire files)
NO_TAGS to not read specified fields from ID3v1 and APEv2 tags and
not create or edit APEv2 tags
4. There are alternate versions of this library available specifically designed
for "resource limited" CPUs or hardware encoding and decoding. There is the
"tiny decoder" library which works with less than 32k of code and less than
4k of data and has assembly language optimizations for the ARM and Freescale
ColdFire CPUs. The "tiny encoder" is also designed for embedded use and
handles the pure lossless, lossy, and hybrid lossless modes. Neither of the
"tiny" versions use any memory allocation functions nor do they require
floating-point arithmetic support.
5. Questions or comments should be directed to david@wavpack.com

View File

@ -0,0 +1,136 @@
<img src="http://www.rarewares.org/wavpack/logos/wavpacklogo.png" width="250"></img>
Hybrid Lossless Wavefile Compressor
Copyright (c) 1998 - 2019 David Bryant.
All Rights Reserved.
Distributed under the [BSD Software License](https://github.com/dbry/WavPack/blob/master/license.txt).
---
This [repository](https://github.com/dbry/WavPack) contains all of the source code required to build the WavPack library (_libwavpack_), and any associated command-line programs.
Additional references:
* [Official website](http://wavpack.com/)
* [Binaries](http://wavpack.com/downloads.html#binaries)
* [Other sources](http://wavpack.com/downloads.html#sources)
* [Documentation](http://wavpack.com/downloads.html#documentation)
* [Test suite](http://www.rarewares.org/wavpack/test_suite.zip)
* [Logos](http://wavpack.com/downloads.html#logos)
---
## Build Status
| Branch | Status |
|----------------|-------------------------------------------------------------------------------------------------------------------|
| `master` | [![Build Status](https://travis-ci.org/dbry/WavPack.svg?branch=master)](https://travis-ci.org/dbry/WavPack) |
Branches [actively built](https://travis-ci.org/dbry/WavPack/branches) by TravisCI.
---
## Building
### Windows
There are solution and project files for Visual Studio 2008, and additional source code to build the [CoolEdit/Audition](https://github.com/dbry/WavPack/tree/master/audition) plugin and the [Winamp](https://github.com/dbry/WavPack/tree/master/winamp) plugin.
The CoolEdit/Audition plugin provides a good example for using the library to both read and write WavPack files, and the Winamp plugin makes extensive use of APEv2 tag reading and writing.
Both 32-bit and 64-bit platforms are provided.
Visual Studio 2008 does not support projects with x64 assembly very well. I have provided a copy of the edited `masm.rules` file that works for me, but I can't provide support if your build does not work. Please make a copy of your `masm.rules` file first.
On my system it lives here: `C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\VCProjectDefaults`
### Linux
To build everything on Linux, type:
1. `./configure`
* `--disable-asm`
* `--enable-man`
* `--enable-rpath`
* `--enable-tests`
* `--disable-apps`
* `--disable-dsd`
* `--enable-legacy`
2. `make`
* Optionally, `make install`, to install into `/usr/local/bin`
If you are using the code directly from Git (rather than a distribution) then you will need to do a ./autogen.sh instead of the configure step. If assembly optimizations are available for your processor they will be automatically enabled, but if there is a problem with them then use the `--disable-asm` option to revert to pure C.
For Clang-based build systems (Darwin, FreeBSD, etc.), Clang version 3.5 or higher is required.
If you get a WARNING about unexpected _libwavpack_ version when you run the command-line programs, you might try using `--enable-rpath` to hardcode the library location in the executables, or simply force static linking with `--disable-shared`.
There is now a CLI program to do a full suite of stress tests for _libwavpack_, and this is particularly useful for packagers to make sure that the assembly language optimizations are working correctly on various platforms. It is built with the configure option `--enable-tests` and requires Pthreads (it worked out-of-the-box on all the platforms I tried it on). There are lots of options, but the default test suite (consisting of 192 tests) is executed with `wvtest --default`. There is also a seeking test. On Windows a third-party Pthreads library is required, so I am not including this in the build for now.
---
## Assembly
Assembly language optimizations are provided for x86 and x86-64 (AMD64) processors (encoding and decoding) and ARMv7 (decoding only).
The x86 assembly code includes a runtime check for MMX capability, so it will work on legacy i386 processors.
## Documentation
There are four documentation files contained in the distribution:
| File | Description |
|------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------|
| [doc/wavpack_doc.html](https://github.com/dbry/WavPack/blob/master/doc/wavpack_doc.html) | Contains user-targeted documentation for the command-line programs. |
| [doc/WavPack5PortingGuide.pdf](https://github.com/dbry/WavPack/blob/master/doc/WavPack5PortingGuide.pdf) | This document is targeted at developers who are migrating to WavPack 5, and it provides a short description of the major improvements and how to utilize them. |
| [doc/WavPack5LibraryDoc.pdf](https://github.com/dbry/WavPack/blob/master/doc/WavPack5LibraryDoc.pdf) | Contains a detailed description of the API provided by WavPack library appropriate for reading and writing WavPack files and manipulating APEv2 tags. |
| [doc/WavPack5FileFormat.pdf](https://github.com/dbry/WavPack/blob/master/doc/WavPack5FileFormat.pdf) | Contains a description of the WavPack file format, including details needed for parsing WavPack, blocks, and interpreting the block header and flags. |
There is also a description of the WavPack algorithms in the forth edition of David Salomon's book "Data Compression: The Complete Reference". This section can be found here: www.wavpack.com/WavPack.pdf
## Portability
This code is designed to be easy to port to other platforms.
It is endian-agnostic and usually uses callbacks for I/O, although there's a convenience function for reading files that accepts filename strings and automatically handles correction files.
On Windows, there is now an option to select UTF-8 instead of ANSI.
To maintain compatibility on various platforms, the following conventions are used:
* `char` must be 8-bits (`signed` or `unsigned`).
* `short` must be 16-bits.
* `int` and `long` must be at least 32-bits.
## Design
The code's modules are organized in such a way that if major chunks of the functionality are not referenced (for example, creating WavPack files) then link-time dependency resolution should provide optimum binary sizes.
However, some functionality could not be easily excluded in this way and so there are additional macros that may be used to further reduce the size of the binary. Note that these must be defined for all modules:
| Macros | Description |
|-----------------|------------------------------------------------------------------------------------------------------------|
| `NO_SEEKING` | To not allow seeking to a specific sample index (for applications that always read entire files). |
| `NO_TAGS` | To not read specified fields from ID3v1 and APEv2 tags, and not create or edit APEv2 tags. |
| `ENABLE_LEGACY` | Include support for Wavpack files from before version 4.0. This was eliminated by default with WavPack 5. |
| `ENABLE_DSD` | Include support for DSD audio. New for WavPack 5 and the default, but obviously not universally required. |
Note that this has been tested on many platforms.
## Tiny Decoder
There are alternate versions of this library available specifically designed for resource limited CPUs, and hardware encoding and decoding.
There is the _Tiny Decoder_ library which works with less than 32k of code and less than 4k of data, and has assembly language optimizations for the ARM and Freescale ColdFire CPUs.
The _Tiny Decoder_ is also designed for embedded use and handles the pure lossless, lossy, and hybrid lossless modes.
Neither of these versions use any memory allocation functions, nor do they require floating-point arithmetic support.
---
Questions or comments should be directed to david@wavpack.com.
You may also find David on GitHub as [dbry](https://github.com/dbry).

View File

@ -11,7 +11,7 @@
// This module provides a lot of the trivial WavPack API functions and several
// functions that are common to both reading and writing WavPack files (like
// WavpackCloseFile()). Functions here are restricted to those that have few
// external dependancies and this is done so that applications that statically
// external dependencies and this is done so that applications that statically
// link to the WavPack library (like the command-line utilities on Windows)
// do not need to include the entire library image if they only use a subset
// of it. This module will be loaded for ANY WavPack application.
@ -40,7 +40,7 @@ const uint32_t sample_rates [] = { 6000, 8000, 9600, 11025, 12000, 16000, 22050,
// MODE_LOSSLESS: file is lossless (either pure or hybrid)
// MODE_HYBRID: file is hybrid mode (either lossy or lossless)
// MODE_FLOAT: audio data is 32-bit ieee floating point
// MODE_VALID_TAG: file conatins a valid ID3v1 or APEv2 tag
// MODE_VALID_TAG: file contains a valid ID3v1 or APEv2 tag
// MODE_HIGH: file was created in "high" mode (information only)
// MODE_FAST: file was created in "fast" mode (information only)
// MODE_EXTRA: file was created using "extra" mode (information only)
@ -164,7 +164,7 @@ uint32_t WavpackGetSampleIndex (WavpackContext *wpc)
int64_t WavpackGetSampleIndex64 (WavpackContext *wpc)
{
if (wpc) {
#ifndef VER4_ONLY
#ifdef ENABLE_LEGACY
if (wpc->stream3)
return get_sample_index3 (wpc);
else if (wpc->streams && wpc->streams [0])
@ -292,6 +292,13 @@ double WavpackGetInstantBitrate (WavpackContext *wpc)
// then that much space must be allocated. Note that all the reordering is actually done
// outside of this library, and that if reordering is done then the appropriate qmode bit
// will be set.
//
// Note: Normally this function would not be used by an application unless it specifically
// wanted to restore a non-standard channel order (to check an MD5, for example) or obtain
// the Core Audio channel layout ID. For simple file decoding for playback, the channel_mask
// should provide all the information required unless there are non-Microsoft channels
// involved, in which case WavpackGetChannelIdentities() will provide the identities of
// the other channels (if they are known).
uint32_t WavpackGetChannelLayout (WavpackContext *wpc, unsigned char *reorder)
{
@ -301,11 +308,60 @@ uint32_t WavpackGetChannelLayout (WavpackContext *wpc, unsigned char *reorder)
return wpc->channel_layout;
}
// This function provides the identities of ALL the channels in the file, including the
// standard Microsoft channels (which come first, in order, and are numbered 1-18) and also
// any non-Microsoft channels (which can be in any order and have values from 33-254). The
// value 0x00 is invalid and 0xFF indicates an "unknown" or "unnassigned" channel. The
// string is NULL terminated so the caller must supply enough space for the number
// of channels indicated by WavpackGetNumChannels(), plus one.
//
// Note that this function returns the actual order of the channels in the Wavpack file
// (i.e., the order returned by WavpackUnpackSamples()). If the file includes a "reordering"
// string because the source file was not in Microsoft order that is NOT taken into account
// here and really only needs to be considered if doing an MD5 verification or if it's
// required to restore the original order/file (like wvunpack does).
void WavpackGetChannelIdentities (WavpackContext *wpc, unsigned char *identities)
{
int num_channels = wpc->config.num_channels, index = 1;
uint32_t channel_mask = wpc->config.channel_mask;
unsigned char *src = wpc->channel_identities;
while (num_channels--) {
if (channel_mask) {
while (!(channel_mask & 1)) {
channel_mask >>= 1;
index++;
}
*identities++ = index++;
channel_mask >>= 1;
}
else if (src && *src)
*identities++ = *src++;
else
*identities++ = 0xff;
}
*identities = 0;
}
// For local use only. Install a callback to be executed when WavpackCloseFile() is called,
// usually used to dump some statistics accumulated during encode or decode.
void install_close_callback (WavpackContext *wpc, void cb_func (void *wpc))
{
wpc->close_callback = cb_func;
}
// Close the specified WavPack file and release all resources used by it.
// Returns NULL.
WavpackContext *WavpackCloseFile (WavpackContext *wpc)
{
if (wpc->close_callback)
wpc->close_callback (wpc);
if (wpc->streams) {
free_streams (wpc);
@ -315,7 +371,7 @@ WavpackContext *WavpackCloseFile (WavpackContext *wpc)
free (wpc->streams);
}
#ifndef VER4_ONLY
#ifdef ENABLE_LEGACY
if (wpc->stream3)
free_stream3 (wpc);
#endif
@ -328,6 +384,19 @@ WavpackContext *WavpackCloseFile (WavpackContext *wpc)
WavpackFreeWrapper (wpc);
if (wpc->metadata) {
int i;
for (i = 0; i < wpc->metacount; ++i)
if (wpc->metadata [i].data)
free (wpc->metadata [i].data);
free (wpc->metadata);
}
if (wpc->channel_identities)
free (wpc->channel_identities);
if (wpc->channel_reordering)
free (wpc->channel_reordering);
@ -335,8 +404,10 @@ WavpackContext *WavpackCloseFile (WavpackContext *wpc)
free_tag (&wpc->m_tag);
#endif
#ifdef ENABLE_DSD
if (wpc->decimation_context)
decimate_dsd_destroy (wpc->decimation_context);
#endif
free (wpc);
@ -374,6 +445,15 @@ uint32_t WavpackGetSampleRate (WavpackContext *wpc)
return wpc ? (wpc->dsd_multiplier ? wpc->config.sample_rate * wpc->dsd_multiplier : wpc->config.sample_rate) : 44100;
}
// Returns the native sample rate of the specified WavPack file
// (provides the native rate for DSD files rather than the "byte" rate that's used for
// seeking, duration, etc. and would generally be used just for user facing reports)
uint32_t WavpackGetNativeSampleRate (WavpackContext *wpc)
{
return wpc ? (wpc->dsd_multiplier ? wpc->config.sample_rate * wpc->dsd_multiplier * 8 : wpc->config.sample_rate) : 44100;
}
// Returns the number of channels of the specified WavPack file. Note that
// this is the actual number of channels contained in the file even if the
// OPEN_2CH_MAX flag was specified when the file was opened.
@ -440,7 +520,7 @@ int WavpackGetReducedChannels (WavpackContext *wpc)
}
// Free all memory allocated for raw WavPack blocks (for all allocated streams)
// and free all additonal streams. This does not free the default stream ([0])
// and free all additional streams. This does not free the default stream ([0])
// which is always kept around.
void free_streams (WavpackContext *wpc)
@ -468,31 +548,9 @@ void free_streams (WavpackContext *wpc)
wpc->streams [si]->dc.shaping_data = NULL;
}
if (wpc->streams [si]->dsd.probabilities) {
free (wpc->streams [si]->dsd.probabilities);
wpc->streams [si]->dsd.probabilities = NULL;
}
if (wpc->streams [si]->dsd.summed_probabilities) {
free (wpc->streams [si]->dsd.summed_probabilities);
wpc->streams [si]->dsd.summed_probabilities = NULL;
}
if (wpc->streams [si]->dsd.value_lookup) {
int i;
for (i = 0; i < wpc->streams [si]->dsd.history_bins; ++i)
if (wpc->streams [si]->dsd.value_lookup [i])
free (wpc->streams [si]->dsd.value_lookup [i]);
free (wpc->streams [si]->dsd.value_lookup);
wpc->streams [si]->dsd.value_lookup = NULL;
}
if (wpc->streams [si]->dsd.ptable) {
free (wpc->streams [si]->dsd.ptable);
wpc->streams [si]->dsd.ptable = NULL;
}
#ifdef ENABLE_DSD
free_dsd_tables (wpc->streams [si]);
#endif
if (si) {
wpc->num_streams--;
@ -504,6 +562,34 @@ void free_streams (WavpackContext *wpc)
wpc->current_stream = 0;
}
void free_dsd_tables (WavpackStream *wps)
{
if (wps->dsd.probabilities) {
free (wps->dsd.probabilities);
wps->dsd.probabilities = NULL;
}
if (wps->dsd.summed_probabilities) {
free (wps->dsd.summed_probabilities);
wps->dsd.summed_probabilities = NULL;
}
if (wps->dsd.lookup_buffer) {
free (wps->dsd.lookup_buffer);
wps->dsd.lookup_buffer = NULL;
}
if (wps->dsd.value_lookup) {
free (wps->dsd.value_lookup);
wps->dsd.value_lookup = NULL;
}
if (wps->dsd.ptable) {
free (wps->dsd.ptable);
wps->dsd.ptable = NULL;
}
}
void WavpackFloatNormalize (int32_t *values, int32_t num_values, int delta_exp)
{
f32 *fvalues = (f32 *) values;

View File

@ -1,142 +0,0 @@
#! /bin/sh
# Wrapper for compilers which do not understand `-c -o'.
scriptversion=2005-05-14.22
# Copyright (C) 1999, 2000, 2003, 2004, 2005 Free Software Foundation, Inc.
# Written by Tom Tromey <tromey@cygnus.com>.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# This file is maintained in Automake, please report
# bugs to <bug-automake@gnu.org> or send patches to
# <automake-patches@gnu.org>.
case $1 in
'')
echo "$0: No command. Try \`$0 --help' for more information." 1>&2
exit 1;
;;
-h | --h*)
cat <<\EOF
Usage: compile [--help] [--version] PROGRAM [ARGS]
Wrapper for compilers which do not understand `-c -o'.
Remove `-o dest.o' from ARGS, run PROGRAM with the remaining
arguments, and rename the output as expected.
If you are trying to build a whole package this is not the
right script to run: please start by reading the file `INSTALL'.
Report bugs to <bug-automake@gnu.org>.
EOF
exit $?
;;
-v | --v*)
echo "compile $scriptversion"
exit $?
;;
esac
ofile=
cfile=
eat=
for arg
do
if test -n "$eat"; then
eat=
else
case $1 in
-o)
# configure might choose to run compile as `compile cc -o foo foo.c'.
# So we strip `-o arg' only if arg is an object.
eat=1
case $2 in
*.o | *.obj)
ofile=$2
;;
*)
set x "$@" -o "$2"
shift
;;
esac
;;
*.c)
cfile=$1
set x "$@" "$1"
shift
;;
*)
set x "$@" "$1"
shift
;;
esac
fi
shift
done
if test -z "$ofile" || test -z "$cfile"; then
# If no `-o' option was seen then we might have been invoked from a
# pattern rule where we don't need one. That is ok -- this is a
# normal compilation that the losing compiler can handle. If no
# `.c' file was seen then we are probably linking. That is also
# ok.
exec "$@"
fi
# Name of file we expect compiler to create.
cofile=`echo "$cfile" | sed -e 's|^.*/||' -e 's/\.c$/.o/'`
# Create the lock directory.
# Note: use `[/.-]' here to ensure that we don't use the same name
# that we are using for the .o file. Also, base the name on the expected
# object file name, since that is what matters with a parallel build.
lockdir=`echo "$cofile" | sed -e 's|[/.-]|_|g'`.d
while true; do
if mkdir "$lockdir" >/dev/null 2>&1; then
break
fi
sleep 1
done
# FIXME: race condition here if user kills between mkdir and trap.
trap "rmdir '$lockdir'; exit 1" 1 2 15
# Run the compile.
"$@"
ret=$?
if test -f "$cofile"; then
mv "$cofile" "$ofile"
elif test -f "${cofile}bj"; then
mv "${cofile}bj" "$ofile"
fi
rmdir "$lockdir"
exit $ret
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-end: "$"
# End:

File diff suppressed because it is too large Load Diff

View File

@ -32,7 +32,7 @@
int read_decorr_terms (WavpackStream *wps, WavpackMetadata *wpmd)
{
int termcnt = wpmd->byte_length;
unsigned char *byteptr = wpmd->data;
unsigned char *byteptr = (unsigned char *)wpmd->data;
struct decorr_pass *dpp;
if (termcnt > MAX_NTERMS)
@ -61,7 +61,7 @@ int read_decorr_terms (WavpackStream *wps, WavpackMetadata *wpmd)
int read_decorr_weights (WavpackStream *wps, WavpackMetadata *wpmd)
{
int termcnt = wpmd->byte_length, tcount;
char *byteptr = wpmd->data;
char *byteptr = (char *)wpmd->data;
struct decorr_pass *dpp;
if (!(wps->wphdr.flags & MONO_DATA))
@ -93,7 +93,7 @@ int read_decorr_weights (WavpackStream *wps, WavpackMetadata *wpmd)
int read_decorr_samples (WavpackStream *wps, WavpackMetadata *wpmd)
{
unsigned char *byteptr = wpmd->data;
unsigned char *byteptr = (unsigned char *)wpmd->data;
unsigned char *endptr = byteptr + wpmd->byte_length;
struct decorr_pass *dpp;
int tcount;
@ -171,14 +171,14 @@ int read_decorr_samples (WavpackStream *wps, WavpackMetadata *wpmd)
int read_shaping_info (WavpackStream *wps, WavpackMetadata *wpmd)
{
if (wpmd->byte_length == 2) {
char *byteptr = wpmd->data;
char *byteptr = (char *)wpmd->data;
wps->dc.shaping_acc [0] = (int32_t) restore_weight (*byteptr++) << 16;
wps->dc.shaping_acc [1] = (int32_t) restore_weight (*byteptr++) << 16;
return TRUE;
}
else if (wpmd->byte_length >= (wps->wphdr.flags & MONO_DATA ? 4 : 8)) {
unsigned char *byteptr = wpmd->data;
unsigned char *byteptr = (unsigned char *)wpmd->data;
wps->dc.error [0] = wp_exp2s ((int16_t)(byteptr [0] + (byteptr [1] << 8)));
wps->dc.shaping_acc [0] = wp_exp2s ((int16_t)(byteptr [2] + (byteptr [3] << 8)));

View File

@ -104,13 +104,13 @@ static const unsigned char exp2_table [] = {
///////////////////////////// executable code ////////////////////////////////
// Read the median log2 values from the specifed metadata structure, convert
// Read the median log2 values from the specified metadata structure, convert
// them back to 32-bit unsigned values and store them. If length is not
// exactly correct then we flag and return an error.
int read_entropy_vars (WavpackStream *wps, WavpackMetadata *wpmd)
{
unsigned char *byteptr = wpmd->data;
unsigned char *byteptr = (unsigned char *)wpmd->data;
if (wpmd->byte_length != ((wps->wphdr.flags & MONO_DATA) ? 6 : 12))
return FALSE;
@ -128,14 +128,14 @@ int read_entropy_vars (WavpackStream *wps, WavpackMetadata *wpmd)
return TRUE;
}
// Read the hybrid related values from the specifed metadata structure, convert
// Read the hybrid related values from the specified metadata structure, convert
// them back to their internal formats and store them. The extended profile
// stuff is not implemented yet, so return an error if we get more data than
// we know what to do with.
int read_hybrid_profile (WavpackStream *wps, WavpackMetadata *wpmd)
{
unsigned char *byteptr = wpmd->data;
unsigned char *byteptr = (unsigned char *)wpmd->data;
unsigned char *endptr = byteptr + wpmd->byte_length;
if (wps->wphdr.flags & HYBRID_BITRATE) {

View File

@ -20,11 +20,11 @@
// This flag causes this module to take into account the size of the header
// (which grows with more decorrelation passes) when making decisions about
// adding additional passes (as opposed to just considering the resulting
// magnitude of the residuals). With small blocks this seems to work correctly,
// but with longer blocks it seems to actually hurt compression (for reasons I
// cannot explain), so it's disabled by default
// magnitude of the residuals). With really long blocks it seems to actually
// hurt compression (for reasons I cannot explain), but with short blocks it
// works okay, so we're enabling it for now.
//#define USE_OVERHEAD
#define USE_OVERHEAD
// If the log2 value of any sample in a buffer being scanned exceeds this value,
// we abandon that configuration. This prevents us from going down paths that
@ -36,7 +36,7 @@
#ifdef OPT_ASM_X86
#define PACK_DECORR_MONO_PASS_CONT pack_decorr_mono_pass_cont_x86
#elif defined(OPT_ASM_X64) && (defined (_WIN64) || defined(__CYGWIN__) || defined(__MINGW64__))
#elif defined(OPT_ASM_X64) && (defined (_WIN64) || defined(__CYGWIN__) || defined(__MINGW64__) || defined(__midipix__))
#define PACK_DECORR_MONO_PASS_CONT pack_decorr_mono_pass_cont_x64win
#elif defined(OPT_ASM_X64)
#define PACK_DECORR_MONO_PASS_CONT pack_decorr_mono_pass_cont_x64

View File

@ -21,11 +21,11 @@
// This flag causes this module to take into account the size of the header
// (which grows with more decorrelation passes) when making decisions about
// adding additional passes (as opposed to just considering the resulting
// magnitude of the residuals). With small blocks this seems to work correctly,
// but with longer blocks it seems to actually hurt compression (for reasons I
// cannot explain), so it's disabled by default
// magnitude of the residuals). With really long blocks it seems to actually
// hurt compression (for reasons I cannot explain), but with short blocks it
// works okay, so we're enabling it for now.
//#define USE_OVERHEAD
#define USE_OVERHEAD
// If the log2 value of any sample in a buffer being scanned exceeds this value,
// we abandon that configuration. This prevents us from going down paths that
@ -39,7 +39,7 @@
#define PACK_DECORR_STEREO_PASS_CONT pack_decorr_stereo_pass_cont_x86
#define PACK_DECORR_STEREO_PASS_CONT_REV pack_decorr_stereo_pass_cont_rev_x86
#define PACK_DECORR_STEREO_PASS_CONT_AVAILABLE pack_cpu_has_feature_x86(CPU_FEATURE_MMX)
#elif defined(OPT_ASM_X64) && (defined (_WIN64) || defined(__CYGWIN__) || defined(__MINGW64__))
#elif defined(OPT_ASM_X64) && (defined (_WIN64) || defined(__CYGWIN__) || defined(__MINGW64__) || defined(__midipix__))
#define PACK_DECORR_STEREO_PASS_CONT pack_decorr_stereo_pass_cont_x64win
#define PACK_DECORR_STEREO_PASS_CONT_REV pack_decorr_stereo_pass_cont_rev_x64win
#define PACK_DECORR_STEREO_PASS_CONT_AVAILABLE 1

View File

@ -1,242 +0,0 @@
////////////////////////////////////////////////////////////////////////////
// **** WAVPACK **** //
// Hybrid Lossless Wavefile Compressor //
// Copyright (c) 1998 - 2006 Conifer Software. //
// All Rights Reserved. //
// Distributed under the BSD Software License (see license.txt) //
////////////////////////////////////////////////////////////////////////////
WavPack 4.0 File / Block Format
-------------------------------
December 9, 2006
David Bryant
updated: April 29, 2007
updated: Sept 26, 2009
1.0 INTRODUCTION
A WavPack 4.0 file consists of a series of WavPack audio blocks. It may also
contain tags and other information, but these must be outside the blocks
(either before, in-between, or after) and are ignored for the purpose of
unpacking audio data. The WavPack blocks are easy to identify by their unique
header data, and by looking in the header it is very easy to determine the total
size of the block (both in physical bytes and compressed samples) and the audio
format stored. There are no specialized seek tables.
The blocks are completely independent in that they can be decoded to mono or
stereo audio all by themselves. The blocks may contain any number of samples
(well, up to 131072), either stereo or mono. Obviously, putting more samples
in each block is more efficient because of reduced header overhead, but they are
reasonably efficient down to even a thousand samples. I have set the max size to
1 MB for the whole block, but this is arbitrary. The blocks may be lossless or
lossy. Currently the hybrid/lossy modes are basically CBR, but I am planning a
quality based VBR version also, and all the provisions exist for this in the
format.
For multichannel audio, the data is divided into some number of stereo and mono
streams and multiplexed into separate blocks which repeat in sequence. A flag
in the header indicates whether the block is the first or the last in the
sequence (for simple mono or stereo files both of these would always be set).
The speaker assignments are in standard Microsoft order and the channel_mask is
transmitted in a separate piece of metadata. Channels that naturally belong
together (i.e. left and right pairs) are put into stereo blocks and other
channels are put into mono block. So, for example, a standard 5.1 audio stream
would have a channel_mask of 0x3F and be organized into 4 blocks in sequence:
1. stereo block (front left + front right) (INITIAL_BLOCK)
2. mono block (front center)
3. mono block (low frequency effects)
4. stereo block (back left + back right) (FINAL_BLOCK)
Correction files (.wvc) have an identical structure to the main file (.wv) and
there is a one-to-one correspondence between main file blocks that contain audio
and their correction file match (blocks that do not contain audio do not exist
in the correction file). The only difference in the headers of main blocks and
correction blocks is the size and the CRC value, although it is easy (if a
little ugly) to tell the blocks apart by looking at the metadata ids.
The format is designed with hardware decoding in mind, and so it is possible to
decode regular stereo (or mono) WavPack files without buffering an entire block,
which allows the memory requirements to be reduced to only a few kilobytes if
desired. This is not true of multichannel files, and this also restricts
playback of high-resolution files to 24 bits of precision (although neither of
these would be associated with low-cost playback equipment).
2.0 BLOCK HEADER
Here is the 32-byte little-endian header at the front of every WavPack block:
typedef struct {
char ckID [4]; // "wvpk"
uint32_t ckSize; // size of entire block (minus 8, of course)
uint16_t version; // 0x402 to 0x410 are currently valid for decode
uchar track_no; // track number (0 if not used, like now)
uchar index_no; // track sub-index (0 if not used, like now)
uint32_t total_samples; // total samples for entire file, but this is
// only valid if block_index == 0 and a value of
// -1 indicates unknown length
uint32_t block_index; // index of first sample in block relative to
// beginning of file (normally this would start
// at 0 for the first block)
uint32_t block_samples; // number of samples in this block (0 = no audio)
uint32_t flags; // various flags for id and decoding
uint32_t crc; // crc for actual decoded data
} WavpackHeader;
Note that in this context the meaning of "samples" refers to a complete
sample for all channels (sometimes called a "frame"). Therefore, in a stereo
or multichannel file the actual number of numeric samples is this value
multiplied by the number of channels. This effectively limits the size of an
on-disk WavPack file to (2^32)-2 samples, although this should not be a big
restriction for most applications (that is over 24 hours at 44.1 kHz, no
matter how many channels).
There is no limit to the size of the WavPack file itself, although the
library currently cannot seek in WavPack files over 4 gig. Also, the .wav
format itself has a 4 gig limit, so this limits the size of the source and
destination files (although this is planned to be resolved with the W64
and RIFF64 file formats).
Normally, the first block of a WavPack file that contains audio samples
(blocks may contains only metadata) would have "block_index" == 0 and
"total_samples" would be equal to the total number of samples in the
file. However, there are some possible exceptions to this rule. For example,
a file may be created such that its total length is unknown (i.e. with
pipes) and in this case total_samples == -1. For these files, the WavPack
decoder will attempt to seek to the end of the file to determine the actual
length, and if this is impossible then the length is simply unknown.
Another case is where a WavPack file is created by cutting a portion out of a
longer WavPack file (or from a WavPack stream). Since this file would start
with a block that didn't have "block_index" == 0, the length would be unknown
until a seek to end was performed. In fact, an on-disk file would still be
perfectly playable and seekable as long as there were less than (2^32)-2 total
samples (the "block_index" could even wrap).
It is also possible to have streamed WavPack data. In this case both the
"block_index" and "total_samples" fields are ignored for every block and the
decoder simply decodes every block encountered indefinitely.
The "flags" field contains information for decoding the block along with some
general information including sample size and format, hybrid/lossless,
mono/stereo and sampling rate (if one of 15 standard rates). Here are the
(little-endian) bit assignments:
bits 1,0: // 00 = 1 byte / sample (1-8 bits / sample)
// 01 = 2 bytes / sample (1-16 bits / sample)
// 10 = 3 bytes / sample (1-24 bits / sample)
// 11 = 4 bytes / sample (1-32 bits / sample)
bit 2: // 0 = stereo output; 1 = mono output
bit 3: // 0 = lossless mode; 1 = hybrid mode
bit 4: // 0 = true stereo; 1 = joint stereo (mid/side)
bit 5: // 0 = independent channels; 1 = cross-channel decorrelation
bit 6: // 0 = flat noise spectrum in hybrid; 1 = hybrid noise shaping
bit 7: // 0 = integer data; 1 = floating point data
bit 8: // 1 = extended size integers (> 24-bit) or shifted integers
bit 9: // 0 = hybrid mode parameters control noise level
// 1 = hybrid mode parameters control bitrate
bit 10: // 1 = hybrid noise balanced between channels
bit 11: // 1 = initial block in sequence (for multichannel)
bit 12: // 1 = final block in sequence (for multichannel)
bits 17-13: // amount of data left-shift after decode (0-31 places)
bits 22-18: // maximum magnitude of decoded data
// (number of bits integers require minus 1)
bits 26-23: // sampling rate (1111 = unknown/custom)
bits 27-28: // reserved (but decoders should ignore if set)
bit 29: // 1 = use IIR for negative hybrid noise shaping
bit 30: // 1 = false stereo (data is mono but output is stereo)
bit 31: // reserved (decoders should refuse to decode if set)
3.0 METADATA SUB-BLOCKS
Following the 32-byte header to the end of the block are a series of "metadata"
sub-blocks. These may from 2 bytes long to the size of the entire block and are
extremely easy to parse (even without knowing what they mean). These mostly
contain extra information needed to decode the audio, but may also contain user
information that is not required for decoding and that could be used in the
future without breaking existing decoders. The final sub-block is usually the
compressed audio bitstream itself, although this is not a strict rule.
The format of the metadata is:
uchar id; // mask meaning
// ---- -------
// 0x1f metadata function
// 0x20 decoder need not understand metadata
// 0x40 actual data byte length is 1 less
// 0x80 large block (> 255 words)
uchar word_size; // small block: data size in words (padded)
or...
uchar word_size [3]; // large block: data size in words (padded,
little-endian)
uint16_t data [word_size]; // data, padded to an even # of bytes
The currently assigned metadata ids are:
ID_DUMMY 0x0 // could be used to pad WavPack blocks
ID_DECORR_TERMS 0x2 // decorrelation terms & deltas (fixed)
ID_DECORR_WEIGHTS 0x3 // initial decorrelation weights
ID_DECORR_SAMPLES 0x4 // decorrelation sample history
ID_ENTROPY_VARS 0x5 // initial entropy variables
ID_HYBRID_PROFILE 0x6 // entropy variables specific to hybrid mode
ID_SHAPING_WEIGHTS 0x7 // info needed for hybrid lossless (wvc) mode
ID_FLOAT_INFO 0x8 // specific info for floating point decode
ID_INT32_INFO 0x9 // specific info for decoding integers > 24
// bits, or data requiring shift after decode
ID_WV_BITSTREAM 0xa // normal compressed audio bitstream (wv file)
ID_WVC_BITSTREAM 0xb // correction file bitstream (wvc file)
ID_WVX_BITSTREAM 0xc // special extended bitstream for floating
// point data or integers > 24 bit (can be
// in either wv or wvc file, depending...)
ID_CHANNEL_INFO 0xd // contains channel count and channel_mask
ID_RIFF_HEADER 0x21 // RIFF header for .wav files (before audio)
ID_RIFF_TRAILER 0x22 // RIFF trailer for .wav files (after audio)
ID_CONFIG_BLOCK 0x25 // some encoding details for info purposes
ID_MD5_CHECKSUM 0x26 // 16-byte MD5 sum of raw audio data
ID_SAMPLE_RATE 0x27 // non-standard sampling rate info
Note: unlisted ids are reserved.
The RIFF header and trailer are optional for most playback purposes, however
older decoders (< 4.40) will not decode to .wav files unless at least the
ID_RIFF_HEADER is present. In the future these could be used to encode other
uncompressed audio formats (like AIFF).
4.0 METADATA TAGS
These tags are not to be confused with the metadata sub-blocks described above
but are specialized tags for storing user data on many formats of audio files.
The tags recommended for use with WavPack files (and the ones that the WavPack
supplied plugins and programs will work with) are ID3v1 and APEv2. The ID3v1
tags are somewhat primitive and limited, but are supported for legacy purposes.
The more recommended tagging format is APEv2 because of its rich functionality
and broad software support (it is also used on Monkey's Audio and Musepack
files). Both the APEv2 tags and/or ID3v1 tags must come at the end of the
WavPack file, with the ID3v1 coming last if both are present.
For the APEv2 tags, the following field names are officially supported and
recommended by WavPack (although there are no restrictions on what field names
may be used):
Artist
Title
Album
Track
Year
Genre
Comment
Cuesheet (note: may include replay gain info as remarks)
Replaygain_Track_Gain
Replaygain_Track_Peak
Replaygain_Album_Gain
Replaygain_Album_Peak
Cover Art (Front)
Cover Art (Back)
Log

View File

@ -1,25 +0,0 @@
Copyright (c) 1998 - 2013 Conifer Software
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Conifer Software 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 REGENTS OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -1,264 +1,291 @@
/*
* This code implements the MD5 message-digest algorithm.
* The algorithm is due to Ron Rivest. This code was
* written by Colin Plumb in 1993, no copyright is claimed.
* This code is in the public domain; do with it what you wish.
* This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
* MD5 Message-Digest Algorithm (RFC 1321).
*
* Equivalent code is available from RSA Data Security, Inc.
* This code has been tested against that, and is equivalent,
* except that you don't need to include two pages of legalese
* with every copy.
* Homepage:
* http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
*
* To compute the message digest of a chunk of bytes, declare an
* MD5Context structure, pass it to MD5Init, call MD5Update as
* needed on buffers full of bytes, and then call MD5Final, which
* will fill a supplied 16-byte array with the digest.
* Author:
* Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
*
* This software was written by Alexander Peslyak in 2001. No copyright is
* claimed, and the software is hereby placed in the public domain.
* In case this attempt to disclaim copyright and place the software in the
* public domain is deemed null and void, then the software is
* Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
* general public under the following terms:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted.
*
* There's ABSOLUTELY NO WARRANTY, express or implied.
*
* (This is a heavily cut-down "BSD license".)
*
* This differs from Colin Plumb's older public domain implementation in that
* no exactly 32-bit integer data type is required (any 32-bit or wider
* unsigned integer data type will do), there's no compile-time endianness
* configuration, and the function prototypes match OpenSSL's. No code from
* Colin Plumb's implementation has been reused; this comment merely compares
* the properties of the two independent implementations.
*
* The primary goals of this implementation are portability and ease of use.
* It is meant to be fast, but not as fast as possible. Some known
* optimizations are not included to reduce source code size and avoid
* compile-time configuration.
*/
/* Brutally hacked by John Walker back from ANSI C to K&R (no
prototypes) to maintain the tradition that Netfone will compile
with Sun's original "cc". */
#ifndef HAVE_LIBCRYPTO
#include <string.h>
#include <memory.h> /* for memcpy() */
#include "md5.h"
#ifdef sgi
#define HIGHFIRST
#endif
/*
* The basic MD5 functions.
*
* F and G are optimized compared to their RFC 1321 definitions for
* architectures that lack an AND-NOT instruction, just like in Colin Plumb's
* implementation.
*/
#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
#define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y))))
#define H(x, y, z) (((x) ^ (y)) ^ (z))
#define H2(x, y, z) ((x) ^ ((y) ^ (z)))
#define I(x, y, z) ((y) ^ ((x) | ~(z)))
#ifdef sun
#define HIGHFIRST
#endif
/*
* The MD5 transformation for all four rounds.
*/
#define STEP(f, a, b, c, d, x, t, s) \
(a) += f((b), (c), (d)) + (x) + (t); \
(a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \
(a) += (b);
#ifndef HIGHFIRST
#define byteReverse(buf, len) /* Nothing */
/*
* SET reads 4 input bytes in little-endian byte order and stores them in a
* properly aligned word in host byte order.
*
* The check for little-endian architectures that tolerate unaligned memory
* accesses is just an optimization. Nothing will break if it fails to detect
* a suitable architecture.
*
* Unfortunately, this optimization may be a C strict aliasing rules violation
* if the caller's data buffer has effective type that cannot be aliased by
* MD5_u32plus. In practice, this problem may occur if these MD5 routines are
* inlined into a calling function, or with future and dangerously advanced
* link-time optimizations. For the time being, keeping these MD5 routines in
* their own translation unit avoids the problem.
*/
#if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
#define SET(n) \
(*(MD5_u32plus *)&ptr[(n) * 4])
#define GET(n) \
SET(n)
#else
/*
* Note: this code is harmless on little-endian machines.
*/
void byteReverse(buf, longs)
unsigned char *buf; unsigned longs;
{
uint32 t;
do {
t = (uint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
((unsigned) buf[1] << 8 | buf[0]);
*(uint32 *) buf = t;
buf += 4;
} while (--longs);
}
#define SET(n) \
(ctx->block[(n)] = \
(MD5_u32plus)ptr[(n) * 4] | \
((MD5_u32plus)ptr[(n) * 4 + 1] << 8) | \
((MD5_u32plus)ptr[(n) * 4 + 2] << 16) | \
((MD5_u32plus)ptr[(n) * 4 + 3] << 24))
#define GET(n) \
(ctx->block[(n)])
#endif
/*
* Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
* initialization constants.
* This processes one or more 64-byte data blocks, but does NOT update the bit
* counters. There are no alignment requirements.
*/
void MD5Init(ctx)
struct MD5Context *ctx;
static const void *body(MD5_CTX *ctx, const void *data, unsigned long size)
{
ctx->buf[0] = 0x67452301;
ctx->buf[1] = 0xefcdab89;
ctx->buf[2] = 0x98badcfe;
ctx->buf[3] = 0x10325476;
const unsigned char *ptr;
MD5_u32plus a, b, c, d;
MD5_u32plus saved_a, saved_b, saved_c, saved_d;
ctx->bits[0] = 0;
ctx->bits[1] = 0;
ptr = (const unsigned char *)data;
a = ctx->a;
b = ctx->b;
c = ctx->c;
d = ctx->d;
do {
saved_a = a;
saved_b = b;
saved_c = c;
saved_d = d;
/* Round 1 */
STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)
/* Round 2 */
STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)
/* Round 3 */
STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
STEP(H2, d, a, b, c, GET(8), 0x8771f681, 11)
STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
STEP(H2, b, c, d, a, GET(14), 0xfde5380c, 23)
STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
STEP(H2, d, a, b, c, GET(4), 0x4bdecfa9, 11)
STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
STEP(H2, b, c, d, a, GET(10), 0xbebfbc70, 23)
STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
STEP(H2, d, a, b, c, GET(0), 0xeaa127fa, 11)
STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
STEP(H2, b, c, d, a, GET(6), 0x04881d05, 23)
STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
STEP(H2, d, a, b, c, GET(12), 0xe6db99e5, 11)
STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
STEP(H2, b, c, d, a, GET(2), 0xc4ac5665, 23)
/* Round 4 */
STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)
a += saved_a;
b += saved_b;
c += saved_c;
d += saved_d;
ptr += 64;
} while (size -= 64);
ctx->a = a;
ctx->b = b;
ctx->c = c;
ctx->d = d;
return ptr;
}
/*
* Update context to reflect the concatenation of another buffer full
* of bytes.
*/
void MD5Update(ctx, buf, len)
struct MD5Context *ctx; unsigned char *buf; unsigned len;
void MD5_Init(MD5_CTX *ctx)
{
uint32 t;
ctx->a = 0x67452301;
ctx->b = 0xefcdab89;
ctx->c = 0x98badcfe;
ctx->d = 0x10325476;
/* Update bitcount */
t = ctx->bits[0];
if ((ctx->bits[0] = t + ((uint32) len << 3)) < t)
ctx->bits[1]++; /* Carry from low to high */
ctx->bits[1] += len >> 29;
t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
/* Handle any leading odd-sized chunks */
if (t) {
unsigned char *p = (unsigned char *) ctx->in + t;
t = 64 - t;
if (len < t) {
memcpy(p, buf, len);
return;
}
memcpy(p, buf, t);
byteReverse(ctx->in, 16);
MD5Transform(ctx->buf, (uint32 *) ctx->in);
buf += t;
len -= t;
}
/* Process data in 64-byte chunks */
while (len >= 64) {
memcpy(ctx->in, buf, 64);
byteReverse(ctx->in, 16);
MD5Transform(ctx->buf, (uint32 *) ctx->in);
buf += 64;
len -= 64;
}
/* Handle any remaining bytes of data. */
memcpy(ctx->in, buf, len);
ctx->lo = 0;
ctx->hi = 0;
}
/*
* Final wrapup - pad to 64-byte boundary with the bit pattern
* 1 0* (64-bit count of bits processed, MSB-first)
*/
void MD5Final(digest, ctx)
unsigned char digest[16]; struct MD5Context *ctx;
void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size)
{
uint32 *ptr32 = (uint32 *) ctx->in;
unsigned count;
unsigned char *p;
MD5_u32plus saved_lo;
unsigned long used, available;
/* Compute number of bytes mod 64 */
count = (ctx->bits[0] >> 3) & 0x3F;
saved_lo = ctx->lo;
if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
ctx->hi++;
ctx->hi += size >> 29;
/* Set the first char of padding to 0x80. This is safe since there is
always at least one byte free */
p = ctx->in + count;
*p++ = 0x80;
used = saved_lo & 0x3f;
/* Bytes of padding needed to make 64 bytes */
count = 64 - 1 - count;
if (used) {
available = 64 - used;
/* Pad out to 56 mod 64 */
if (count < 8) {
/* Two lots of padding: Pad the first block to 64 bytes */
memset(p, 0, count);
byteReverse(ctx->in, 16);
MD5Transform(ctx->buf, ptr32);
if (size < available) {
memcpy(&ctx->buffer[used], data, size);
return;
}
/* Now fill the next block with 56 bytes */
memset(ctx->in, 0, 56);
} else {
/* Pad block to 56 bytes */
memset(p, 0, count - 8);
}
byteReverse(ctx->in, 14);
memcpy(&ctx->buffer[used], data, available);
data = (const unsigned char *)data + available;
size -= available;
body(ctx, ctx->buffer, 64);
}
/* Append length in bits and transform */
ptr32 [14] = ctx->bits[0];
ptr32 [15] = ctx->bits[1];
if (size >= 64) {
data = body(ctx, data, size & ~(unsigned long)0x3f);
size &= 0x3f;
}
MD5Transform(ctx->buf, ptr32);
byteReverse((unsigned char *) ctx->buf, 4);
memcpy(digest, ctx->buf, 16);
memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
memcpy(ctx->buffer, data, size);
}
#define OUT(dst, src) \
(dst)[0] = (unsigned char)(src); \
(dst)[1] = (unsigned char)((src) >> 8); \
(dst)[2] = (unsigned char)((src) >> 16); \
(dst)[3] = (unsigned char)((src) >> 24);
/* The four core functions - F1 is optimized somewhat */
/* #define F1(x, y, z) (x & y | ~x & z) */
#define F1(x, y, z) (z ^ (x & (y ^ z)))
#define F2(x, y, z) F1(z, x, y)
#define F3(x, y, z) (x ^ y ^ z)
#define F4(x, y, z) (y ^ (x | ~z))
/* This is the central step in the MD5 algorithm. */
#define MD5STEP(f, w, x, y, z, data, s) \
( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
/*
* The core of the MD5 algorithm, this alters an existing MD5 hash to
* reflect the addition of 16 longwords of new data. MD5Update blocks
* the data and converts bytes into longwords for this routine.
*/
void MD5Transform(buf, in)
uint32 buf[4]; uint32 in[16];
void MD5_Final(unsigned char *result, MD5_CTX *ctx)
{
register uint32 a, b, c, d;
unsigned long used, available;
a = buf[0];
b = buf[1];
c = buf[2];
d = buf[3];
used = ctx->lo & 0x3f;
MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
ctx->buffer[used++] = 0x80;
MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
available = 64 - used;
MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
if (available < 8) {
memset(&ctx->buffer[used], 0, available);
body(ctx, ctx->buffer, 64);
used = 0;
available = 64;
}
MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
memset(&ctx->buffer[used], 0, available - 8);
buf[0] += a;
buf[1] += b;
buf[2] += c;
buf[3] += d;
ctx->lo <<= 3;
OUT(&ctx->buffer[56], ctx->lo)
OUT(&ctx->buffer[60], ctx->hi)
body(ctx, ctx->buffer, 64);
OUT(&result[0], ctx->a)
OUT(&result[4], ctx->b)
OUT(&result[8], ctx->c)
OUT(&result[12], ctx->d)
memset(ctx, 0, sizeof(*ctx));
}
#endif

View File

@ -1,26 +1,45 @@
#ifndef MD5_H
#define MD5_H
#if defined (__alpha__) || defined (__x86_64__)
typedef unsigned int uint32;
#else
typedef unsigned long uint32;
#endif
struct MD5Context {
uint32 buf[4];
uint32 bits[2];
unsigned char in[64];
};
extern void MD5Init (struct MD5Context *ctx);
extern void MD5Update (struct MD5Context *ctx, unsigned char *buf, unsigned len);
extern void MD5Final (unsigned char digest[16], struct MD5Context *ctx);
extern void MD5Transform (uint32 buf[4], uint32 in[16]);
/*
* This is needed to make RSAREF happy on some MS-DOS compilers.
* This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
* MD5 Message-Digest Algorithm (RFC 1321).
*
* Homepage:
* http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
*
* Author:
* Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
*
* This software was written by Alexander Peslyak in 2001. No copyright is
* claimed, and the software is hereby placed in the public domain.
* In case this attempt to disclaim copyright and place the software in the
* public domain is deemed null and void, then the software is
* Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
* general public under the following terms:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted.
*
* There's ABSOLUTELY NO WARRANTY, express or implied.
*
* See md5.c for more information.
*/
typedef struct MD5Context MD5_CTX;
#endif /* !MD5_H */
#ifdef HAVE_LIBCRYPTO
#include <openssl/md5.h>
#elif !defined(_MD5_H)
#define _MD5_H
/* Any 32-bit or wider unsigned integer data type will do */
typedef unsigned int MD5_u32plus;
typedef struct {
MD5_u32plus lo, hi;
MD5_u32plus a, b, c, d;
unsigned char buffer[64];
MD5_u32plus block[16];
} MD5_CTX;
extern void MD5_Init(MD5_CTX *ctx);
extern void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size);
extern void MD5_Final(unsigned char *result, MD5_CTX *ctx);
#endif

View File

@ -52,6 +52,14 @@
#ifdef _WIN32
#define fileno _fileno
static FILE *fopen_utf8 (const char *filename_utf8, const char *mode_utf8);
#if !defined(S_ISREG) && defined(S_IFMT) && defined(S_IFREG)
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
#endif
#endif
#ifdef HAVE_FSEEKO
#define fseek fseeko
#define ftell ftello
#endif
static int32_t read_bytes (void *id, void *data, int32_t bcount)
@ -120,7 +128,7 @@ static int64_t get_length (void *id)
FILE *file = id;
struct stat statbuf;
if (!file || fstat (fileno (file), &statbuf) || !(statbuf.st_mode & S_IFREG))
if (!file || fstat (fileno (file), &statbuf) || !S_ISREG(statbuf.st_mode))
return 0;
return statbuf.st_size;
@ -133,7 +141,7 @@ static int can_seek (void *id)
FILE *file = id;
struct stat statbuf;
return file && !fstat (fileno (file), &statbuf) && (statbuf.st_mode & S_IFREG);
return file && !fstat (fileno (file), &statbuf) && S_ISREG(statbuf.st_mode);
}
static int32_t write_bytes (void *id, void *data, int32_t bcount)
@ -239,7 +247,7 @@ WavpackContext *WavpackOpenFileInput (const char *infilename, char *error, int f
return NULL;
}
if (wv_id != stdin && (flags & OPEN_WVC)) {
if (*infilename != '-' && (flags & OPEN_WVC)) {
char *in2filename = malloc (strlen (infilename) + 10);
strcpy (in2filename, infilename);
@ -279,7 +287,7 @@ static FILE *fopen_utf8(const char *filename_utf8, const char *mode_utf8)
FILE *ret = NULL;
wchar_t *filename_utf16 = utf8_to_utf16(filename_utf8);
wchar_t *mode_utf16 = utf8_to_utf16(mode_utf8);
if(filename_utf16 && mode_utf16)
{
ret = _wfopen(filename_utf16, mode_utf16);

View File

@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////////////////////
// **** WAVPACK **** //
// Hybrid Lossless Wavefile Compressor //
// Copyright (c) 1998 - 2016 David Bryant. //
// Copyright (c) 1998 - 2019 David Bryant. //
// All Rights Reserved. //
// Distributed under the BSD Software License (see license.txt) //
////////////////////////////////////////////////////////////////////////////
@ -24,49 +24,49 @@ typedef struct {
static int32_t trans_read_bytes (void *id, void *data, int32_t bcount)
{
WavpackReaderTranslator *trans = id;
WavpackReaderTranslator *trans = (WavpackReaderTranslator *)id;
return trans->reader->read_bytes (trans->id, data, bcount);
}
static int32_t trans_write_bytes (void *id, void *data, int32_t bcount)
{
WavpackReaderTranslator *trans = id;
WavpackReaderTranslator *trans = (WavpackReaderTranslator *)id;
return trans->reader->write_bytes (trans->id, data, bcount);
}
static int64_t trans_get_pos (void *id)
{
WavpackReaderTranslator *trans = id;
WavpackReaderTranslator *trans = (WavpackReaderTranslator *)id;
return trans->reader->get_pos (trans->id);
}
static int trans_set_pos_abs (void *id, int64_t pos)
{
WavpackReaderTranslator *trans = id;
WavpackReaderTranslator *trans = (WavpackReaderTranslator *)id;
return trans->reader->set_pos_abs (trans->id, (uint32_t) pos);
}
static int trans_set_pos_rel (void *id, int64_t delta, int mode)
{
WavpackReaderTranslator *trans = id;
WavpackReaderTranslator *trans = (WavpackReaderTranslator *)id;
return trans->reader->set_pos_rel (trans->id, (int32_t) delta, mode);
}
static int trans_push_back_byte (void *id, int c)
{
WavpackReaderTranslator *trans = id;
WavpackReaderTranslator *trans = (WavpackReaderTranslator *)id;
return trans->reader->push_back_byte (trans->id, c);
}
static int64_t trans_get_length (void *id)
{
WavpackReaderTranslator *trans = id;
WavpackReaderTranslator *trans = (WavpackReaderTranslator *)id;
return trans->reader->get_length (trans->id);
}
static int trans_can_seek (void *id)
{
WavpackReaderTranslator *trans = id;
WavpackReaderTranslator *trans = (WavpackReaderTranslator *)id;
return trans->reader->can_seek (trans->id);
}
@ -76,42 +76,36 @@ static int trans_close_stream (void *id)
return 0;
}
// int32_t (*read_bytes)(void *id, void *data, int32_t bcount);
// int32_t (*write_bytes)(void *id, void *data, int32_t bcount);
// int64_t (*get_pos)(void *id); // new signature for large files
// int (*set_pos_abs)(void *id, int64_t pos); // new signature for large files
// int (*set_pos_rel)(void *id, int64_t delta, int mode); // new signature for large files
// int (*push_back_byte)(void *id, int c);
// int64_t (*get_length)(void *id); // new signature for large files
// int (*can_seek)(void *id);
// int (*truncate_here)(void *id); // new function to truncate file at current position
// int (*close)(void *id); // new function to close file
static WavpackStreamReader64 trans_reader = {
trans_read_bytes, trans_write_bytes, trans_get_pos, trans_set_pos_abs, trans_set_pos_rel,
trans_push_back_byte, trans_get_length, trans_can_seek, NULL, trans_close_stream
};
// This function is identical to WavpackOpenFileInput() except that instead
// of providing a filename to open, the caller provides a pointer to a set of
// reader callbacks and instances of up to two streams. The first of these
// streams is required and contains the regular WavPack data stream; the second
// contains the "correction" file if desired. Unlike the standard open
// function which handles the correction file transparently, in this case it
// is the responsibility of the caller to be aware of correction files.
// This function is identical to WavpackOpenFileInput64() except that instead
// of providing the new 64-bit reader callbacks, the old reader callbacks are
// utilized and a translation layer is employed. It is provided as a compatibility
// function for existing applications. To ensure that streaming applications using
// this function continue to work, the OPEN_NO_CHECKSUM flag is forced on when
// the OPEN_STREAMING flag is set.
WavpackContext *WavpackOpenFileInputEx (WavpackStreamReader *reader, void *wv_id, void *wvc_id, char *error, int flags, int norm_offset)
{
WavpackReaderTranslator *trans_wv = NULL, *trans_wvc = NULL;
// this prevents existing streaming applications from failing if they try to pass
// in blocks that have been modified from the original (e.g., Matroska blocks)
if (flags & OPEN_STREAMING)
flags |= OPEN_NO_CHECKSUM;
if (wv_id) {
trans_wv = malloc (sizeof (WavpackReaderTranslator));
trans_wv = (WavpackReaderTranslator *)malloc (sizeof (WavpackReaderTranslator));
trans_wv->reader = reader;
trans_wv->id = wv_id;
}
if (wvc_id) {
trans_wvc = malloc (sizeof (WavpackReaderTranslator));
trans_wvc = (WavpackReaderTranslator *)malloc (sizeof (WavpackReaderTranslator));
trans_wvc->reader = reader;
trans_wvc->id = wvc_id;
}

View File

@ -0,0 +1,315 @@
////////////////////////////////////////////////////////////////////////////
// **** WAVPACK **** //
// Hybrid Lossless Wavefile Compressor //
// Copyright (c) 1998 - 2019 David Bryant. //
// All Rights Reserved. //
// Distributed under the BSD Software License (see license.txt) //
////////////////////////////////////////////////////////////////////////////
// open_raw.c
// This code provides the ability to decode WavPack frames directly from
// memory for use in a streaming application. It can handle full blocks
// or the headerless block data provided by Matroska and the DirectShow
// WavPack splitter. For information about how Matroska stores WavPack,
// see: https://www.matroska.org/technical/specs/codecid/wavpack.html
#include <stdlib.h>
#include <string.h>
#include "wavpack_local.h"
typedef struct {
unsigned char *sptr, *dptr, *eptr, free_required;
} RawSegment;
typedef struct {
RawSegment *segments;
int num_segments, curr_segment;
unsigned char ungetc_char, ungetc_flag;
} WavpackRawContext;
static int32_t raw_read_bytes (void *id, void *data, int32_t bcount)
{
WavpackRawContext *rcxt = id;
unsigned char *outptr = data;
while (bcount) {
if (rcxt->ungetc_flag) {
*outptr++ = rcxt->ungetc_char;
rcxt->ungetc_flag = 0;
bcount--;
}
else if (rcxt->curr_segment < rcxt->num_segments) {
RawSegment *segptr = rcxt->segments + rcxt->curr_segment;
int bytes_to_copy = (int)(segptr->eptr - segptr->dptr);
if (bytes_to_copy > bcount)
bytes_to_copy = bcount;
memcpy (outptr, segptr->dptr, bytes_to_copy);
outptr += bytes_to_copy;
bcount -= bytes_to_copy;
if ((segptr->dptr += bytes_to_copy) == segptr->eptr)
rcxt->curr_segment++;
}
else
break;
}
return (int32_t)(outptr - (unsigned char *) data);
}
static int32_t raw_write_bytes (void *id, void *data, int32_t bcount)
{
return 0;
}
static int64_t raw_get_pos (void *id)
{
return 0;
}
static int raw_set_pos_abs (void *id, int64_t pos)
{
return 0;
}
static int raw_set_pos_rel (void *id, int64_t delta, int mode)
{
return 0;
}
static int raw_push_back_byte (void *id, int c)
{
WavpackRawContext *rcxt = id;
rcxt->ungetc_char = c;
rcxt->ungetc_flag = 1;
return c;
}
static int64_t raw_get_length (void *id)
{
return 0;
}
static int raw_can_seek (void *id)
{
return 0;
}
static int raw_close_stream (void *id)
{
WavpackRawContext *rcxt = id;
int i;
if (rcxt) {
for (i = 0; i < rcxt->num_segments; ++i)
if (rcxt->segments [i].sptr && rcxt->segments [i].free_required)
free (rcxt->segments [i].sptr);
if (rcxt->segments) free (rcxt->segments);
free (rcxt);
}
return 0;
}
static WavpackStreamReader64 raw_reader = {
raw_read_bytes, raw_write_bytes, raw_get_pos, raw_set_pos_abs, raw_set_pos_rel,
raw_push_back_byte, raw_get_length, raw_can_seek, NULL, raw_close_stream
};
// This function is similar to WavpackOpenFileInput() except that instead of
// providing a filename to open, the caller provides pointers to buffered
// WavPack frames (both standard and, optionally, correction data). It
// decodes only a single frame. Note that in this context, a "frame" is a
// collection of WavPack blocks that represent all the channels present. In
// the case of mono or [most] stereo streams, this is the same thing, but
// for multichannel streams each frame consists of several WavPack blocks
// (which can contain only 1 or 2 channels).
WavpackContext *WavpackOpenRawDecoder (
void *main_data, int32_t main_size,
void *corr_data, int32_t corr_size,
int16_t version, char *error, int flags, int norm_offset)
{
WavpackRawContext *raw_wv = NULL, *raw_wvc = NULL;
// if the WavPack data does not contain headers we assume Matroska-style storage
// and recreate the missing headers
if (strncmp (main_data, "wvpk", 4)) {
uint32_t multiple_blocks = 0, block_size, block_samples = 0, wphdr_flags, crc;
uint32_t main_bytes = main_size, corr_bytes = corr_size;
unsigned char *mcp = main_data;
unsigned char *ccp = corr_data;
int msi = 0, csi = 0;
raw_wv = malloc (sizeof (WavpackRawContext));
memset (raw_wv, 0, sizeof (WavpackRawContext));
if (corr_data && corr_size) {
raw_wvc = malloc (sizeof (WavpackRawContext));
memset (raw_wvc, 0, sizeof (WavpackRawContext));
}
while (main_bytes >= 12) {
if (!msi) {
block_samples = *mcp++;
block_samples += *mcp++ << 8;
block_samples += *mcp++ << 16;
block_samples += *mcp++ << 24;
main_bytes -= 4;
}
wphdr_flags = *mcp++;
wphdr_flags += *mcp++ << 8;
wphdr_flags += *mcp++ << 16;
wphdr_flags += *mcp++ << 24;
main_bytes -= 4;
// if the first block does not have the FINAL_BLOCK flag set,
// then there are multiple blocks
if (!msi && !(wphdr_flags & FINAL_BLOCK))
multiple_blocks = 1;
crc = *mcp++;
crc += *mcp++ << 8;
crc += *mcp++ << 16;
crc += *mcp++ << 24;
main_bytes -= 4;
if (multiple_blocks) {
block_size = *mcp++;
block_size += *mcp++ << 8;
block_size += *mcp++ << 16;
block_size += *mcp++ << 24;
main_bytes -= 4;
}
else
block_size = main_bytes;
if (block_size > main_bytes) {
if (error) strcpy (error, "main block overran available data!");
raw_close_stream (raw_wv);
raw_close_stream (raw_wvc);
return NULL;
}
else {
WavpackHeader *wphdr = malloc (sizeof (WavpackHeader));
memset (wphdr, 0, sizeof (WavpackHeader));
memcpy (wphdr->ckID, "wvpk", 4);
wphdr->ckSize = sizeof (WavpackHeader) - 8 + block_size;
SET_TOTAL_SAMPLES (*wphdr, block_samples);
wphdr->block_samples = block_samples;
wphdr->version = version;
wphdr->flags = wphdr_flags;
wphdr->crc = crc;
WavpackLittleEndianToNative (wphdr, WavpackHeaderFormat);
raw_wv->num_segments += 2;
raw_wv->segments = realloc (raw_wv->segments, sizeof (RawSegment) * raw_wv->num_segments);
raw_wv->segments [msi].dptr = raw_wv->segments [msi].sptr = (unsigned char *) wphdr;
raw_wv->segments [msi].eptr = raw_wv->segments [msi].dptr + sizeof (WavpackHeader);
raw_wv->segments [msi++].free_required = 1;
raw_wv->segments [msi].dptr = raw_wv->segments [msi].sptr = mcp;
raw_wv->segments [msi].eptr = raw_wv->segments [msi].dptr + block_size;
raw_wv->segments [msi++].free_required = 0;
main_bytes -= block_size;
mcp += block_size;
}
if (corr_data && corr_bytes >= 4) {
crc = *ccp++;
crc += *ccp++ << 8;
crc += *ccp++ << 16;
crc += *ccp++ << 24;
corr_bytes -= 4;
if (multiple_blocks) {
block_size = *ccp++;
block_size += *ccp++ << 8;
block_size += *ccp++ << 16;
block_size += *ccp++ << 24;
corr_bytes -= 4;
}
else
block_size = corr_bytes;
if (block_size > corr_bytes) {
if (error) strcpy (error, "correction block overran available data!");
raw_close_stream (raw_wv);
raw_close_stream (raw_wvc);
return NULL;
}
else {
WavpackHeader *wphdr = malloc (sizeof (WavpackHeader));
memset (wphdr, 0, sizeof (WavpackHeader));
memcpy (wphdr->ckID, "wvpk", 4);
wphdr->ckSize = sizeof (WavpackHeader) - 8 + block_size;
SET_TOTAL_SAMPLES (*wphdr, block_samples);
wphdr->block_samples = block_samples;
wphdr->version = version;
wphdr->flags = wphdr_flags;
wphdr->crc = crc;
WavpackLittleEndianToNative (wphdr, WavpackHeaderFormat);
raw_wvc->num_segments += 2;
raw_wvc->segments = realloc (raw_wvc->segments, sizeof (RawSegment) * raw_wvc->num_segments);
raw_wvc->segments [csi].dptr = raw_wvc->segments [csi].sptr = (unsigned char *) wphdr;
raw_wvc->segments [csi].eptr = raw_wvc->segments [csi].dptr + sizeof (WavpackHeader);
raw_wvc->segments [csi++].free_required = 1;
raw_wvc->segments [csi].dptr = raw_wvc->segments [csi].sptr = ccp;
raw_wvc->segments [csi].eptr = raw_wvc->segments [csi].dptr + block_size;
raw_wvc->segments [csi++].free_required = 0;
corr_bytes -= block_size;
ccp += block_size;
}
}
}
if (main_bytes || (corr_data && corr_bytes)) {
if (error) strcpy (error, "leftover multiblock data!");
raw_close_stream (raw_wv);
raw_close_stream (raw_wvc);
return NULL;
}
}
else { // the case of WavPack blocks with headers is much easier...
if (main_data) {
raw_wv = malloc (sizeof (WavpackRawContext));
memset (raw_wv, 0, sizeof (WavpackRawContext));
raw_wv->num_segments = 1;
raw_wv->segments = malloc (sizeof (RawSegment) * raw_wv->num_segments);
raw_wv->segments [0].dptr = raw_wv->segments [0].sptr = main_data;
raw_wv->segments [0].eptr = raw_wv->segments [0].dptr + main_size;
raw_wv->segments [0].free_required = 0;
}
if (corr_data && corr_size) {
raw_wvc = malloc (sizeof (WavpackRawContext));
memset (raw_wvc, 0, sizeof (WavpackRawContext));
raw_wvc->num_segments = 1;
raw_wvc->segments = malloc (sizeof (RawSegment) * raw_wvc->num_segments);
raw_wvc->segments [0].dptr = raw_wvc->segments [0].sptr = corr_data;
raw_wvc->segments [0].eptr = raw_wvc->segments [0].dptr + corr_size;
raw_wvc->segments [0].free_required = 0;
}
}
return WavpackOpenFileInputEx64 (&raw_reader, raw_wv, raw_wvc, error, flags | OPEN_STREAMING | OPEN_NO_CHECKSUM, norm_offset);
}
// Return the number of samples represented by the current (and in the raw case, only) frame.
uint32_t WavpackGetNumSamplesInFrame (WavpackContext *wpc)
{
if (wpc && wpc->streams && wpc->streams [0])
return wpc->streams [0]->wphdr.block_samples;
else
return -1;
}

View File

@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////////////////////
// **** WAVPACK **** //
// Hybrid Lossless Wavefile Compressor //
// Copyright (c) 1998 - 2016 David Bryant. //
// Copyright (c) 1998 - 2019 David Bryant. //
// All Rights Reserved. //
// Distributed under the BSD Software License (see license.txt) //
////////////////////////////////////////////////////////////////////////////
@ -33,7 +33,7 @@ static int seek_eof_information (WavpackContext *wpc, int64_t *final_index, int
WavpackContext *WavpackOpenFileInputEx64 (WavpackStreamReader64 *reader, void *wv_id, void *wvc_id, char *error, int flags, int norm_offset)
{
WavpackContext *wpc = malloc (sizeof (WavpackContext));
WavpackContext *wpc = (WavpackContext *)malloc (sizeof (WavpackContext));
WavpackStream *wps;
int num_blocks = 0;
unsigned char first_byte;
@ -67,7 +67,6 @@ WavpackContext *WavpackOpenFileInputEx64 (WavpackStreamReader64 *reader, void *w
}
#endif
#ifndef VER4_ONLY
if (wpc->reader->read_bytes (wpc->wv_in, &first_byte, 1) != 1) {
if (error) strcpy (error, "can't read all of WavPack file!");
return WavpackCloseFile (wpc);
@ -75,17 +74,22 @@ WavpackContext *WavpackOpenFileInputEx64 (WavpackStreamReader64 *reader, void *w
wpc->reader->push_back_byte (wpc->wv_in, first_byte);
if (first_byte == 'R')
if (first_byte == 'R') {
#ifdef ENABLE_LEGACY
return open_file3 (wpc, error);
#else
if (error) strcpy (error, "this legacy WavPack file is deprecated, use version 4.80.0 to transcode");
return WavpackCloseFile (wpc);
#endif
}
wpc->streams = malloc ((wpc->num_streams = 1) * sizeof (wpc->streams [0]));
wpc->streams = (WavpackStream **)(malloc ((wpc->num_streams = 1) * sizeof (wpc->streams [0])));
if (!wpc->streams) {
if (error) strcpy (error, "can't allocate memory");
return WavpackCloseFile (wpc);
}
wpc->streams [0] = wps = malloc (sizeof (WavpackStream));
wpc->streams [0] = wps = (WavpackStream *)malloc (sizeof (WavpackStream));
if (!wps) {
if (error) strcpy (error, "can't allocate memory");
return WavpackCloseFile (wpc);
@ -104,7 +108,7 @@ WavpackContext *WavpackOpenFileInputEx64 (WavpackStreamReader64 *reader, void *w
}
wpc->filepos += bcount;
wps->blockbuff = malloc (wps->wphdr.ckSize + 8);
wps->blockbuff = (unsigned char *)malloc (wps->wphdr.ckSize + 8);
if (!wps->blockbuff) {
if (error) strcpy (error, "can't allocate memory");
return WavpackCloseFile (wpc);
@ -116,25 +120,40 @@ WavpackContext *WavpackOpenFileInputEx64 (WavpackStreamReader64 *reader, void *w
return WavpackCloseFile (wpc);
}
// if block does not verify, flag error, free buffer, and continue
if (!WavpackVerifySingleBlock (wps->blockbuff, !(flags & OPEN_NO_CHECKSUM))) {
wps->wphdr.block_samples = 0;
free (wps->blockbuff);
wps->blockbuff = NULL;
wpc->crc_errors++;
continue;
}
wps->init_done = FALSE;
if (wps->wphdr.block_samples && !(flags & OPEN_STREAMING)) {
if (GET_BLOCK_INDEX (wps->wphdr) || GET_TOTAL_SAMPLES (wps->wphdr) == -1) {
wpc->initial_index = GET_BLOCK_INDEX (wps->wphdr);
if (wps->wphdr.block_samples) {
if (flags & OPEN_STREAMING)
SET_BLOCK_INDEX (wps->wphdr, 0);
else if (wpc->total_samples == -1) {
if (GET_BLOCK_INDEX (wps->wphdr) || GET_TOTAL_SAMPLES (wps->wphdr) == -1) {
wpc->initial_index = GET_BLOCK_INDEX (wps->wphdr);
SET_BLOCK_INDEX (wps->wphdr, 0);
if (wpc->reader->can_seek (wpc->wv_in)) {
int64_t final_index = -1;
if (wpc->reader->can_seek (wpc->wv_in)) {
int64_t final_index = -1;
seek_eof_information (wpc, &final_index, FALSE);
seek_eof_information (wpc, &final_index, FALSE);
if (final_index != -1)
wpc->total_samples = final_index - wpc->initial_index;
if (final_index != -1)
wpc->total_samples = final_index - wpc->initial_index;
}
}
else
wpc->total_samples = GET_TOTAL_SAMPLES (wps->wphdr);
}
else
wpc->total_samples = GET_TOTAL_SAMPLES (wps->wphdr);
}
else if (wpc->total_samples == -1 && !GET_BLOCK_INDEX (wps->wphdr) && GET_TOTAL_SAMPLES (wps->wphdr))
wpc->total_samples = GET_TOTAL_SAMPLES (wps->wphdr);
if (wpc->wvc_in && wps->wphdr.block_samples && (wps->wphdr.flags & HYBRID_FLAG)) {
unsigned char ch;
@ -158,6 +177,11 @@ WavpackContext *WavpackOpenFileInputEx64 (WavpackStreamReader64 *reader, void *w
return WavpackCloseFile (wpc);
}
if (!wps->wphdr.block_samples) { // free blockbuff if we're going to loop again
free (wps->blockbuff);
wps->blockbuff = NULL;
}
wps->init_done = TRUE;
}
@ -173,6 +197,7 @@ WavpackContext *WavpackOpenFileInputEx64 (WavpackStreamReader64 *reader, void *w
wpc->reduced_channels = (wps->wphdr.flags & MONO_FLAG) ? 1 : 2;
if (wps->wphdr.flags & DSD_FLAG) {
#ifdef ENABLE_DSD
if (flags & OPEN_DSD_NATIVE) {
wpc->config.bytes_per_sample = 1;
wpc->config.bits_per_sample = 8;
@ -188,6 +213,10 @@ WavpackContext *WavpackOpenFileInputEx64 (WavpackStreamReader64 *reader, void *w
if (error) strcpy (error, "not configured to handle DSD WavPack files!");
return WavpackCloseFile (wpc);
}
#else
if (error) strcpy (error, "not configured to handle DSD WavPack files!");
return WavpackCloseFile (wpc);
#endif
}
else {
wpc->config.bytes_per_sample = (wps->wphdr.flags & BYTES_STORED) + 1;
@ -214,7 +243,7 @@ WavpackContext *WavpackOpenFileInputEx64 (WavpackStreamReader64 *reader, void *w
int WavpackGetVersion (WavpackContext *wpc)
{
if (wpc) {
#ifndef VER4_ONLY
#ifdef ENABLE_LEGACY
if (wpc->stream3)
return get_version3 (wpc);
#endif
@ -334,7 +363,7 @@ int unpack_init (WavpackContext *wpc)
// These functions handle specific metadata types and are called directly
// during WavPack block parsing by process_metadata() at the bottom.
// This function initialzes the main bitstream for audio samples, which must
// This function initializes the main bitstream for audio samples, which must
// be in the "wv" file.
static int init_wv_bitstream (WavpackStream *wps, WavpackMetadata *wpmd)
@ -346,7 +375,7 @@ static int init_wv_bitstream (WavpackStream *wps, WavpackMetadata *wpmd)
return TRUE;
}
// This function initialzes the "correction" bitstream for audio samples,
// This function initializes the "correction" bitstream for audio samples,
// which currently must be in the "wvc" file.
static int init_wvc_bitstream (WavpackStream *wps, WavpackMetadata *wpmd)
@ -358,7 +387,7 @@ static int init_wvc_bitstream (WavpackStream *wps, WavpackMetadata *wpmd)
return TRUE;
}
// This function initialzes the "extra" bitstream for audio samples which
// This function initializes the "extra" bitstream for audio samples which
// contains the information required to losslessly decompress 32-bit float data
// or integer data that exceeds 24 bits. This bitstream is in the "wv" file
// for pure lossless data or the "wvc" file for hybrid lossless. This data
@ -367,7 +396,7 @@ static int init_wvc_bitstream (WavpackStream *wps, WavpackMetadata *wpmd)
static int init_wvx_bitstream (WavpackStream *wps, WavpackMetadata *wpmd)
{
unsigned char *cp = wpmd->data;
unsigned char *cp = (unsigned char *)wpmd->data;
if (wpmd->byte_length <= 4 || (wpmd->byte_length & 1))
return FALSE;
@ -388,7 +417,7 @@ static int init_wvx_bitstream (WavpackStream *wps, WavpackMetadata *wpmd)
static int read_int32_info (WavpackStream *wps, WavpackMetadata *wpmd)
{
int bytecnt = wpmd->byte_length;
char *byteptr = wpmd->data;
char *byteptr = (char *)wpmd->data;
if (bytecnt != 4)
return FALSE;
@ -404,7 +433,7 @@ static int read_int32_info (WavpackStream *wps, WavpackMetadata *wpmd)
static int read_float_info (WavpackStream *wps, WavpackMetadata *wpmd)
{
int bytecnt = wpmd->byte_length;
char *byteptr = wpmd->data;
char *byteptr = (char *)wpmd->data;
if (bytecnt != 4)
return FALSE;
@ -423,7 +452,7 @@ static int read_float_info (WavpackStream *wps, WavpackMetadata *wpmd)
static int read_channel_info (WavpackContext *wpc, WavpackMetadata *wpmd)
{
int bytecnt = wpmd->byte_length, shift = 0, mask_bits;
unsigned char *byteptr = wpmd->data;
unsigned char *byteptr = (unsigned char *)wpmd->data;
uint32_t mask = 0;
if (!bytecnt || bytecnt > 7)
@ -439,7 +468,7 @@ static int read_channel_info (WavpackContext *wpc, WavpackMetadata *wpmd)
if (wpc->config.num_channels < wpc->max_streams)
return FALSE;
byteptr += 3;
mask = *byteptr++;
mask |= (uint32_t) *byteptr++ << 8;
@ -470,12 +499,29 @@ static int read_channel_info (WavpackContext *wpc, WavpackMetadata *wpmd)
return TRUE;
}
// Read multichannel identity information from metadata. Data is an array of
// unsigned characters representing any channels in the file that DO NOT
// match one the 18 Microsoft standard channels (and are represented in the
// channel mask). A value of 0 is not allowed and 0xff means an unknown or
// undefined channel identity.
static int read_channel_identities (WavpackContext *wpc, WavpackMetadata *wpmd)
{
if (!wpc->channel_identities) {
wpc->channel_identities = (unsigned char *)malloc (wpmd->byte_length + 1);
memcpy (wpc->channel_identities, wpmd->data, wpmd->byte_length);
wpc->channel_identities [wpmd->byte_length] = 0;
}
return TRUE;
}
// Read configuration information from metadata.
static int read_config_info (WavpackContext *wpc, WavpackMetadata *wpmd)
{
int bytecnt = wpmd->byte_length;
unsigned char *byteptr = wpmd->data;
unsigned char *byteptr = (unsigned char *)wpmd->data;
if (bytecnt >= 3) {
wpc->config.flags &= 0xff;
@ -506,7 +552,7 @@ static int read_config_info (WavpackContext *wpc, WavpackMetadata *wpmd)
static int read_new_config_info (WavpackContext *wpc, WavpackMetadata *wpmd)
{
int bytecnt = wpmd->byte_length;
unsigned char *byteptr = wpmd->data;
unsigned char *byteptr = (unsigned char *)wpmd->data;
wpc->version_five = 1; // just having this block signals version 5.0
@ -519,7 +565,7 @@ static int read_new_config_info (WavpackContext *wpc, WavpackMetadata *wpmd)
// if there's any data, the first two bytes are file_format and qmode flags
if (bytecnt) {
if (bytecnt >= 2) {
wpc->file_format = *byteptr++;
wpc->config.qmode = (wpc->config.qmode & ~0xff) | *byteptr++;
bytecnt -= 2;
@ -544,7 +590,7 @@ static int read_new_config_info (WavpackContext *wpc, WavpackMetadata *wpmd)
if (bytecnt > nchans)
return FALSE;
wpc->channel_reordering = malloc (nchans);
wpc->channel_reordering = (unsigned char *)malloc (nchans);
// note that redundant reordering info is not stored, so we fill in the rest
@ -552,6 +598,10 @@ static int read_new_config_info (WavpackContext *wpc, WavpackMetadata *wpmd)
for (i = 0; i < nchans; ++i)
if (bytecnt) {
wpc->channel_reordering [i] = *byteptr++;
if (wpc->channel_reordering [i] >= nchans) // make sure index is in range
wpc->channel_reordering [i] = 0;
bytecnt--;
}
else
@ -572,7 +622,7 @@ static int read_new_config_info (WavpackContext *wpc, WavpackMetadata *wpmd)
static int read_sample_rate (WavpackContext *wpc, WavpackMetadata *wpmd)
{
int bytecnt = wpmd->byte_length;
unsigned char *byteptr = wpmd->data;
unsigned char *byteptr = (unsigned char *)wpmd->data;
if (bytecnt == 3 || bytecnt == 4) {
wpc->config.sample_rate = (int32_t) *byteptr++;
@ -597,7 +647,7 @@ static int read_sample_rate (WavpackContext *wpc, WavpackMetadata *wpmd)
static int read_wrapper_data (WavpackContext *wpc, WavpackMetadata *wpmd)
{
if ((wpc->open_flags & OPEN_WRAPPER) && wpc->wrapper_bytes < MAX_WRAPPER_BYTES && wpmd->byte_length) {
wpc->wrapper_data = realloc (wpc->wrapper_data, wpc->wrapper_bytes + wpmd->byte_length);
wpc->wrapper_data = (unsigned char *)realloc (wpc->wrapper_data, wpc->wrapper_bytes + wpmd->byte_length);
if (!wpc->wrapper_data)
return FALSE;
memcpy (wpc->wrapper_data + wpc->wrapper_bytes, wpmd->data, wpmd->byte_length);
@ -685,6 +735,9 @@ static int process_metadata (WavpackContext *wpc, WavpackMetadata *wpmd)
case ID_CHANNEL_INFO:
return read_channel_info (wpc, wpmd);
case ID_CHANNEL_IDENTITIES:
return read_channel_identities (wpc, wpmd);
case ID_CONFIG_BLOCK:
return read_config_info (wpc, wpmd);
@ -704,7 +757,12 @@ static int process_metadata (WavpackContext *wpc, WavpackMetadata *wpmd)
return init_wvx_bitstream (wps, wpmd);
case ID_DSD_BLOCK:
#ifdef ENABLE_DSD
return init_dsd_block (wpc, wpmd);
#else
strcpy (wpc->error_message, "not configured to handle DSD WavPack files!");
return FALSE;
#endif
case ID_ALT_HEADER: case ID_ALT_TRAILER:
if (!(wpc->open_flags & OPEN_ALT_TYPES))
@ -732,6 +790,15 @@ static int process_metadata (WavpackContext *wpc, WavpackMetadata *wpmd)
wpc->file_extension [wpmd->byte_length] = 0;
}
return TRUE;
// we don't actually verify the checksum here (it's done right after the
// block is read), but it's a good indicator of version 5 files
case ID_BLOCK_CHECKSUM:
wpc->version_five = 1;
return TRUE;
default:
return (wpmd->id & ID_OPTIONAL_DATA) ? TRUE : FALSE;
}
@ -887,7 +954,7 @@ static int match_wvc_header (WavpackHeader *wv_hdr, WavpackHeader *wvc_hdr)
return (wvci - wvi < 0) ? 1 : -1;
}
if (GET_BLOCK_INDEX (*wvc_hdr) > GET_BLOCK_INDEX (*wv_hdr))
if (((GET_BLOCK_INDEX (*wvc_hdr) - GET_BLOCK_INDEX (*wv_hdr)) << 24) < 0)
return 1;
else
return -1;
@ -905,6 +972,7 @@ int read_wvc_block (WavpackContext *wpc)
{
WavpackStream *wps = wpc->streams [wpc->current_stream];
int64_t bcount, file2pos;
WavpackHeader orig_wphdr;
WavpackHeader wphdr;
int compare_result;
@ -918,6 +986,8 @@ int read_wvc_block (WavpackContext *wpc)
return FALSE;
}
memcpy (&orig_wphdr, &wphdr, 32); // save original header for verify step
if (wpc->open_flags & OPEN_STREAMING)
SET_BLOCK_INDEX (wphdr, wps->sample_index = 0);
else
@ -929,13 +999,12 @@ int read_wvc_block (WavpackContext *wpc)
compare_result = match_wvc_header (&wps->wphdr, &wphdr);
if (!compare_result) {
wps->block2buff = malloc (wphdr.ckSize + 8);
wps->block2buff = (unsigned char *)malloc (wphdr.ckSize + 8);
if (!wps->block2buff)
return FALSE;
memcpy (wps->block2buff, &wphdr, 32);
if (wpc->reader->read_bytes (wpc->wvc_in, wps->block2buff + 32, wphdr.ckSize - 24) !=
wphdr.ckSize - 24 || (wphdr.flags & UNKNOWN_FLAGS)) {
wphdr.ckSize - 24) {
free (wps->block2buff);
wps->block2buff = NULL;
wps->wvc_skip = TRUE;
@ -943,7 +1012,19 @@ int read_wvc_block (WavpackContext *wpc)
return FALSE;
}
memcpy (wps->block2buff, &orig_wphdr, 32);
// don't use corrupt blocks
if (!WavpackVerifySingleBlock (wps->block2buff, !(wpc->open_flags & OPEN_NO_CHECKSUM))) {
free (wps->block2buff);
wps->block2buff = NULL;
wps->wvc_skip = TRUE;
wpc->crc_errors++;
return TRUE;
}
wps->wvc_skip = FALSE;
memcpy (wps->block2buff, &wphdr, 32);
memcpy (&wps->wphdr, &wphdr, 32);
return TRUE;
}
@ -981,7 +1062,7 @@ static int seek_eof_information (WavpackContext *wpc, int64_t *final_index, int
// start 1MB from the end-of-file, or from the start if the file is not that big
if (reader->get_length (id) > 1048576LL)
if (reader->get_length (id) > (int64_t) 1048576)
reader->set_pos_rel (id, -1048576, SEEK_END);
else
reader->set_pos_abs (id, 0);
@ -1013,7 +1094,7 @@ static int seek_eof_information (WavpackContext *wpc, int64_t *final_index, int
// beginning of the file) and try again
if (!blocks) {
if (current_pos > 2000000LL)
if (current_pos > (int64_t) 2000000)
reader->set_pos_rel (id, -2000000, SEEK_CUR);
else
reader->set_pos_abs (id, 0);
@ -1041,7 +1122,7 @@ static int seek_eof_information (WavpackContext *wpc, int64_t *final_index, int
audio_blocks++;
}
else if (!audio_blocks) {
if (current_pos > 1048576LL)
if (current_pos > (int64_t) 1048576)
reader->set_pos_rel (id, -1048576, SEEK_CUR);
else
reader->set_pos_abs (id, 0);
@ -1082,7 +1163,7 @@ static int seek_eof_information (WavpackContext *wpc, int64_t *final_index, int
meta_id &= ID_UNIQUE;
if (get_wrapper && (meta_id == ID_RIFF_TRAILER || (alt_types && meta_id == ID_ALT_TRAILER)) && meta_bc) {
wpc->wrapper_data = realloc (wpc->wrapper_data, wpc->wrapper_bytes + meta_bc);
wpc->wrapper_data = (unsigned char *)realloc (wpc->wrapper_data, wpc->wrapper_bytes + meta_bc);
if (!wpc->wrapper_data) {
reader->set_pos_abs (id, restore_pos);
@ -1115,3 +1196,89 @@ static int seek_eof_information (WavpackContext *wpc, int64_t *final_index, int
}
}
}
// Quickly verify the referenced block. It is assumed that the WavPack header has been converted
// to native endian format. If a block checksum is performed, that is done in little-endian
// (file) format. It is also assumed that the caller has made sure that the block length
// indicated in the header is correct (we won't overflow the buffer). If a checksum is present,
// then it is checked, otherwise we just check that all the metadata blocks are formatted
// correctly (without looking at their contents). Returns FALSE for bad block.
int WavpackVerifySingleBlock (unsigned char *buffer, int verify_checksum)
{
WavpackHeader *wphdr = (WavpackHeader *) buffer;
uint32_t checksum_passed = 0, bcount, meta_bc;
unsigned char *dp, meta_id, c1, c2;
if (strncmp (wphdr->ckID, "wvpk", 4) || wphdr->ckSize + 8 < sizeof (WavpackHeader))
return FALSE;
bcount = wphdr->ckSize - sizeof (WavpackHeader) + 8;
dp = (unsigned char *)(wphdr + 1);
while (bcount >= 2) {
meta_id = *dp++;
c1 = *dp++;
meta_bc = c1 << 1;
bcount -= 2;
if (meta_id & ID_LARGE) {
if (bcount < 2)
return FALSE;
c1 = *dp++;
c2 = *dp++;
meta_bc += ((uint32_t) c1 << 9) + ((uint32_t) c2 << 17);
bcount -= 2;
}
if (bcount < meta_bc)
return FALSE;
if (verify_checksum && (meta_id & ID_UNIQUE) == ID_BLOCK_CHECKSUM) {
#ifdef BITSTREAM_SHORTS
uint16_t *csptr = (uint16_t*) buffer;
#else
unsigned char *csptr = buffer;
#endif
int wcount = (int)(dp - 2 - buffer) >> 1;
uint32_t csum = (uint32_t) -1;
if ((meta_id & ID_ODD_SIZE) || meta_bc < 2 || meta_bc > 4)
return FALSE;
#ifdef BITSTREAM_SHORTS
while (wcount--)
csum = (csum * 3) + *csptr++;
#else
WavpackNativeToLittleEndian ((WavpackHeader *) buffer, WavpackHeaderFormat);
while (wcount--) {
csum = (csum * 3) + csptr [0] + (csptr [1] << 8);
csptr += 2;
}
WavpackLittleEndianToNative ((WavpackHeader *) buffer, WavpackHeaderFormat);
#endif
if (meta_bc == 4) {
if (*dp != (csum & 0xff) || dp[1] != ((csum >> 8) & 0xff) || dp[2] != ((csum >> 16) & 0xff) || dp[3] != ((csum >> 24) & 0xff))
return FALSE;
}
else {
csum ^= csum >> 16;
if (*dp != (csum & 0xff) || dp[1] != ((csum >> 8) & 0xff))
return FALSE;
}
checksum_passed++;
}
bcount -= meta_bc;
dp += meta_bc;
}
return (bcount == 0) && (!verify_checksum || !(wphdr->flags & HAS_CHECKSUM) || checksum_passed);
}

View File

@ -336,6 +336,19 @@ static void write_channel_info (WavpackContext *wpc, WavpackMetadata *wpmd)
wpmd->byte_length = (int32_t)(byteptr - (char *) wpmd->data);
}
// Allocate room for and copy the multichannel identities into the specified
// metadata structure. Data is an array of unsigned characters representing
// any channels in the file that DO NOT match one the 18 Microsoft standard
// channels (and are represented in the channel mask). A value of 0 is not
// allowed and 0xff means an unknown or undefined channel identity.
static void write_channel_identities_info (WavpackContext *wpc, WavpackMetadata *wpmd)
{
wpmd->byte_length = (int) strlen ((char *) wpc->channel_identities);
wpmd->data = strdup ((char *) wpc->channel_identities);
wpmd->id = ID_CHANNEL_IDENTITIES;
}
// Allocate room for and copy the configuration information into the specified
// metadata structure. Currently, we just store the upper 3 bytes of
// config.flags and only in the first block of audio data. Note that this is
@ -374,7 +387,7 @@ static void write_new_config_info (WavpackContext *wpc, WavpackMetadata *wpmd)
wpmd->id = ID_NEW_CONFIG_BLOCK;
if (wpc->file_format || wpc->config.qmode || wpc->channel_layout) {
if (wpc->file_format || (wpc->config.qmode & 0xff) || wpc->channel_layout) {
*byteptr++ = (char) wpc->file_format;
*byteptr++ = (char) wpc->config.qmode;
@ -454,6 +467,13 @@ int pack_block (WavpackContext *wpc, int32_t *buffer)
int32_t sample_count = wps->wphdr.block_samples, *orig_data = NULL;
int dynamic_shaping_done = FALSE;
// This is done first because this code can potentially change the size of the block about to
// be encoded. This can happen because the dynamic noise shaping algorithm wants to send a
// shorter block because the desired noise-shaping profile is changing quickly. It can also
// be that the --merge-blocks feature wants to create a longer block because it combines areas
// with equal redundancy. These are not applicable for anything besides the first stream of
// the file and they are not applicable with float data or >24-bit data.
if (!wpc->current_stream && !(flags & FLOAT_DATA) && (flags & MAG_MASK) >> MAG_LSB < 24) {
if ((wpc->config.flags & CONFIG_DYNAMIC_SHAPING) && !wpc->config.block_samples) {
dynamic_noise_shaping (wpc, buffer, TRUE);
@ -462,7 +482,7 @@ int pack_block (WavpackContext *wpc, int32_t *buffer)
}
else if (wpc->block_boundary && sample_count >= (int32_t) wpc->block_boundary * 2) {
int bc = sample_count / wpc->block_boundary, chans = (flags & MONO_DATA) ? 1 : 2;
int res = scan_redundancy (buffer, wpc->block_boundary * chans), i;
int res = scan_redundancy (buffer, wpc->block_boundary * chans), i;
for (i = 1; i < bc; ++i)
if (res != scan_redundancy (buffer + (i * wpc->block_boundary * chans),
@ -474,10 +494,9 @@ int pack_block (WavpackContext *wpc, int32_t *buffer)
}
// This code scans stereo data to check whether it can be stored as mono data
// (i.e., all L/R samples identical). This used to be an option because
// decoders < 4.30 pre-dated this feature, but now it's standard.
// (i.e., all L/R samples identical). Only available with MAX_STREAM_VERS.
if (!(flags & MONO_FLAG)) {
if (!(flags & MONO_FLAG) && wpc->stream_version == MAX_STREAM_VERS) {
int32_t lor = 0, diff = 0;
int32_t *sptr, *dptr, i;
@ -511,6 +530,9 @@ int pack_block (WavpackContext *wpc, int32_t *buffer)
}
}
// This is where we handle any fixed shift which occurs when the integer size does not evenly fit
// in bytes (like 12-bit or 20-bit) and is the same for the entire file (not based on scanning)
if (flags & SHIFT_MASK) {
int shift = (flags & SHIFT_MASK) >> SHIFT_LSB;
int mag = (flags & MAG_MASK) >> MAG_LSB;
@ -534,12 +556,23 @@ int pack_block (WavpackContext *wpc, int32_t *buffer)
wps->wphdr.flags = flags;
}
if ((flags & FLOAT_DATA) || (flags & MAG_MASK) >> MAG_LSB >= 24) {
// The regular WavPack decorrelation and entropy encoding can handle up to 24-bit integer data. If
// we have float data or integers larger than 24-bit, then we have to potentially do extra processing.
// For lossy encoding, we can simply convert this data in-place to 24-bit data and encode and sent
// that, along with some metadata about how to restore the original format (even if the restoration
// is not exact). However, for lossless operation we must make a copy of the original data that will
// be used to create a "extension stream" that will allow verbatim restoration of the original data.
// In the hybrid mode that extension goes in the correction file, otherwise it goes in the mail file.
if ((flags & FLOAT_DATA) || (flags & MAG_MASK) >> MAG_LSB >= 24) { // if float data or >24-bit integers...
// if lossless we have to copy the data to use later...
if ((!(flags & HYBRID_FLAG) || wpc->wvc_flag) && !(wpc->config.flags & CONFIG_SKIP_WVX)) {
orig_data = malloc (sizeof (f32) * ((flags & MONO_DATA) ? sample_count : sample_count * 2));
memcpy (orig_data, buffer, sizeof (f32) * ((flags & MONO_DATA) ? sample_count : sample_count * 2));
if (flags & FLOAT_DATA) {
if (flags & FLOAT_DATA) { // if lossless float data come here
wps->float_norm_exp = wpc->config.float_norm_exp;
if (!scan_float_data (wps, (f32 *) buffer, (flags & MONO_DATA) ? sample_count : sample_count * 2)) {
@ -547,14 +580,14 @@ int pack_block (WavpackContext *wpc, int32_t *buffer)
orig_data = NULL;
}
}
else {
else { // otherwise lossless > 24-bit integers
if (!scan_int32_data (wps, buffer, (flags & MONO_DATA) ? sample_count : sample_count * 2)) {
free (orig_data);
orig_data = NULL;
}
}
}
else {
else { // otherwise, we're lossy, so no copy
if (flags & FLOAT_DATA) {
wps->float_norm_exp = wpc->config.float_norm_exp;
@ -565,20 +598,30 @@ int pack_block (WavpackContext *wpc, int32_t *buffer)
wpc->lossy_blocks = TRUE;
}
// if there's any chance of magnitude change, clear the noise-shaping error term
// and also reset the entropy encoder (which this does)
wps->dc.error [0] = wps->dc.error [1] = 0;
wps->num_terms = 0;
}
// if 24-bit integers or less we do a "quick" scan which just scans for redundancy and does NOT set the flag's "magnitude" value
else {
scan_int32_quick (wps, buffer, (flags & MONO_DATA) ? sample_count : sample_count * 2);
if (wps->shift != wps->int32_zeros + wps->int32_ones + wps->int32_dups) {
if (wps->shift != wps->int32_zeros + wps->int32_ones + wps->int32_dups) { // detect a change in any redundancy shifting here
wps->shift = wps->int32_zeros + wps->int32_ones + wps->int32_dups;
wps->num_terms = 0;
wps->dc.error [0] = wps->dc.error [1] = 0; // on a change, clear the noise-shaping error term and
wps->num_terms = 0; // also reset the entropy encoder (which this does)
}
}
if ((wpc->config.flags & CONFIG_DYNAMIC_SHAPING) && !dynamic_shaping_done)
if ((wpc->config.flags & CONFIG_DYNAMIC_SHAPING) && !dynamic_shaping_done) // calculate dynamic noise profile
dynamic_noise_shaping (wpc, buffer, FALSE);
// In some cases we need to start the decorrelation and entropy encoding from scratch. This
// could be because we switched from stereo to mono encoding or because the magnitude of
// the data changed, or just because this is the first block.
if (!wps->num_passes && !wps->num_terms) {
wps->num_passes = 1;
@ -590,6 +633,8 @@ int pack_block (WavpackContext *wpc, int32_t *buffer)
wps->num_passes = 0;
}
// actually pack the block here and return on an error (which pretty much can only be a block buffer overrun)
if (!pack_samples (wpc, buffer)) {
wps->wphdr.flags = sflags;
@ -601,6 +646,8 @@ int pack_block (WavpackContext *wpc, int32_t *buffer)
else
wps->wphdr.flags = sflags;
// potentially move any unused dynamic noise shaping profile data to use next time
if (wps->dc.shaping_data) {
if (wps->dc.shaping_samples != sample_count)
memmove (wps->dc.shaping_data, wps->dc.shaping_data + sample_count,
@ -609,6 +656,10 @@ int pack_block (WavpackContext *wpc, int32_t *buffer)
wps->dc.shaping_samples -= sample_count;
}
// finally, if we're doing lossless float data or lossless >24-bit integers, this is where we take the
// original data that we saved earlier and create the "extension" stream containing the information
// required to refine the "lossy" 24-bit data into the lossless original
if (orig_data) {
uint32_t data_count;
unsigned char *cptr;
@ -866,6 +917,12 @@ void send_general_metadata (WavpackContext *wpc)
write_channel_info (wpc, &wpmd);
copy_metadata (&wpmd, wps->blockbuff, wps->blockend);
free_metadata (&wpmd);
if (wpc->channel_identities) {
write_channel_identities_info (wpc, &wpmd);
copy_metadata (&wpmd, wps->blockbuff, wps->blockend);
free_metadata (&wpmd);
}
}
if ((flags & INITIAL_BLOCK) && !wps->sample_index) {
@ -902,7 +959,7 @@ void send_general_metadata (WavpackContext *wpc)
(pack_cpu_has_feature_x86 (CPU_FEATURE_MMX) ? \
scan_max_magnitude_x86 (a, b) : \
scan_max_magnitude (a, b))
#elif defined(OPT_ASM_X64) && (defined (_WIN64) || defined(__CYGWIN__) || defined(__MINGW64__))
#elif defined(OPT_ASM_X64) && (defined (_WIN64) || defined(__CYGWIN__) || defined(__MINGW64__) || defined(__midipix__))
#define DECORR_STEREO_PASS pack_decorr_stereo_pass_x64win
#define DECORR_MONO_BUFFER pack_decorr_mono_buffer_x64win
#define SCAN_MAX_MAGNITUDE scan_max_magnitude_x64win

View File

@ -10,6 +10,8 @@
// This module actually handles the compression of the DSD audio data.
#ifdef ENABLE_DSD
#include <stdlib.h>
#include <string.h>
#include <math.h>
@ -165,7 +167,6 @@ int pack_dsd_block (WavpackContext *wpc, int32_t *buffer)
// #define DSD_BYTE_READY(low,high) (!(((low) ^ (high)) >> 24))
#define DSD_BYTE_READY(low,high) (!(((low) ^ (high)) & 0xff000000))
#define MAX_HISTORY_BITS 5
#define MAX_PROBABILITY 0xa0 // set to 0xff to disable RLE encoding for probabilities table
#if (MAX_PROBABILITY < 0xff)
@ -351,8 +352,8 @@ static int encode_buffer_fast (WavpackStream *wps, int32_t *buffer, int num_samp
// normally only happen with large blocks or poorly compressible data. The target is to guarantee that the total memory
// required for all three decode tables will be 2K bytes per history bin.
while (total_summed_probabilities > history_bins * 1280) {
int max_sum = 0, sum_values = 0, largest_bin;
while (total_summed_probabilities > history_bins * MAX_BYTES_PER_BIN) {
int max_sum = 0, sum_values = 0, largest_bin = 0;
for (p0 = 0; p0 < history_bins; ++p0)
if (summed_probabilities [p0] [255] > max_sum) {
@ -452,7 +453,7 @@ static int encode_buffer_fast (WavpackStream *wps, int32_t *buffer, int num_samp
#define DOWN 0x00010000
#define DECAY 8
#define PRECISION 24
#define PRECISION 20
#define VALUE_ONE (1 << PRECISION)
#define PRECISION_USE 12
@ -505,20 +506,16 @@ static int normalize_ptable (int *ptable)
static int encode_buffer_high (WavpackStream *wps, int32_t *buffer, int num_samples, unsigned char *destination)
{
uint32_t flags = wps->wphdr.flags, crc = 0xffffffff;
unsigned int high = 0xffffffff, low = 0;
int channel, stereo = (wps->wphdr.flags & MONO_DATA) ? 0 : 1;
uint32_t crc = 0xffffffff, high = 0xffffffff, low = 0;
unsigned char *dp = destination, *ep;
DSDfilters *sp;
int channel;
if (!(flags & MONO_DATA))
num_samples *= 2;
if (num_samples < 280)
if (num_samples * (stereo + 1) < 280)
return -1;
*dp++ = 2;
ep = destination + num_samples - 10;
*dp++ = 3;
ep = destination + num_samples * (stereo + 1) - 10;
if (!wps->sample_index) {
if (!wps->dsd.ptable)
@ -543,58 +540,55 @@ static int encode_buffer_high (WavpackStream *wps, int32_t *buffer, int num_samp
*dp++ = RATE_S;
}
for (channel = 0; channel < ((flags & MONO_DATA) ? 1 : 2); ++channel) {
for (channel = 0; channel <= stereo; ++channel) {
sp = wps->dsd.filters + channel;
*dp++ = (sp->filter1 + 32768) >> 16;
*dp++ = (sp->filter2 + 32768) >> 16;
*dp++ = (sp->filter3 + 32768) >> 16;
*dp++ = (sp->filter4 + 32768) >> 16;
*dp++ = (sp->filter5 + 32768) >> 16;
*dp = sp->filter1 >> (PRECISION - 8);
sp->filter1 = *dp++ << (PRECISION - 8);
*dp = sp->filter2 >> (PRECISION - 8);
sp->filter2 = *dp++ << (PRECISION - 8);
*dp = sp->filter3 >> (PRECISION - 8);
sp->filter3 = *dp++ << (PRECISION - 8);
*dp = sp->filter4 >> (PRECISION - 8);
sp->filter4 = *dp++ << (PRECISION - 8);
*dp = sp->filter5 >> (PRECISION - 8);
sp->filter5 = *dp++ << (PRECISION - 8);
*dp++ = sp->factor;
*dp++ = sp->factor >> 8;
sp->filter1 = ((sp->filter1 + 32768) >> 16) << 16;
sp->filter2 = ((sp->filter2 + 32768) >> 16) << 16;
sp->filter3 = ((sp->filter3 + 32768) >> 16) << 16;
sp->filter4 = ((sp->filter4 + 32768) >> 16) << 16;
sp->filter5 = ((sp->filter5 + 32768) >> 16) << 16;
sp->filter6 = 0;
sp->factor = (sp->factor << 16) >> 16;
}
channel = 0;
sp = wps->dsd.filters;
while (dp < ep && num_samples--) {
int byte = (*buffer++ & 0xff), bitcount = 8;
sp = wps->dsd.filters + channel;
int bitcount = 8;
crc += (crc << 1) + byte;
crc += (crc << 1) + (sp->byte = *buffer++ & 0xff);
sp [0].value = sp [0].filter1 - sp [0].filter5 + ((sp [0].filter6 * sp [0].factor) >> 2);
if (stereo) {
crc += (crc << 1) + (sp [1].byte = *buffer++ & 0xff);
sp [1].value = sp [1].filter1 - sp [1].filter5 + ((sp [1].filter6 * sp [1].factor) >> 2);
}
while (bitcount--) {
int value = sp->filter1 - sp->filter5 + sp->filter6 * (sp->factor >> 2);
int index = (value >> (PRECISION - PRECISION_USE)) & PTABLE_MASK;
int *val = wps->dsd.ptable + index;
int32_t *pp = wps->dsd.ptable + ((sp [0].value >> (PRECISION - PRECISION_USE)) & PTABLE_MASK);
value += sp->filter6 << 3;
if (byte & 0x80) {
high = low + (((high - low) >> 24) ? ((high - low) >> 8) * (*val >> 16) : (((high - low) * (*val >> 16)) >> 8));
*val += (UP - *val) >> DECAY;
sp->filter1 += (VALUE_ONE - sp->filter1) >> 6;
sp->filter2 += (VALUE_ONE - sp->filter2) >> 4;
if ((value ^ (value - (sp->filter6 << 4))) < 0)
sp->factor -= (value >> 31) | 1;
if (sp [0].byte & 0x80) {
high = low + ((high - low) >> 8) * (*pp >> 16);
*pp += (UP - *pp) >> DECAY;
sp [0].filter0 = -1;
}
else {
low += 1 + (((high - low) >> 24) ? ((high - low) >> 8) * (*val >> 16) : (((high - low) * (*val >> 16)) >> 8));
*val += (DOWN - *val) >> DECAY;
sp->filter1 -= sp->filter1 >> 6;
sp->filter2 -= sp->filter2 >> 4;
if ((value ^ (value - (sp->filter6 << 4))) < 0)
sp->factor += (value >> 31) | 1;
low += 1 + ((high - low) >> 8) * (*pp >> 16);
*pp += (DOWN - *pp) >> DECAY;
sp [0].filter0 = 0;
}
while (DSD_BYTE_READY (high, low)) {
@ -603,15 +597,57 @@ static int encode_buffer_high (WavpackStream *wps, int32_t *buffer, int num_samp
low <<= 8;
}
sp->filter3 += (sp->filter2 - sp->filter3) >> 4;
sp->filter4 += (sp->filter3 - sp->filter4) >> 4;
sp->filter5 += value = (sp->filter4 - sp->filter5) >> 4;
sp->filter6 += (value - sp->filter6) >> 3;
byte <<= 1;
sp [0].value += sp [0].filter6 << 3;
sp [0].factor += (((sp [0].value ^ sp [0].filter0) >> 31) | 1) & ((sp [0].value ^ (sp [0].value - (sp [0].filter6 << 4))) >> 31);
sp [0].filter1 += ((sp [0].filter0 & VALUE_ONE) - sp [0].filter1) >> 6;
sp [0].filter2 += ((sp [0].filter0 & VALUE_ONE) - sp [0].filter2) >> 4;
sp [0].filter3 += (sp [0].filter2 - sp [0].filter3) >> 4;
sp [0].filter4 += (sp [0].filter3 - sp [0].filter4) >> 4;
sp [0].value = (sp [0].filter4 - sp [0].filter5) >> 4;
sp [0].filter5 += sp [0].value;
sp [0].filter6 += (sp [0].value - sp [0].filter6) >> 3;
sp [0].value = sp [0].filter1 - sp [0].filter5 + ((sp [0].filter6 * sp [0].factor) >> 2);
sp [0].byte <<= 1;
if (!stereo)
continue;
pp = wps->dsd.ptable + ((sp [1].value >> (PRECISION - PRECISION_USE)) & PTABLE_MASK);
if (sp [1].byte & 0x80) {
high = low + ((high - low) >> 8) * (*pp >> 16);
*pp += (UP - *pp) >> DECAY;
sp [1].filter0 = -1;
}
else {
low += 1 + ((high - low) >> 8) * (*pp >> 16);
*pp += (DOWN - *pp) >> DECAY;
sp [1].filter0 = 0;
}
while (DSD_BYTE_READY (high, low)) {
*dp++ = high >> 24;
high = (high << 8) | 0xff;
low <<= 8;
}
sp [1].value += sp [1].filter6 << 3;
sp [1].factor += (((sp [1].value ^ sp [1].filter0) >> 31) | 1) & ((sp [1].value ^ (sp [1].value - (sp [1].filter6 << 4))) >> 31);
sp [1].filter1 += ((sp [1].filter0 & VALUE_ONE) - sp [1].filter1) >> 6;
sp [1].filter2 += ((sp [1].filter0 & VALUE_ONE) - sp [1].filter2) >> 4;
sp [1].filter3 += (sp [1].filter2 - sp [1].filter3) >> 4;
sp [1].filter4 += (sp [1].filter3 - sp [1].filter4) >> 4;
sp [1].value = (sp [1].filter4 - sp [1].filter5) >> 4;
sp [1].filter5 += sp [1].value;
sp [1].filter6 += (sp [1].value - sp [1].filter6) >> 3;
sp [1].value = sp [1].filter1 - sp [1].filter5 + ((sp [1].filter6 * sp [1].factor) >> 2);
sp [1].byte <<= 1;
}
if (!(flags & MONO_DATA))
channel ^= 1;
sp [0].factor -= (sp->factor + 512) >> 10;
if (stereo)
sp [1].factor -= (sp [1].factor + 512) >> 10;
}
((WavpackHeader *) wps->blockbuff)->crc = crc;
@ -628,3 +664,5 @@ static int encode_buffer_high (WavpackStream *wps, int32_t *buffer, int num_samp
else
return -1;
}
#endif // ENABLE_DSD

View File

@ -202,7 +202,7 @@ int scan_float_data (WavpackStream *wps, f32 *values, int32_t num_values)
// significant bits shifted out of the integers, plus information about +/- zeros and exceptions
// like NaN and +/- infinities) into the wvxbits stream (which is assumed to be opened). Note that
// for this work correctly, scan_float_data() must have been called on the original data to set
// the appropiate flags in float_flags and max_exp.
// the appropriate flags in float_flags and max_exp.
void send_float_data (WavpackStream *wps, f32 *values, int32_t num_values)
{

View File

@ -38,6 +38,7 @@ WavpackContext *WavpackOpenFileOutput (WavpackBlockOutput blockout, void *wv_id,
return NULL;
CLEAR (*wpc);
wpc->total_samples = -1;
wpc->stream_version = CUR_STREAM_VERS;
wpc->blockout = blockout;
wpc->wv_out = wv_id;
@ -120,35 +121,94 @@ void WavpackSetFileInformation (WavpackContext *wpc, char *file_extension, unsig
// a RIFF header has been included then it should be updated as well or the
// WavPack file will not be directly unpackable to a valid wav file (although
// it will still be usable by itself). A return of FALSE indicates an error.
//
// The enhanced version of this function now allows setting the identities of
// any channels that are NOT standard Microsoft channels and are therefore not
// represented in the channel mask. WavPack files require that all the Microsoft
// channels come first (and in Microsoft order) and these are followed by any
// other channels (which can be in any order).
//
// The identities are provided in a NULL-terminated string (0x00 is not an allowed
// channel ID). The Microsoft channels may be provided as well (and will be checked)
// but it is really only necessary to provide the "unknown" channels. Any truly
// unknown channels are indicated with a 0xFF.
//
// The channel IDs so far reserved are listed here:
//
// 0: not allowed / terminator
// 1 - 18: Microsoft standard channels
// 30, 31: Stereo mix from RF64 (not really recommended, but RF64 specifies this)
// 33 - 44: Core Audio channels (see Core Audio specification)
// 127 - 128: Amio LeftHeight, Amio RightHeight
// 138 - 142: Amio BottomFrontLeft/Center/Right, Amio ProximityLeft/Right
// 200 - 207: Core Audio channels (see Core Audio specification)
// 221 - 224: Core Audio channels 301 - 305 (offset by 80)
// 255: Present but unknown or unused channel
//
// All other channel IDs are reserved. Ask if something you need is missing.
static const uint32_t stereo_pairings [] = {
(1 << 0) | (1 << 1), // FL, FR
(1 << 4) | (1 << 5), // BL, BR
(1 << 6) | (1 << 7), // FLC, FRC
(1 << 9) | (1 << 10), // SL, SR
(1 << 12) | (1 << 14), // TFL, TFR
(1 << 15) | (1 << 17), // TBL, TBR
(1 << 29) | (1 << 30) // stereo mix L,R (RF64)
// Table of channels that will automatically "pair" into a single stereo stream
static const struct { unsigned char a, b; } stereo_pairs [] = {
{ 1, 2 }, // FL, FR
{ 5, 6 }, // BL, BR
{ 7, 8 }, // FLC, FRC
{ 10, 11 }, // SL, SR
{ 13, 15 }, // TFL, TFR
{ 16, 18 }, // TBL, TBR
{ 30, 31 }, // stereo mix L,R (RF64)
{ 33, 34 }, // Rls, Rrs
{ 35, 36 }, // Lw, Rw
{ 38, 39 }, // Lt, Rt
{ 127, 128 }, // Lh, Rh
{ 138, 140 }, // Bfl, Bfr
{ 141, 142 }, // Pl, Pr
{ 200, 201 }, // Amb_W, Amb_X
{ 202, 203 }, // Amb_Y, Amb_Z
{ 204, 205 }, // MS_Mid, MS_Side
{ 206, 207 }, // XY_X, XY_Y
{ 221, 222 }, // Hph_L, Hph_R
};
#define NUM_STEREO_PAIRINGS (sizeof (stereo_pairings) / sizeof (stereo_pairings [0]))
#define NUM_STEREO_PAIRS (sizeof (stereo_pairs) / sizeof (stereo_pairs [0]))
// Legacy version of this function for compatibility with existing applications. Note that this version
// also generates older streams to be compatible with all decoders back to 4.0, but of course cannot be
// used with > 2^32 samples or non-Microsoft channels. The older stream version only differs in that it
// does not support the "mono optimization" feature where stereo blocks containing identical audio data
// in both channels are encoded in mono for better efficiency.
int WavpackSetConfiguration (WavpackContext *wpc, WavpackConfig *config, uint32_t total_samples)
{
config->flags |= CONFIG_COMPATIBLE_WRITE; // write earlier version streams
if (total_samples == (uint32_t) -1)
return WavpackSetConfiguration64 (wpc, config, -1);
return WavpackSetConfiguration64 (wpc, config, -1, NULL);
else
return WavpackSetConfiguration64 (wpc, config, total_samples);
return WavpackSetConfiguration64 (wpc, config, total_samples, NULL);
}
int WavpackSetConfiguration64 (WavpackContext *wpc, WavpackConfig *config, int64_t total_samples)
int WavpackSetConfiguration64 (WavpackContext *wpc, WavpackConfig *config, int64_t total_samples, const unsigned char *chan_ids)
{
uint32_t flags, bps = 0, shift = 0;
uint32_t flags, bps = 0;
uint32_t chan_mask = config->channel_mask;
int num_chans = config->num_channels;
int i;
if (!config->sample_rate) {
strcpy (wpc->error_message, "sample rate cannot be zero!");
return FALSE;
}
if (!num_chans) {
strcpy (wpc->error_message, "channel count cannot be zero!");
return FALSE;
}
wpc->stream_version = (config->flags & CONFIG_COMPATIBLE_WRITE) ? CUR_STREAM_VERS : MAX_STREAM_VERS;
if ((config->qmode & QMODE_DSD_AUDIO) && config->bytes_per_sample == 1 && config->bits_per_sample == 8) {
#ifdef ENABLE_DSD
wpc->dsd_multiplier = 1;
flags = DSD_FLAG;
@ -163,9 +223,19 @@ int WavpackSetConfiguration64 (WavpackContext *wpc, WavpackConfig *config, int64
}
}
// most options that don't apply to DSD we can simply ignore for now, but NOT hybrid mode!
if (config->flags & CONFIG_HYBRID_FLAG) {
strcpy (wpc->error_message, "hybrid mode not available for DSD!");
return FALSE;
}
// with DSD, very few PCM options work (or make sense), so only allow those that do
config->flags &= (CONFIG_HIGH_FLAG | CONFIG_MD5_CHECKSUM | CONFIG_PAIR_UNDEF_CHANS);
config->float_norm_exp = config->xmode = 0;
#else
strcpy (wpc->error_message, "libwavpack not configured for DSD!");
return FALSE;
#endif
}
else
flags = config->bytes_per_sample - 1;
@ -188,18 +258,33 @@ int WavpackSetConfiguration64 (WavpackContext *wpc, WavpackConfig *config, int64
break;
flags |= i << SRATE_LSB;
flags |= shift << SHIFT_LSB;
// all of this stuff only applies to PCM
if (!(flags & DSD_FLAG)) {
if (config->float_norm_exp) {
if (config->bytes_per_sample != 4 || config->bits_per_sample != 32) {
strcpy (wpc->error_message, "incorrect bits/bytes configuration for float data!");
return FALSE;
}
wpc->config.float_norm_exp = config->float_norm_exp;
wpc->config.flags |= CONFIG_FLOAT_DATA;
flags |= FLOAT_DATA;
}
else
shift = (config->bytes_per_sample * 8) - config->bits_per_sample;
else {
if (config->bytes_per_sample < 1 || config->bytes_per_sample > 4) {
strcpy (wpc->error_message, "invalid bytes per sample!");
return FALSE;
}
if (config->bits_per_sample < 1 || config->bits_per_sample > config->bytes_per_sample * 8) {
strcpy (wpc->error_message, "invalid bits per sample!");
return FALSE;
}
flags |= ((config->bytes_per_sample * 8) - config->bits_per_sample) << SHIFT_LSB;
}
if (config->flags & CONFIG_HYBRID_FLAG) {
flags |= HYBRID_FLAG | HYBRID_BITRATE | HYBRID_BALANCE;
@ -235,48 +320,95 @@ int WavpackSetConfiguration64 (WavpackContext *wpc, WavpackConfig *config, int64
wpc->wvc_flag = TRUE;
}
// if a channel-identities string was specified, process that here, otherwise all channels
// not present in the channel mask are considered "unassigned"
if (chan_ids) {
int lastchan = 0, mask_copy = chan_mask;
if ((int) strlen ((char *) chan_ids) > num_chans) { // can't be more than num channels!
strcpy (wpc->error_message, "chan_ids longer than num channels!");
return FALSE;
}
// skip past channels that are specified in the channel mask (no reason to store those)
while (*chan_ids)
if (*chan_ids <= 32 && *chan_ids > lastchan && (mask_copy & (1 << (*chan_ids-1)))) {
mask_copy &= ~(1 << (*chan_ids-1));
lastchan = *chan_ids++;
}
else
break;
// now scan the string for an actually defined channel (and don't store if there aren't any)
for (i = 0; chan_ids [i]; i++)
if (chan_ids [i] != 0xff) {
wpc->channel_identities = (unsigned char *) strdup ((char *) chan_ids);
break;
}
}
// This loop goes through all the channels and creates the Wavpack "streams" for them to go in.
// A stream can hold either one or two channels, so we have several rules to determine how many
// channels will go in each stream.
for (wpc->current_stream = 0; num_chans; wpc->current_stream++) {
WavpackStream *wps = malloc (sizeof (WavpackStream));
uint32_t stereo_mask = 0, mono_mask = 0;
int pos, chans = 0;
unsigned char left_chan_id = 0, right_chan_id = 0;
int pos, chans = 1;
// allocate the stream and initialize the pointer to it
wpc->streams = realloc (wpc->streams, (wpc->current_stream + 1) * sizeof (wpc->streams [0]));
wpc->streams [wpc->current_stream] = wps;
CLEAR (*wps);
for (pos = 0; pos < 32; ++pos)
if (chan_mask & (1 << pos)) {
if (mono_mask) {
stereo_mask = mono_mask | (1 << pos);
break;
}
else
mono_mask = 1 << pos;
}
if (num_chans > 1 && stereo_mask) {
for (i = 0; i < NUM_STEREO_PAIRINGS; ++i)
if (stereo_mask == stereo_pairings [i]) {
chan_mask &= ~stereo_mask;
chans = 2;
break;
// if there are any bits [still] set in the channel_mask, get the next one or two IDs from there
if (chan_mask)
for (pos = 0; pos < 32; ++pos)
if (chan_mask & (1 << pos)) {
if (left_chan_id) {
right_chan_id = pos + 1;
break;
}
else {
chan_mask &= ~(1 << pos);
left_chan_id = pos + 1;
}
}
if (i == NUM_STEREO_PAIRINGS) {
chan_mask &= ~mono_mask;
chans = 1;
}
}
else if (mono_mask) {
chan_mask &= ~mono_mask;
chans = 1;
}
if (!chans) {
if (config->flags & CONFIG_PAIR_UNDEF_CHANS)
chans = num_chans > 1 ? 2 : 1;
// next check for any channels identified in the channel-identities string
while (!right_chan_id && chan_ids && *chan_ids)
if (left_chan_id)
right_chan_id = *chan_ids;
else
chans = 1;
left_chan_id = *chan_ids++;
// assume anything we did not get is "unassigned"
if (!left_chan_id)
left_chan_id = right_chan_id = 0xff;
else if (!right_chan_id)
right_chan_id = 0xff;
// if we have 2 channels, this is where we decide if we can combine them into one stream:
// 1. they are "unassigned" and we've been told to combine unassigned pairs, or
// 2. they appear together in the valid "pairings" list
if (num_chans >= 2) {
if ((config->flags & CONFIG_PAIR_UNDEF_CHANS) && left_chan_id == 0xff && right_chan_id == 0xff)
chans = 2;
else
for (i = 0; i < NUM_STEREO_PAIRS; ++i)
if ((left_chan_id == stereo_pairs [i].a && right_chan_id == stereo_pairs [i].b) ||
(left_chan_id == stereo_pairs [i].b && right_chan_id == stereo_pairs [i].a)) {
if (right_chan_id <= 32 && (chan_mask & (1 << (right_chan_id-1))))
chan_mask &= ~(1 << (right_chan_id-1));
else if (chan_ids && *chan_ids == right_chan_id)
chan_ids++;
chans = 2;
break;
}
}
num_chans -= chans;
@ -328,6 +460,11 @@ int WavpackSetConfiguration64 (WavpackContext *wpc, WavpackConfig *config, int64
// then the appropriate qmode bit must be set to ensure that any MD5 sum is stored with a new
// ID so that old decoders don't try to verify it (and to let the decoder know that a reorder
// might be required).
//
// Note: This function should only be used to encode Core Audio files in such a way that a
// verbatim archive can be created. Applications can just include the chan_ids parameter in
// the call to WavpackSetConfiguration64() if there are non-Microsoft channels to specify,
// or do nothing special if only Microsoft channels are present (the vast majority of cases).
int WavpackSetChannelLayout (WavpackContext *wpc, uint32_t layout_tag, const unsigned char *reorder)
{
@ -372,28 +509,37 @@ int WavpackPackInit (WavpackContext *wpc)
if (wpc->metabytes > 16384) // 16384 bytes still leaves plenty of room for audio
write_metadata_block (wpc); // in this block (otherwise write a special one)
if (wpc->config.flags & CONFIG_HIGH_FLAG)
wpc->block_samples = wpc->config.sample_rate;
else if (!(wpc->config.sample_rate % 2))
wpc->block_samples = wpc->config.sample_rate / 2;
else
wpc->block_samples = wpc->config.sample_rate;
// The default block size is a compromise. Longer blocks provide better encoding efficiency,
// but longer blocks adversely affect memory requirements and seeking performance. For WavPack
// version 5.0, the default block sizes have been reduced by half from the previous version,
// but the difference in encoding efficiency will generally be less than 0.1 percent.
if (wpc->dsd_multiplier) {
wpc->block_samples = (wpc->config.sample_rate % 7) ? 48000 : 44100;
if (wpc->config.flags & CONFIG_HIGH_FLAG)
wpc->block_samples = 22050;
else
wpc->block_samples = 44100;
wpc->block_samples /= 2;
if (wpc->config.num_channels == 1)
wpc->block_samples *= 2;
while (wpc->block_samples > 12000 && wpc->block_samples * wpc->config.num_channels > 300000)
wpc->block_samples /= 2;
}
else {
int divisor = (wpc->config.flags & CONFIG_HIGH_FLAG) ? 2 : 4;
while (wpc->block_samples * wpc->config.num_channels > 150000)
wpc->block_samples /= 2;
while (wpc->config.sample_rate % divisor)
divisor--;
while (wpc->block_samples * wpc->config.num_channels < 40000)
wpc->block_samples *= 2;
wpc->block_samples = wpc->config.sample_rate / divisor;
while (wpc->block_samples > 12000 && wpc->block_samples * wpc->config.num_channels > 75000)
wpc->block_samples /= 2;
while (wpc->block_samples * wpc->config.num_channels < 20000)
wpc->block_samples *= 2;
}
if (wpc->config.block_samples) {
if ((wpc->config.flags & CONFIG_MERGE_BLOCKS) &&
@ -414,9 +560,11 @@ int WavpackPackInit (WavpackContext *wpc)
wps->sample_buffer = malloc (wpc->max_samples * (wps->wphdr.flags & MONO_FLAG ? 4 : 8));
#ifdef ENABLE_DSD
if (wps->wphdr.flags & DSD_FLAG)
pack_dsd_init (wpc);
else
#endif
pack_init (wpc);
}
@ -715,24 +863,24 @@ static int create_riff_header (WavpackContext *wpc, int64_t total_samples, void
wavhdr.GUID [13] = 0x71;
}
strncpy (riffhdr.ckID, do_rf64 ? "RF64" : "RIFF", sizeof (riffhdr.ckID));
strncpy (riffhdr.formType, "WAVE", sizeof (riffhdr.formType));
memcpy (riffhdr.ckID, do_rf64 ? "RF64" : "RIFF", sizeof (riffhdr.ckID));
memcpy (riffhdr.formType, "WAVE", sizeof (riffhdr.formType));
total_riff_bytes = sizeof (riffhdr) + wavhdrsize + sizeof (datahdr) + total_data_bytes + wpc->riff_trailer_bytes;
if (do_rf64) total_riff_bytes += sizeof (ds64hdr) + sizeof (ds64_chunk);
if (write_junk) total_riff_bytes += sizeof (junkchunk);
strncpy (fmthdr.ckID, "fmt ", sizeof (fmthdr.ckID));
strncpy (datahdr.ckID, "data", sizeof (datahdr.ckID));
memcpy (fmthdr.ckID, "fmt ", sizeof (fmthdr.ckID));
memcpy (datahdr.ckID, "data", sizeof (datahdr.ckID));
fmthdr.ckSize = wavhdrsize;
if (write_junk) {
CLEAR (junkchunk);
strncpy (junkchunk.ckID, "junk", sizeof (junkchunk.ckID));
memcpy (junkchunk.ckID, "junk", sizeof (junkchunk.ckID));
junkchunk.ckSize = sizeof (junkchunk) - 8;
WavpackNativeToLittleEndian (&junkchunk, ChunkHeaderFormat);
}
if (do_rf64) {
strncpy (ds64hdr.ckID, "ds64", sizeof (ds64hdr.ckID));
memcpy (ds64hdr.ckID, "ds64", sizeof (ds64hdr.ckID));
ds64hdr.ckSize = sizeof (ds64_chunk);
CLEAR (ds64_chunk);
ds64_chunk.riffSize64 = total_riff_bytes;
@ -772,16 +920,35 @@ static int create_riff_header (WavpackContext *wpc, int64_t total_samples, void
return (int)(outptr - (char *) outbuffer);
}
static int block_add_checksum (unsigned char *buffer_start, unsigned char *buffer_end, int bytes);
static int pack_streams (WavpackContext *wpc, uint32_t block_samples)
{
uint32_t max_blocksize, bcount;
uint32_t max_blocksize, max_chans = 1, bcount;
unsigned char *outbuff, *outend, *out2buff, *out2end;
int result = TRUE;
int result = TRUE, i;
// for calculating output (block) buffer size, first see if any streams are stereo
for (i = 0; i < wpc->num_streams; i++)
if (!(wpc->streams [i]->wphdr.flags & MONO_FLAG)) {
max_chans = 2;
break;
}
// then calculate maximum size based on bytes / sample
max_blocksize = block_samples * max_chans * ((wpc->streams [0]->wphdr.flags & BYTES_STORED) + 1);
// add margin based on how much "negative" compression is possible with pathological audio
if ((wpc->config.flags & CONFIG_FLOAT_DATA) && !(wpc->config.flags & CONFIG_SKIP_WVX))
max_blocksize = block_samples * 16 + 4096;
max_blocksize += max_blocksize; // 100% margin for lossless float data
else
max_blocksize = block_samples * 10 + 4096;
max_blocksize += max_blocksize >> 2; // otherwise 25% margin for everything else
max_blocksize += wpc->metabytes + 1024; // finally, add metadata & another 1K margin
max_blocksize += max_blocksize & 1; // and make sure it's even so we detect overflow
out2buff = (wpc->wvc_flag) ? malloc (max_blocksize) : NULL;
out2end = out2buff + max_blocksize;
@ -803,11 +970,20 @@ static int pack_streams (WavpackContext *wpc, uint32_t block_samples)
wps->blockbuff = outbuff;
wps->blockend = outend;
#ifdef ENABLE_DSD
if (flags & DSD_FLAG)
result = pack_dsd_block (wpc, wps->sample_buffer);
else
#endif
result = pack_block (wpc, wps->sample_buffer);
if (result) {
result = block_add_checksum (outbuff, outend, (flags & HYBRID_FLAG) ? 2 : 4);
if (result && out2buff)
result = block_add_checksum (out2buff, out2end, 2);
}
wps->blockbuff = wps->block2buff = NULL;
if (wps->wphdr.block_samples != block_samples)
@ -865,6 +1041,8 @@ static int pack_streams (WavpackContext *wpc, uint32_t block_samples)
// of samples (or -1). It is the responsibility of the application to read and
// rewrite the block. An example of this can be found in the Audition filter.
static void block_update_checksum (unsigned char *buffer_start);
void WavpackUpdateNumSamples (WavpackContext *wpc, void *first_block)
{
uint32_t wrapper_size;
@ -879,6 +1057,7 @@ void WavpackUpdateNumSamples (WavpackContext *wpc, void *first_block)
memcpy (WavpackGetWrapperLocation (first_block, NULL), riff_header, wrapper_size);
}
block_update_checksum (first_block);
WavpackNativeToLittleEndian (first_block, WavpackHeaderFormat);
}
@ -1081,7 +1260,8 @@ static int write_metadata_block (WavpackContext *wpc)
wpmdp++;
}
wphdr = (WavpackHeader *) (block_buff = malloc (block_size));
// allocate 6 extra bytes for 4-byte checksum (which we add last)
wphdr = (WavpackHeader *) (block_buff = malloc (block_size + 6));
CLEAR (*wphdr);
memcpy (wphdr->ckID, "wvpk", 4);
@ -1103,6 +1283,8 @@ static int write_metadata_block (WavpackContext *wpc)
free (wpc->metadata);
wpc->metadata = NULL;
// add a 4-byte checksum here (increases block size by 6)
block_add_checksum ((unsigned char *) block_buff, (unsigned char *) block_buff + (block_size += 6), 4);
WavpackNativeToLittleEndian ((WavpackHeader *) block_buff, WavpackHeaderFormat);
if (!wpc->blockout (wpc->wv_out, block_buff, block_size)) {
@ -1124,3 +1306,140 @@ void free_metadata (WavpackMetadata *wpmd)
wpmd->data = NULL;
}
}
// These two functions add or update the block checksums that were introduced in WavPack 5.0.
// The presence of the checksum is indicated by a flag in the wavpack header (HAS_CHECKSUM)
// and the actual metadata item should be the last one in the block, and can be either 2 or 4
// bytes. Of course, older versions of the decoder will simply ignore both of these.
static int block_add_checksum (unsigned char *buffer_start, unsigned char *buffer_end, int bytes)
{
WavpackHeader *wphdr = (WavpackHeader *) buffer_start;
#ifdef BITSTREAM_SHORTS
uint16_t *csptr = (uint16_t*) buffer_start;
#else
unsigned char *csptr = buffer_start;
#endif
int bcount = wphdr->ckSize + 8, wcount;
uint32_t csum = (uint32_t) -1;
if (bytes != 2 && bytes != 4)
return FALSE;
if (bcount < sizeof (WavpackHeader) || (bcount & 1) || buffer_start + bcount + 2 + bytes > buffer_end)
return FALSE;
wphdr->flags |= HAS_CHECKSUM;
wphdr->ckSize += 2 + bytes;
wcount = bcount >> 1;
#ifdef BITSTREAM_SHORTS
while (wcount--)
csum = (csum * 3) + *csptr++;
#else
WavpackNativeToLittleEndian ((WavpackHeader *) buffer_start, WavpackHeaderFormat);
while (wcount--) {
csum = (csum * 3) + csptr [0] + (csptr [1] << 8);
csptr += 2;
}
WavpackLittleEndianToNative ((WavpackHeader *) buffer_start, WavpackHeaderFormat);
#endif
buffer_start += bcount;
*buffer_start++ = ID_BLOCK_CHECKSUM;
*buffer_start++ = bytes >> 1;
if (bytes == 4) {
*buffer_start++ = csum;
*buffer_start++ = csum >> 8;
*buffer_start++ = csum >> 16;
*buffer_start++ = csum >> 24;
}
else {
csum ^= csum >> 16;
*buffer_start++ = csum;
*buffer_start++ = csum >> 8;
}
return TRUE;
}
static void block_update_checksum (unsigned char *buffer_start)
{
WavpackHeader *wphdr = (WavpackHeader *) buffer_start;
unsigned char *dp, meta_id, c1, c2;
uint32_t bcount, meta_bc;
if (!(wphdr->flags & HAS_CHECKSUM))
return;
bcount = wphdr->ckSize - sizeof (WavpackHeader) + 8;
dp = (unsigned char *)(wphdr + 1);
while (bcount >= 2) {
meta_id = *dp++;
c1 = *dp++;
meta_bc = c1 << 1;
bcount -= 2;
if (meta_id & ID_LARGE) {
if (bcount < 2)
return;
c1 = *dp++;
c2 = *dp++;
meta_bc += ((uint32_t) c1 << 9) + ((uint32_t) c2 << 17);
bcount -= 2;
}
if (bcount < meta_bc)
return;
if ((meta_id & ID_UNIQUE) == ID_BLOCK_CHECKSUM) {
#ifdef BITSTREAM_SHORTS
uint16_t *csptr = (uint16_t*) buffer_start;
#else
unsigned char *csptr = buffer_start;
#endif
int wcount = (int)(dp - 2 - buffer_start) >> 1;
uint32_t csum = (uint32_t) -1;
if ((meta_id & ID_ODD_SIZE) || meta_bc < 2 || meta_bc > 4)
return;
#ifdef BITSTREAM_SHORTS
while (wcount--)
csum = (csum * 3) + *csptr++;
#else
WavpackNativeToLittleEndian ((WavpackHeader *) buffer_start, WavpackHeaderFormat);
while (wcount--) {
csum = (csum * 3) + csptr [0] + (csptr [1] << 8);
csptr += 2;
}
WavpackLittleEndianToNative ((WavpackHeader *) buffer_start, WavpackHeaderFormat);
#endif
if (meta_bc == 4) {
*dp++ = csum;
*dp++ = csum >> 8;
*dp++ = csum >> 16;
*dp++ = csum >> 24;
return;
}
else {
csum ^= csum >> 16;
*dp++ = csum;
*dp++ = csum >> 8;
return;
}
}
bcount -= meta_bc;
dp += meta_bc;
}
}

View File

@ -66,7 +66,7 @@ static uint32_t __inline read_code (Bitstream *bs, uint32_t maxcode);
int32_t FASTCALL get_word (WavpackStream *wps, int chan, int32_t *correction)
{
register struct entropy_data *c = wps->w.c + chan;
struct entropy_data *c = wps->w.c + chan;
uint32_t ones_count, low, mid, high;
int32_t value;
int sign;
@ -124,8 +124,8 @@ int32_t FASTCALL get_word (WavpackStream *wps, int chan, int32_t *correction)
wps->wvbits.bc += sizeof (*(wps->wvbits.ptr)) * 8;
}
#ifdef _WIN32
_BitScanForward (&ones_count, ~wps->wvbits.sr);
#ifdef _MSC_VER
{ unsigned long res; _BitScanForward (&res, (unsigned long)~wps->wvbits.sr); ones_count = (uint32_t) res; }
#else
ones_count = __builtin_ctz (~wps->wvbits.sr);
#endif
@ -288,6 +288,10 @@ int32_t FASTCALL get_word (WavpackStream *wps, int chan, int32_t *correction)
low &= 0x7fffffff;
high &= 0x7fffffff;
if (low > high) // make sure high and low make sense
high = low;
mid = (high + low + 1) >> 1;
if (!c->error_limit)
@ -399,8 +403,8 @@ int32_t get_words_lossless (WavpackStream *wps, int32_t *buffer, int32_t nsample
bs->bc += sizeof (*(bs->ptr)) * 8;
}
#ifdef _WIN32
_BitScanForward (&ones_count, ~wps->wvbits.sr);
#ifdef _MSC_VER
{ unsigned long res; _BitScanForward (&res, (unsigned long)~wps->wvbits.sr); ones_count = (uint32_t) res; }
#else
ones_count = __builtin_ctz (~wps->wvbits.sr);
#endif

View File

@ -411,7 +411,7 @@ static int append_ape_tag_item (WavpackContext *wpc, const char *item, const cha
int isize = (int) strlen (item);
if (!m_tag->ape_tag_hdr.ID [0]) {
strncpy (m_tag->ape_tag_hdr.ID, "APETAGEX", sizeof (m_tag->ape_tag_hdr.ID));
memcpy (m_tag->ape_tag_hdr.ID, "APETAGEX", sizeof (m_tag->ape_tag_hdr.ID));
m_tag->ape_tag_hdr.version = 2000;
m_tag->ape_tag_hdr.length = sizeof (m_tag->ape_tag_hdr);
m_tag->ape_tag_hdr.item_count = 0;
@ -429,7 +429,7 @@ static int append_ape_tag_item (WavpackContext *wpc, const char *item, const cha
m_tag->ape_tag_hdr.item_count++;
m_tag->ape_tag_hdr.length += new_item_len;
p = m_tag->ape_tag_data = realloc (m_tag->ape_tag_data, m_tag->ape_tag_hdr.length);
p = m_tag->ape_tag_data = (unsigned char*)realloc (m_tag->ape_tag_data, m_tag->ape_tag_hdr.length);
p += m_tag->ape_tag_hdr.length - sizeof (APE_Tag_Hdr) - new_item_len;
*p++ = (unsigned char) vsize;

View File

@ -21,7 +21,7 @@
// This function attempts to load an ID3v1 or APEv2 tag from the specified
// file into the specified M_Tag structure. The ID3 tag fits in completely,
// but an APEv2 tag is variable length and so space must be allocated here
// to accomodate the data, and this will need to be freed later. A return
// to accommodate the data, and this will need to be freed later. A return
// value of TRUE indicates a valid tag was found and loaded. Note that the
// file pointer is undefined when this function exits.
@ -59,7 +59,7 @@ int load_tag (WavpackContext *wpc)
if (m_tag->ape_tag_hdr.version == 2000 && m_tag->ape_tag_hdr.item_count &&
m_tag->ape_tag_hdr.length > sizeof (m_tag->ape_tag_hdr) &&
m_tag->ape_tag_hdr.length <= APE_TAG_MAX_LENGTH &&
(m_tag->ape_tag_data = malloc (m_tag->ape_tag_hdr.length)) != NULL) {
(m_tag->ape_tag_data = (unsigned char *)malloc (m_tag->ape_tag_hdr.length)) != NULL) {
ape_tag_items = m_tag->ape_tag_hdr.item_count;
ape_tag_length = m_tag->ape_tag_hdr.length;
@ -145,7 +145,7 @@ int load_tag (WavpackContext *wpc)
m_tag->tag_begins_file = 1; // failed ID3v1, so look for APEv2 at beginning of file
CLEAR (m_tag->id3_tag);
}
}
}
}
// Return TRUE is a valid ID3v1 or APEv2 tag has been loaded.

View File

@ -22,7 +22,7 @@
#define DECORR_STEREO_PASS_CONT unpack_decorr_stereo_pass_cont_x86
#define DECORR_STEREO_PASS_CONT_AVAILABLE unpack_cpu_has_feature_x86(CPU_FEATURE_MMX)
#define DECORR_MONO_PASS_CONT unpack_decorr_mono_pass_cont_x86
#elif defined(OPT_ASM_X64) && (defined (_WIN64) || defined(__CYGWIN__) || defined(__MINGW64__))
#elif defined(OPT_ASM_X64) && (defined (_WIN64) || defined(__CYGWIN__) || defined(__MINGW64__) || defined(__midipix__))
#define DECORR_STEREO_PASS_CONT unpack_decorr_stereo_pass_cont_x64win
#define DECORR_STEREO_PASS_CONT_AVAILABLE 1
#define DECORR_MONO_PASS_CONT unpack_decorr_mono_pass_cont_x64win
@ -52,7 +52,7 @@ extern void DECORR_MONO_PASS_CONT (struct decorr_pass *dpp, int32_t *buffer, int
///////////////////////////// executable code ////////////////////////////////
// This monster actually unpacks the WavPack bitstream(s) into the specified
// buffer as 32-bit integers or floats (depending on orignal data). Lossy
// buffer as 32-bit integers or floats (depending on original data). Lossy
// samples will be clipped to their original limits (i.e. 8-bit samples are
// clipped to -128/+127) but are still returned in longs. It is up to the
// caller to potentially reformat this for the final output including any
@ -83,7 +83,7 @@ int32_t unpack_samples (WavpackContext *wpc, int32_t *buffer, uint32_t sample_co
// don't attempt to decode past the end of the block, but watch out for overflow!
if (wps->sample_index + sample_count > GET_BLOCK_INDEX (wps->wphdr) + wps->wphdr.block_samples &&
GET_BLOCK_INDEX (wps->wphdr) + wps->wphdr.block_samples - wps->sample_index < sample_count)
(uint32_t) (GET_BLOCK_INDEX (wps->wphdr) + wps->wphdr.block_samples - wps->sample_index) < sample_count)
sample_count = (uint32_t) (GET_BLOCK_INDEX (wps->wphdr) + wps->wphdr.block_samples - wps->sample_index);
if (GET_BLOCK_INDEX (wps->wphdr) > wps->sample_index || wps->wphdr.block_samples < sample_count)
@ -148,6 +148,11 @@ int32_t unpack_samples (WavpackContext *wpc, int32_t *buffer, uint32_t sample_co
crc = crc * 3 + bptr [0];
}
#ifndef LOSSY_MUTE
else
for (bptr = buffer; bptr < eptr; ++bptr)
crc = crc * 3 + bptr [0];
#endif
}
/////////////// handle lossless or hybrid lossy stereo data ///////////////

View File

@ -11,11 +11,13 @@
// This module provides unpacking for WavPack files prior to version 4.0,
// not including "raw" files. As these modes are all obsolete and are no
// longer written, this code will not be fully documented other than the
// global functions. However, full documenation is provided in the version
// global functions. However, full documentation is provided in the version
// 3.97 source code. Note that this module does only the low-level sample
// unpacking; the actual opening of the file (and obtaining information
// from it) is handled in the unpack3_open.c module.
#ifdef ENABLE_LEGACY
#include <stdlib.h>
#include <string.h>
@ -1172,11 +1174,11 @@ int32_t unpack_samples3 (WavpackContext *wpc, int32_t *buffer, uint32_t sample_c
wpc->crc_errors++;
if (wpc->open_flags & OPEN_WRAPPER) {
unsigned char *temp = malloc (1024);
unsigned char *temp = (unsigned char *)malloc (1024);
uint32_t bcount;
if (bs_unused_bytes (&wps->wvbits)) {
wpc->wrapper_data = realloc (wpc->wrapper_data, wpc->wrapper_bytes + bs_unused_bytes (&wps->wvbits));
wpc->wrapper_data = (unsigned char *)realloc (wpc->wrapper_data, wpc->wrapper_bytes + bs_unused_bytes (&wps->wvbits));
memcpy (wpc->wrapper_data + wpc->wrapper_bytes, bs_unused_data (&wps->wvbits), bs_unused_bytes (&wps->wvbits));
wpc->wrapper_bytes += bs_unused_bytes (&wps->wvbits);
}
@ -1187,7 +1189,7 @@ int32_t unpack_samples3 (WavpackContext *wpc, int32_t *buffer, uint32_t sample_c
if (!bcount)
break;
wpc->wrapper_data = realloc (wpc->wrapper_data, wpc->wrapper_bytes + bcount);
wpc->wrapper_data = (unsigned char *)realloc (wpc->wrapper_data, wpc->wrapper_bytes + bcount);
memcpy (wpc->wrapper_data + wpc->wrapper_bytes, temp, bcount);
wpc->wrapper_bytes += bcount;
}
@ -1697,3 +1699,5 @@ static unsigned char *bs_unused_data (Bitstream3 *bs)
return bs->ptr;
}
#endif // ENABLE_LEGACY

View File

@ -11,11 +11,13 @@
// This module provides an extension to the open_utils.c module for handling
// WavPack files prior to version 4.0, not including "raw" files. As these
// modes are all obsolete and are no longer written, this code will not be
// fully documented other than the global functions. However, full documenation
// fully documented other than the global functions. However, full documentation
// is provided in the version 3.97 source code. Note that this module only
// provides the functionality of opening the files and obtaining information
// from them; the actual audio decoding is located in the unpack3.c module.
#ifdef ENABLE_LEGACY
#include <stdlib.h>
#include <string.h>
@ -51,7 +53,7 @@ WavpackContext *open_file3 (WavpackContext *wpc, char *error)
if (!strncmp (RiffChunkHeader.ckID, "RIFF", 4) && !strncmp (RiffChunkHeader.formType, "WAVE", 4)) {
if (wpc->open_flags & OPEN_WRAPPER) {
wpc->wrapper_data = malloc (wpc->wrapper_bytes = sizeof (RiffChunkHeader));
wpc->wrapper_data = (unsigned char *)malloc (wpc->wrapper_bytes = sizeof (RiffChunkHeader));
memcpy (wpc->wrapper_data, &RiffChunkHeader, sizeof (RiffChunkHeader));
}
@ -69,7 +71,7 @@ WavpackContext *open_file3 (WavpackContext *wpc, char *error)
}
else {
if (wpc->open_flags & OPEN_WRAPPER) {
wpc->wrapper_data = realloc (wpc->wrapper_data, wpc->wrapper_bytes + sizeof (ChunkHeader));
wpc->wrapper_data = (unsigned char *)realloc (wpc->wrapper_data, wpc->wrapper_bytes + sizeof (ChunkHeader));
memcpy (wpc->wrapper_data + wpc->wrapper_bytes, &ChunkHeader, sizeof (ChunkHeader));
wpc->wrapper_bytes += sizeof (ChunkHeader);
}
@ -84,7 +86,7 @@ WavpackContext *open_file3 (WavpackContext *wpc, char *error)
return WavpackCloseFile (wpc);
}
else if (wpc->open_flags & OPEN_WRAPPER) {
wpc->wrapper_data = realloc (wpc->wrapper_data, wpc->wrapper_bytes + sizeof (wavhdr));
wpc->wrapper_data = (unsigned char *)realloc (wpc->wrapper_data, wpc->wrapper_bytes + sizeof (wavhdr));
memcpy (wpc->wrapper_data + wpc->wrapper_bytes, &wavhdr, sizeof (wavhdr));
wpc->wrapper_bytes += sizeof (wavhdr);
}
@ -100,12 +102,12 @@ WavpackContext *open_file3 (WavpackContext *wpc, char *error)
}
if (wpc->open_flags & OPEN_WRAPPER) {
wpc->wrapper_data = realloc (wpc->wrapper_data, wpc->wrapper_bytes + bytes_to_skip);
wpc->wrapper_data = (unsigned char *)realloc (wpc->wrapper_data, wpc->wrapper_bytes + bytes_to_skip);
wpc->reader->read_bytes (wpc->wv_in, wpc->wrapper_data + wpc->wrapper_bytes, bytes_to_skip);
wpc->wrapper_bytes += bytes_to_skip;
}
else {
unsigned char *temp = malloc (bytes_to_skip);
unsigned char *temp = (unsigned char *)malloc (bytes_to_skip);
wpc->reader->read_bytes (wpc->wv_in, temp, bytes_to_skip);
free (temp);
}
@ -122,12 +124,12 @@ WavpackContext *open_file3 (WavpackContext *wpc, char *error)
}
if (wpc->open_flags & OPEN_WRAPPER) {
wpc->wrapper_data = realloc (wpc->wrapper_data, wpc->wrapper_bytes + bytes_to_skip);
wpc->wrapper_data = (unsigned char *)realloc (wpc->wrapper_data, wpc->wrapper_bytes + bytes_to_skip);
wpc->reader->read_bytes (wpc->wv_in, wpc->wrapper_data + wpc->wrapper_bytes, bytes_to_skip);
wpc->wrapper_bytes += bytes_to_skip;
}
else {
unsigned char *temp = malloc (bytes_to_skip);
unsigned char *temp = (unsigned char *)malloc (bytes_to_skip);
wpc->reader->read_bytes (wpc->wv_in, temp, bytes_to_skip);
free (temp);
}
@ -283,3 +285,5 @@ void free_stream3 (WavpackContext *wpc)
free (wps);
}
}
#endif // ENABLE_LEGACY

View File

@ -10,6 +10,7 @@
// This module provides seeking support for WavPack files prior to version 4.0.
#ifdef ENABLE_LEGACY
#ifndef NO_SEEKING
#include <stdlib.h>
@ -207,4 +208,5 @@ static void bs_restore3 (Bitstream3 *bs)
}
}
#endif
#endif // NO_SEEKING
#endif // ENABLE_LEGACY

View File

@ -10,6 +10,8 @@
// This module actually handles the uncompression of the DSD audio data.
#ifdef ENABLE_DSD
#include <stdlib.h>
#include <string.h>
#include <math.h>
@ -18,7 +20,7 @@
///////////////////////////// executable code ////////////////////////////////
// This function initialzes the main range-encoded data for DSD audio samples
// This function initializes the main range-encoded data for DSD audio samples
static int init_dsd_block_fast (WavpackStream *wps, WavpackMetadata *wpmd);
static int init_dsd_block_high (WavpackStream *wps, WavpackMetadata *wpmd);
@ -32,7 +34,7 @@ int init_dsd_block (WavpackContext *wpc, WavpackMetadata *wpmd)
if (wpmd->byte_length < 2)
return FALSE;
wps->dsd.byteptr = wpmd->data;
wps->dsd.byteptr = (unsigned char *)wpmd->data;
wps->dsd.endptr = wps->dsd.byteptr + wpmd->byte_length;
wpc->dsd_multiplier = 1 << *wps->dsd.byteptr++;
wps->dsd.mode = *wps->dsd.byteptr++;
@ -48,7 +50,7 @@ int init_dsd_block (WavpackContext *wpc, WavpackMetadata *wpmd)
if (wps->dsd.mode == 1)
return init_dsd_block_fast (wps, wpmd);
else if (wps->dsd.mode == 2)
else if (wps->dsd.mode == 3)
return init_dsd_block_high (wps, wpmd);
else
return FALSE;
@ -57,12 +59,12 @@ int init_dsd_block (WavpackContext *wpc, WavpackMetadata *wpmd)
int32_t unpack_dsd_samples (WavpackContext *wpc, int32_t *buffer, uint32_t sample_count)
{
WavpackStream *wps = wpc->streams [wpc->current_stream];
uint32_t flags = wps->wphdr.flags, crc = wps->crc;
uint32_t flags = wps->wphdr.flags;
// don't attempt to decode past the end of the block, but watch out for overflow!
if (wps->sample_index + sample_count > GET_BLOCK_INDEX (wps->wphdr) + wps->wphdr.block_samples &&
GET_BLOCK_INDEX (wps->wphdr) + wps->wphdr.block_samples - wps->sample_index < sample_count)
(uint32_t) (GET_BLOCK_INDEX (wps->wphdr) + wps->wphdr.block_samples - wps->sample_index) < sample_count)
sample_count = (uint32_t) (GET_BLOCK_INDEX (wps->wphdr) + wps->wphdr.block_samples - wps->sample_index);
if (GET_BLOCK_INDEX (wps->wphdr) > wps->sample_index || wps->wphdr.block_samples < sample_count)
@ -122,12 +124,11 @@ int32_t unpack_dsd_samples (WavpackContext *wpc, int32_t *buffer, uint32_t sampl
// #define DSD_BYTE_READY(low,high) (((low) >> 24) == ((high) >> 24))
// #define DSD_BYTE_READY(low,high) (!(((low) ^ (high)) >> 24))
#define DSD_BYTE_READY(low,high) (!(((low) ^ (high)) & 0xff000000))
#define MAX_HISTORY_BITS 5
static int init_dsd_block_fast (WavpackStream *wps, WavpackMetadata *wpmd)
{
unsigned char history_bits, max_probability;
int total_summed_probabilities = 0, i;
unsigned char history_bits, max_probability, *lb_ptr;
int total_summed_probabilities = 0, bi, i;
if (wps->dsd.byteptr == wps->dsd.endptr)
return FALSE;
@ -139,10 +140,12 @@ static int init_dsd_block_fast (WavpackStream *wps, WavpackMetadata *wpmd)
wps->dsd.history_bins = 1 << history_bits;
wps->dsd.value_lookup = malloc (sizeof (*wps->dsd.value_lookup) * wps->dsd.history_bins);
free_dsd_tables (wps);
lb_ptr = wps->dsd.lookup_buffer = (unsigned char *)malloc (wps->dsd.history_bins * MAX_BYTES_PER_BIN);
wps->dsd.value_lookup = (unsigned char **)malloc (sizeof (*wps->dsd.value_lookup) * wps->dsd.history_bins);
memset (wps->dsd.value_lookup, 0, sizeof (*wps->dsd.value_lookup) * wps->dsd.history_bins);
wps->dsd.summed_probabilities = malloc (sizeof (*wps->dsd.summed_probabilities) * wps->dsd.history_bins);
wps->dsd.probabilities = malloc (sizeof (*wps->dsd.probabilities) * wps->dsd.history_bins);
wps->dsd.summed_probabilities = (int16_t (*)[256])malloc (sizeof (*wps->dsd.summed_probabilities) * wps->dsd.history_bins);
wps->dsd.probabilities = (unsigned char (*)[256])malloc (sizeof (*wps->dsd.probabilities) * wps->dsd.history_bins);
max_probability = *wps->dsd.byteptr++;
@ -175,27 +178,28 @@ static int init_dsd_block_fast (WavpackStream *wps, WavpackMetadata *wpmd)
else
return FALSE;
for (wps->dsd.p0 = 0; wps->dsd.p0 < wps->dsd.history_bins; ++wps->dsd.p0) {
for (bi = 0; bi < wps->dsd.history_bins; ++bi) {
int32_t sum_values;
unsigned char *vp;
for (sum_values = i = 0; i < 256; ++i)
wps->dsd.summed_probabilities [wps->dsd.p0] [i] = sum_values += wps->dsd.probabilities [wps->dsd.p0] [i];
wps->dsd.summed_probabilities [bi] [i] = sum_values += wps->dsd.probabilities [bi] [i];
if (sum_values) {
total_summed_probabilities += sum_values;
vp = wps->dsd.value_lookup [wps->dsd.p0] = malloc (sum_values);
if ((total_summed_probabilities += sum_values) > wps->dsd.history_bins * MAX_BYTES_PER_BIN)
return FALSE;
wps->dsd.value_lookup [bi] = lb_ptr;
for (i = 0; i < 256; i++) {
int c = wps->dsd.probabilities [wps->dsd.p0] [i];
int c = wps->dsd.probabilities [bi] [i];
while (c--)
*vp++ = i;
*lb_ptr++ = i;
}
}
}
if (wps->dsd.endptr - wps->dsd.byteptr < 4 || total_summed_probabilities > wps->dsd.history_bins * 1280)
if (wps->dsd.endptr - wps->dsd.byteptr < 4 || total_summed_probabilities > wps->dsd.history_bins * MAX_BYTES_PER_BIN)
return FALSE;
for (i = 4; i--;)
@ -274,7 +278,7 @@ static int decode_fast (WavpackStream *wps, int32_t *output, int sample_count)
#define DOWN 0x00010000
#define DECAY 8
#define PRECISION 24
#define PRECISION 20
#define VALUE_ONE (1 << PRECISION)
#define PRECISION_USE 12
@ -314,17 +318,19 @@ static int init_dsd_block_high (WavpackStream *wps, WavpackMetadata *wpmd)
if (rate_s != RATE_S)
return FALSE;
wps->dsd.ptable = malloc (PTABLE_BINS * sizeof (*wps->dsd.ptable));
if (!wps->dsd.ptable)
wps->dsd.ptable = (int32_t *)malloc (PTABLE_BINS * sizeof (*wps->dsd.ptable));
init_ptable (wps->dsd.ptable, rate_i, rate_s);
for (channel = 0; channel < ((flags & MONO_DATA) ? 1 : 2); ++channel) {
DSDfilters *sp = wps->dsd.filters + channel;
sp->filter1 = *wps->dsd.byteptr++ << 16;
sp->filter2 = *wps->dsd.byteptr++ << 16;
sp->filter3 = *wps->dsd.byteptr++ << 16;
sp->filter4 = *wps->dsd.byteptr++ << 16;
sp->filter5 = *wps->dsd.byteptr++ << 16;
sp->filter1 = *wps->dsd.byteptr++ << (PRECISION - 8);
sp->filter2 = *wps->dsd.byteptr++ << (PRECISION - 8);
sp->filter3 = *wps->dsd.byteptr++ << (PRECISION - 8);
sp->filter4 = *wps->dsd.byteptr++ << (PRECISION - 8);
sp->filter5 = *wps->dsd.byteptr++ << (PRECISION - 8);
sp->filter6 = 0;
sp->factor = *wps->dsd.byteptr++ & 0xff;
sp->factor |= (*wps->dsd.byteptr++ << 8) & 0xff00;
@ -344,43 +350,30 @@ static int init_dsd_block_high (WavpackStream *wps, WavpackMetadata *wpmd)
static int decode_high (WavpackStream *wps, int32_t *output, int sample_count)
{
int total_samples = sample_count, channel = 0;
if (!(wps->wphdr.flags & MONO_DATA))
total_samples *= 2;
int total_samples = sample_count, stereo = (wps->wphdr.flags & MONO_DATA) ? 0 : 1;
DSDfilters *sp = wps->dsd.filters;
while (total_samples--) {
DSDfilters *sp = wps->dsd.filters + channel;
int byte = 0, bitcount = 8;
int bitcount = 8;
sp [0].value = sp [0].filter1 - sp [0].filter5 + ((sp [0].filter6 * sp [0].factor) >> 2);
if (stereo)
sp [1].value = sp [1].filter1 - sp [1].filter5 + ((sp [1].filter6 * sp [1].factor) >> 2);
while (bitcount--) {
int value = sp->filter1 - sp->filter5 + sp->filter6 * (sp->factor >> 2);
int index = (value >> (PRECISION - PRECISION_USE)) & PTABLE_MASK;
unsigned int range = wps->dsd.high - wps->dsd.low, split;
int *val = wps->dsd.ptable + index;
split = wps->dsd.low + ((range & 0xff000000) ? (range >> 8) * (*val >> 16) : ((range * (*val >> 16)) >> 8));
value += sp->filter6 << 3;
int32_t *pp = wps->dsd.ptable + ((sp [0].value >> (PRECISION - PRECISION_USE)) & PTABLE_MASK);
uint32_t split = wps->dsd.low + ((wps->dsd.high - wps->dsd.low) >> 8) * (*pp >> 16);
if (wps->dsd.value <= split) {
wps->dsd.high = split;
byte = (byte << 1) | 1;
*val += (UP - *val) >> DECAY;
sp->filter1 += (VALUE_ONE - sp->filter1) >> 6;
sp->filter2 += (VALUE_ONE - sp->filter2) >> 4;
if ((value ^ (value - (sp->filter6 << 4))) < 0)
sp->factor -= (value >> 31) | 1;
*pp += (UP - *pp) >> DECAY;
sp [0].filter0 = -1;
}
else {
wps->dsd.low = split + 1;
byte <<= 1;
*val += (DOWN - *val) >> DECAY;
sp->filter1 -= sp->filter1 >> 6;
sp->filter2 -= sp->filter2 >> 4;
if ((value ^ (value - (sp->filter6 << 4))) < 0)
sp->factor += (value >> 31) | 1;
*pp += (DOWN - *pp) >> DECAY;
sp [0].filter0 = 0;
}
while (DSD_BYTE_READY (wps->dsd.high, wps->dsd.low) && wps->dsd.byteptr < wps->dsd.endptr) {
@ -389,16 +382,61 @@ static int decode_high (WavpackStream *wps, int32_t *output, int sample_count)
wps->dsd.low <<= 8;
}
sp->filter3 += (sp->filter2 - sp->filter3) >> 4;
sp->filter4 += (sp->filter3 - sp->filter4) >> 4;
sp->filter5 += value = (sp->filter4 - sp->filter5) >> 4;
sp->filter6 += (value - sp->filter6) >> 3;
sp [0].value += sp [0].filter6 << 3;
sp [0].byte = (sp [0].byte << 1) | (sp [0].filter0 & 1);
sp [0].factor += (((sp [0].value ^ sp [0].filter0) >> 31) | 1) & ((sp [0].value ^ (sp [0].value - (sp [0].filter6 << 4))) >> 31);
sp [0].filter1 += ((sp [0].filter0 & VALUE_ONE) - sp [0].filter1) >> 6;
sp [0].filter2 += ((sp [0].filter0 & VALUE_ONE) - sp [0].filter2) >> 4;
sp [0].filter3 += (sp [0].filter2 - sp [0].filter3) >> 4;
sp [0].filter4 += (sp [0].filter3 - sp [0].filter4) >> 4;
sp [0].value = (sp [0].filter4 - sp [0].filter5) >> 4;
sp [0].filter5 += sp [0].value;
sp [0].filter6 += (sp [0].value - sp [0].filter6) >> 3;
sp [0].value = sp [0].filter1 - sp [0].filter5 + ((sp [0].filter6 * sp [0].factor) >> 2);
if (!stereo)
continue;
pp = wps->dsd.ptable + ((sp [1].value >> (PRECISION - PRECISION_USE)) & PTABLE_MASK);
split = wps->dsd.low + ((wps->dsd.high - wps->dsd.low) >> 8) * (*pp >> 16);
if (wps->dsd.value <= split) {
wps->dsd.high = split;
*pp += (UP - *pp) >> DECAY;
sp [1].filter0 = -1;
}
else {
wps->dsd.low = split + 1;
*pp += (DOWN - *pp) >> DECAY;
sp [1].filter0 = 0;
}
while (DSD_BYTE_READY (wps->dsd.high, wps->dsd.low) && wps->dsd.byteptr < wps->dsd.endptr) {
wps->dsd.value = (wps->dsd.value << 8) | *wps->dsd.byteptr++;
wps->dsd.high = (wps->dsd.high << 8) | 0xff;
wps->dsd.low <<= 8;
}
sp [1].value += sp [1].filter6 << 3;
sp [1].byte = (sp [1].byte << 1) | (sp [1].filter0 & 1);
sp [1].factor += (((sp [1].value ^ sp [1].filter0) >> 31) | 1) & ((sp [1].value ^ (sp [1].value - (sp [1].filter6 << 4))) >> 31);
sp [1].filter1 += ((sp [1].filter0 & VALUE_ONE) - sp [1].filter1) >> 6;
sp [1].filter2 += ((sp [1].filter0 & VALUE_ONE) - sp [1].filter2) >> 4;
sp [1].filter3 += (sp [1].filter2 - sp [1].filter3) >> 4;
sp [1].filter4 += (sp [1].filter3 - sp [1].filter4) >> 4;
sp [1].value = (sp [1].filter4 - sp [1].filter5) >> 4;
sp [1].filter5 += sp [1].value;
sp [1].filter6 += (sp [1].value - sp [1].filter6) >> 3;
sp [1].value = sp [1].filter1 - sp [1].filter5 + ((sp [1].filter6 * sp [1].factor) >> 2);
}
wps->crc += (wps->crc << 1) + (*output++ = byte);
wps->crc += (wps->crc << 1) + (*output++ = sp [0].byte & 0xff);
sp [0].factor -= (sp [0].factor + 512) >> 10;
if (!(wps->wphdr.flags & MONO_DATA))
channel ^= 1;
if (stereo) {
wps->crc += (wps->crc << 1) + (*output++ = wps->dsd.filters [1].byte & 0xff);
wps->dsd.filters [1].factor -= (wps->dsd.filters [1].factor + 512) >> 10;
}
}
return sample_count;
@ -406,9 +444,11 @@ static int decode_high (WavpackStream *wps, int32_t *output, int sample_count)
/*------------------------------------------------------------------------------------------------------------------------*/
#if 0
// 80 term DSD decimation filter
// < 1 dB down at 20 kHz
// > 108 dB stopband attenuation
// > 108 dB stopband attenuation (fs/16)
static const int32_t decm_filter [] = {
4, 17, 56, 147, 336, 693, 1320, 2359,
@ -423,7 +463,28 @@ static const int32_t decm_filter [] = {
2359, 1320, 693, 336, 147, 56, 17, 4,
};
#define NUM_FILTER_TERMS ((int)(sizeof (decm_filter) / sizeof (decm_filter [0])))
#define NUM_FILTER_TERMS 80
#else
// 56 term decimation filter
// < 0.5 dB down at 20 kHz
// > 100 dB stopband attenuation (fs/12)
static const int32_t decm_filter [] = {
4, 17, 56, 147, 336, 692, 1315, 2337,
3926, 6281, 9631, 14216, 20275, 28021, 37619, 49155,
62616, 77870, 94649, 112551, 131049, 149507, 167220, 183448,
197472, 208636, 216402, 220385, 220385, 216402, 208636, 197472,
183448, 167220, 149507, 131049, 112551, 94649, 77870, 62616,
49155, 37619, 28021, 20275, 14216, 9631, 6281, 3926,
2337, 1315, 692, 336, 147, 56, 17, 4,
};
#define NUM_FILTER_TERMS 56
#endif
#define HISTORY_BYTES ((NUM_FILTER_TERMS+7)/8)
typedef struct {
@ -438,7 +499,7 @@ typedef struct {
void *decimate_dsd_init (int num_channels)
{
DecimationContext *context = malloc (sizeof (DecimationContext));
DecimationContext *context = (DecimationContext *)malloc (sizeof (DecimationContext));
double filter_sum = 0, filter_scale;
int skipped_terms, i, j;
@ -447,7 +508,7 @@ void *decimate_dsd_init (int num_channels)
memset (context, 0, sizeof (*context));
context->num_channels = num_channels;
context->chans = malloc (num_channels * sizeof (DecimationChannel));
context->chans = (DecimationChannel *)malloc (num_channels * sizeof (DecimationChannel));
if (!context->chans) {
free (context);
@ -506,6 +567,7 @@ void decimate_dsd_run (void *decimate_context, int32_t *samples, int num_samples
DecimationChannel *sp = context->chans + chan;
int sum = 0;
#if (HISTORY_BYTES == 10)
sum += context->conv_tables [0] [sp->delay [0] = sp->delay [1]];
sum += context->conv_tables [1] [sp->delay [1] = sp->delay [2]];
sum += context->conv_tables [2] [sp->delay [2] = sp->delay [3]];
@ -516,6 +578,23 @@ void decimate_dsd_run (void *decimate_context, int32_t *samples, int num_samples
sum += context->conv_tables [7] [sp->delay [7] = sp->delay [8]];
sum += context->conv_tables [8] [sp->delay [8] = sp->delay [9]];
sum += context->conv_tables [9] [sp->delay [9] = *samples];
#elif (HISTORY_BYTES == 7)
sum += context->conv_tables [0] [sp->delay [0] = sp->delay [1]];
sum += context->conv_tables [1] [sp->delay [1] = sp->delay [2]];
sum += context->conv_tables [2] [sp->delay [2] = sp->delay [3]];
sum += context->conv_tables [3] [sp->delay [3] = sp->delay [4]];
sum += context->conv_tables [4] [sp->delay [4] = sp->delay [5]];
sum += context->conv_tables [5] [sp->delay [5] = sp->delay [6]];
sum += context->conv_tables [6] [sp->delay [6] = *samples];
#else
int i;
for (i = 0; i < HISTORY_BYTES-1; ++i)
sum += context->conv_tables [i] [sp->delay [i] = sp->delay [i+1]];
sum += context->conv_tables [i] [sp->delay [i] = *samples];
#endif
*samples++ = sum >> 4;
if (++chan == context->num_channels) {
@ -537,3 +616,5 @@ void decimate_dsd_destroy (void *decimate_context)
free (context);
}
#endif // ENABLE_DSD

View File

@ -22,7 +22,7 @@
static int64_t find_sample (WavpackContext *wpc, void *infile, int64_t header_pos, int64_t sample);
// Seek to the specifed sample index, returning TRUE on success. Note that
// Seek to the specified sample index, returning TRUE on success. Note that
// files generated with version 4.0 or newer will seek almost immediately.
// Older files can take quite long if required to seek through unplayed
// portions of the file, but will create a seek map so that reverse seeks
@ -38,7 +38,7 @@ int WavpackSeekSample (WavpackContext *wpc, uint32_t sample)
int WavpackSeekSample64 (WavpackContext *wpc, int64_t sample)
{
WavpackStream *wps = wpc->streams ? wpc->streams [wpc->current_stream = 0] : NULL;
uint32_t bcount, samples_to_skip;
uint32_t bcount, samples_to_skip, samples_to_decode = 0;
int32_t *buffer;
if (wpc->total_samples == -1 || sample >= wpc->total_samples ||
@ -46,11 +46,24 @@ int WavpackSeekSample64 (WavpackContext *wpc, int64_t sample)
(wpc->wvc_flag && !wpc->reader->can_seek (wpc->wvc_in)))
return FALSE;
#ifndef VER4_ONLY
#ifdef ENABLE_LEGACY
if (wpc->stream3)
return seek_sample3 (wpc, (uint32_t) sample);
#endif
#ifdef ENABLE_DSD
if (wpc->decimation_context) { // the decimation code needs some context to be sample accurate
if (sample < 16) {
samples_to_decode = (uint32_t) sample;
sample = 0;
}
else {
samples_to_decode = 16;
sample -= 16;
}
}
#endif
if (!wps->wphdr.block_samples || !(wps->wphdr.flags & INITIAL_BLOCK) || sample < GET_BLOCK_INDEX (wps->wphdr) ||
sample >= GET_BLOCK_INDEX (wps->wphdr) + wps->wphdr.block_samples) {
@ -72,8 +85,13 @@ int WavpackSeekSample64 (WavpackContext *wpc, int64_t sample)
wpc->reader->set_pos_abs (wpc->wv_in, wpc->filepos);
wpc->reader->read_bytes (wpc->wv_in, &wps->wphdr, sizeof (WavpackHeader));
WavpackLittleEndianToNative (&wps->wphdr, WavpackHeaderFormat);
SET_BLOCK_INDEX (wps->wphdr, GET_BLOCK_INDEX (wps->wphdr) - wpc->initial_index);
wps->blockbuff = malloc (wps->wphdr.ckSize + 8);
if ((wps->wphdr.ckSize & 1) || wps->wphdr.ckSize < 24 || wps->wphdr.ckSize >= 1024 * 1024) {
free_streams (wpc);
return FALSE;
}
wps->blockbuff = (unsigned char *)malloc (wps->wphdr.ckSize + 8);
memcpy (wps->blockbuff, &wps->wphdr, sizeof (WavpackHeader));
if (wpc->reader->read_bytes (wpc->wv_in, wps->blockbuff + sizeof (WavpackHeader), wps->wphdr.ckSize - 24) !=
@ -82,14 +100,28 @@ int WavpackSeekSample64 (WavpackContext *wpc, int64_t sample)
return FALSE;
}
// render corrupt blocks harmless
if (!WavpackVerifySingleBlock (wps->blockbuff, !(wpc->open_flags & OPEN_NO_CHECKSUM))) {
wps->wphdr.ckSize = sizeof (WavpackHeader) - 8;
wps->wphdr.block_samples = 0;
memcpy (wps->blockbuff, &wps->wphdr, 32);
}
SET_BLOCK_INDEX (wps->wphdr, GET_BLOCK_INDEX (wps->wphdr) - wpc->initial_index);
memcpy (wps->blockbuff, &wps->wphdr, sizeof (WavpackHeader));
wps->init_done = FALSE;
if (wpc->wvc_flag) {
wpc->reader->set_pos_abs (wpc->wvc_in, wpc->file2pos);
wpc->reader->read_bytes (wpc->wvc_in, &wps->wphdr, sizeof (WavpackHeader));
WavpackLittleEndianToNative (&wps->wphdr, WavpackHeaderFormat);
SET_BLOCK_INDEX (wps->wphdr, GET_BLOCK_INDEX (wps->wphdr) - wpc->initial_index);
wps->block2buff = malloc (wps->wphdr.ckSize + 8);
if ((wps->wphdr.ckSize & 1) || wps->wphdr.ckSize < 24 || wps->wphdr.ckSize >= 1024 * 1024) {
free_streams (wpc);
return FALSE;
}
wps->block2buff = (unsigned char *)malloc (wps->wphdr.ckSize + 8);
memcpy (wps->block2buff, &wps->wphdr, sizeof (WavpackHeader));
if (wpc->reader->read_bytes (wpc->wvc_in, wps->block2buff + sizeof (WavpackHeader), wps->wphdr.ckSize - 24) !=
@ -97,6 +129,16 @@ int WavpackSeekSample64 (WavpackContext *wpc, int64_t sample)
free_streams (wpc);
return FALSE;
}
// render corrupt blocks harmless
if (!WavpackVerifySingleBlock (wps->block2buff, !(wpc->open_flags & OPEN_NO_CHECKSUM))) {
wps->wphdr.ckSize = sizeof (WavpackHeader) - 8;
wps->wphdr.block_samples = 0;
memcpy (wps->block2buff, &wps->wphdr, 32);
}
SET_BLOCK_INDEX (wps->wphdr, GET_BLOCK_INDEX (wps->wphdr) - wpc->initial_index);
memcpy (wps->block2buff, &wps->wphdr, sizeof (WavpackHeader));
}
if (!wps->init_done && !unpack_init (wpc)) {
@ -115,8 +157,8 @@ int WavpackSeekSample64 (WavpackContext *wpc, int64_t sample)
return FALSE;
}
wpc->streams = realloc (wpc->streams, (wpc->num_streams + 1) * sizeof (wpc->streams [0]));
wps = wpc->streams [wpc->num_streams++] = malloc (sizeof (WavpackStream));
wpc->streams = (WavpackStream **)realloc (wpc->streams, (wpc->num_streams + 1) * sizeof (wpc->streams [0]));
wps = wpc->streams [wpc->num_streams++] = (WavpackStream *)malloc (sizeof (WavpackStream));
CLEAR (*wps);
bcount = read_next_header (wpc->reader, wpc->wv_in, &wps->wphdr);
@ -125,7 +167,7 @@ int WavpackSeekSample64 (WavpackContext *wpc, int64_t sample)
return FALSE;
}
wps->blockbuff = malloc (wps->wphdr.ckSize + 8);
wps->blockbuff = (unsigned char *)malloc (wps->wphdr.ckSize + 8);
memcpy (wps->blockbuff, &wps->wphdr, 32);
if (wpc->reader->read_bytes (wpc->wv_in, wps->blockbuff + 32, wps->wphdr.ckSize - 24) !=
@ -134,6 +176,13 @@ int WavpackSeekSample64 (WavpackContext *wpc, int64_t sample)
return FALSE;
}
// render corrupt blocks harmless
if (!WavpackVerifySingleBlock (wps->blockbuff, !(wpc->open_flags & OPEN_NO_CHECKSUM))) {
wps->wphdr.ckSize = sizeof (WavpackHeader) - 8;
wps->wphdr.block_samples = 0;
memcpy (wps->blockbuff, &wps->wphdr, 32);
}
wps->init_done = FALSE;
if (wpc->wvc_flag && !read_wvc_block (wpc)) {
@ -168,12 +217,14 @@ int WavpackSeekSample64 (WavpackContext *wpc, int64_t sample)
}
if (samples_to_skip) {
buffer = malloc (samples_to_skip * 8);
buffer = (int32_t *)malloc (samples_to_skip * 8);
for (wpc->current_stream = 0; wpc->current_stream < wpc->num_streams; wpc->current_stream++)
#ifdef ENABLE_DSD
if (wpc->streams [wpc->current_stream]->wphdr.flags & DSD_FLAG)
unpack_dsd_samples (wpc, buffer, samples_to_skip);
else
#endif
unpack_samples (wpc, buffer, samples_to_skip);
free (buffer);
@ -181,9 +232,20 @@ int WavpackSeekSample64 (WavpackContext *wpc, int64_t sample)
wpc->current_stream = 0;
#ifdef ENABLE_DSD
if (wpc->decimation_context)
decimate_dsd_reset (wpc->decimation_context);
if (samples_to_decode) {
buffer = (int32_t *)malloc (samples_to_decode * wpc->config.num_channels * 4);
if (buffer) {
WavpackUnpackSamples (wpc, buffer, samples_to_decode);
free (buffer);
}
}
#endif
return TRUE;
}
@ -198,7 +260,7 @@ int WavpackSeekSample64 (WavpackContext *wpc, int64_t sample)
static int64_t find_header (WavpackStreamReader64 *reader, void *id, int64_t filepos, WavpackHeader *wphdr)
{
unsigned char *buffer = malloc (BUFSIZE), *sp = buffer, *ep = buffer;
unsigned char *buffer = (unsigned char *)malloc (BUFSIZE), *sp = buffer, *ep = buffer;
if (filepos != (uint32_t) -1 && reader->set_pos_abs (id, filepos)) {
free (buffer);
@ -210,7 +272,7 @@ static int64_t find_header (WavpackStreamReader64 *reader, void *id, int64_t fil
if (sp < ep) {
bleft = (int)(ep - sp);
memcpy (buffer, sp, bleft);
memmove (buffer, sp, bleft);
ep -= (sp - buffer);
sp = buffer;
}

View File

@ -41,7 +41,7 @@ uint32_t WavpackUnpackSamples (WavpackContext *wpc, int32_t *buffer, uint32_t sa
uint32_t bcount, samples_unpacked = 0, samples_to_unpack;
int32_t *bptr = buffer;
#ifndef VER4_ONLY
#ifdef ENABLE_LEGACY
if (wpc->stream3)
return unpack_samples3 (wpc, buffer, samples);
#endif
@ -69,14 +69,9 @@ uint32_t WavpackUnpackSamples (WavpackContext *wpc, int32_t *buffer, uint32_t sa
wpc->filepos = nexthdrpos + bcount;
if (wpc->open_flags & OPEN_STREAMING)
SET_BLOCK_INDEX (wps->wphdr, wps->sample_index = 0);
else
SET_BLOCK_INDEX (wps->wphdr, GET_BLOCK_INDEX (wps->wphdr) - wpc->initial_index);
// allocate the memory for the entire raw block and read it in
wps->blockbuff = malloc (wps->wphdr.ckSize + 8);
wps->blockbuff = (unsigned char *)malloc (wps->wphdr.ckSize + 8);
if (!wps->blockbuff)
break;
@ -91,6 +86,21 @@ uint32_t WavpackUnpackSamples (WavpackContext *wpc, int32_t *buffer, uint32_t sa
break;
}
// render corrupt blocks harmless
if (!WavpackVerifySingleBlock (wps->blockbuff, !(wpc->open_flags & OPEN_NO_CHECKSUM))) {
wps->wphdr.ckSize = sizeof (WavpackHeader) - 8;
wps->wphdr.block_samples = 0;
memcpy (wps->blockbuff, &wps->wphdr, 32);
}
// potentially adjusting block_index must be done AFTER verifying block
if (wpc->open_flags & OPEN_STREAMING)
SET_BLOCK_INDEX (wps->wphdr, wps->sample_index = 0);
else
SET_BLOCK_INDEX (wps->wphdr, GET_BLOCK_INDEX (wps->wphdr) - wpc->initial_index);
memcpy (wps->blockbuff, &wps->wphdr, 32);
wps->init_done = FALSE; // we have not yet called unpack_init() for this block
// if this block has audio, but not the sample index we were expecting, flag an error
@ -168,7 +178,7 @@ uint32_t WavpackUnpackSamples (WavpackContext *wpc, int32_t *buffer, uint32_t sa
// to stereo), then enter this conditional block...otherwise we just unpack the samples directly
if (!wpc->reduced_channels && !(wps->wphdr.flags & FINAL_BLOCK)) {
int32_t *temp_buffer = malloc (samples_to_unpack * 8), *src, *dst;
int32_t *temp_buffer = (int32_t *)malloc (samples_to_unpack * 8), *src, *dst;
int offset = 0; // offset to next channel in sequence (0 to num_channels - 1)
uint32_t samcnt;
@ -185,12 +195,12 @@ uint32_t WavpackUnpackSamples (WavpackContext *wpc, int32_t *buffer, uint32_t sa
// if the stream has not been allocated and corresponding block read, do that here...
if (wpc->current_stream == wpc->num_streams) {
wpc->streams = realloc (wpc->streams, (wpc->num_streams + 1) * sizeof (wpc->streams [0]));
wpc->streams = (WavpackStream **)realloc (wpc->streams, (wpc->num_streams + 1) * sizeof (wpc->streams [0]));
if (!wpc->streams)
break;
wps = wpc->streams [wpc->num_streams++] = malloc (sizeof (WavpackStream));
wps = wpc->streams [wpc->num_streams++] = (WavpackStream *)malloc (sizeof (WavpackStream));
if (!wps)
break;
@ -205,12 +215,7 @@ uint32_t WavpackUnpackSamples (WavpackContext *wpc, int32_t *buffer, uint32_t sa
break;
}
if (wpc->open_flags & OPEN_STREAMING)
SET_BLOCK_INDEX (wps->wphdr, wps->sample_index = 0);
else
SET_BLOCK_INDEX (wps->wphdr, GET_BLOCK_INDEX (wps->wphdr) - wpc->initial_index);
wps->blockbuff = malloc (wps->wphdr.ckSize + 8);
wps->blockbuff = (unsigned char *)malloc (wps->wphdr.ckSize + 8);
if (!wps->blockbuff)
break;
@ -225,6 +230,22 @@ uint32_t WavpackUnpackSamples (WavpackContext *wpc, int32_t *buffer, uint32_t sa
break;
}
// render corrupt blocks harmless
if (!WavpackVerifySingleBlock (wps->blockbuff, !(wpc->open_flags & OPEN_NO_CHECKSUM))) {
wps->wphdr.ckSize = sizeof (WavpackHeader) - 8;
wps->wphdr.block_samples = 0;
memcpy (wps->blockbuff, &wps->wphdr, 32);
}
// potentially adjusting block_index must be done AFTER verifying block
if (wpc->open_flags & OPEN_STREAMING)
SET_BLOCK_INDEX (wps->wphdr, wps->sample_index = 0);
else
SET_BLOCK_INDEX (wps->wphdr, GET_BLOCK_INDEX (wps->wphdr) - wpc->initial_index);
memcpy (wps->blockbuff, &wps->wphdr, 32);
// if this block has audio, and we're in hybrid lossless mode, read the matching wvc block
if (wpc->wvc_flag)
@ -242,9 +263,11 @@ uint32_t WavpackUnpackSamples (WavpackContext *wpc, int32_t *buffer, uint32_t sa
// unpack the correct number of samples (either mono or stereo) into the temp buffer
#ifdef ENABLE_DSD
if (wps->wphdr.flags & DSD_FLAG)
unpack_dsd_samples (wpc, src = temp_buffer, samples_to_unpack);
else
#endif
unpack_samples (wpc, src = temp_buffer, samples_to_unpack);
samcnt = samples_to_unpack;
@ -325,8 +348,10 @@ uint32_t WavpackUnpackSamples (WavpackContext *wpc, int32_t *buffer, uint32_t sa
wps->sample_index += samples_to_unpack;
wpc->crc_errors++;
}
#ifdef ENABLE_DSD
else if (wps->wphdr.flags & DSD_FLAG)
unpack_dsd_samples (wpc, bptr, samples_to_unpack);
#endif
else
unpack_samples (wpc, bptr, samples_to_unpack);
@ -377,8 +402,10 @@ uint32_t WavpackUnpackSamples (WavpackContext *wpc, int32_t *buffer, uint32_t sa
break;
}
#ifdef ENABLE_DSD
if (wpc->decimation_context)
decimate_dsd_run (wpc->decimation_context, buffer, samples_unpacked);
#endif
return samples_unpacked;
}

View File

@ -691,7 +691,7 @@ int64_t DoGetFileSize (FILE *hFile)
{
struct stat statbuf;
if (!hFile || fstat (fileno (hFile), &statbuf) || !(statbuf.st_mode & S_IFREG))
if (!hFile || fstat (fileno (hFile), &statbuf) || !S_ISREG(statbuf.st_mode))
return 0;
return (int64_t) statbuf.st_size;

View File

@ -28,7 +28,7 @@
#else
#define VERSION_OS "Win32"
#endif
#define PACKAGE_VERSION "5.0.0-alpha4"
#define PACKAGE_VERSION "5.2.0"
#endif
#define FALSE 0

View File

@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////////////////////
// **** WAVPACK **** //
// Hybrid Lossless Wavefile Compressor //
// Copyright (c) 1998 - 2016 David Bryant. //
// Copyright (c) 1998 - 2019 David Bryant. //
// All Rights Reserved. //
// Distributed under the BSD Software License (see license.txt) //
////////////////////////////////////////////////////////////////////////////
@ -132,14 +132,17 @@ typedef struct {
#define SRATE_MASK (0xfL << SRATE_LSB)
#define FALSE_STEREO 0x40000000 // block is stereo, but data is mono
#define IGNORED_FLAGS 0x18000000 // reserved, but ignore if encountered
#define NEW_SHAPING 0x20000000 // use IIR filter for negative shaping
#define UNKNOWN_FLAGS 0x80000000 // also reserved, but refuse decode if
// encountered
#define MONO_DATA (MONO_FLAG | FALSE_STEREO)
// Introduced in WavPack 5.0:
#define HAS_CHECKSUM 0x10000000 // block contains a trailing checksum
#define DSD_FLAG 0x80000000 // block is encoded DSD (1-bit PCM)
#define IGNORED_FLAGS 0x08000000 // reserved, but ignore if encountered
#define UNKNOWN_FLAGS 0x00000000 // we no longer have any of these spares
#define MIN_STREAM_VERS 0x402 // lowest stream version we'll decode
#define MAX_STREAM_VERS 0x410 // highest stream version we'll decode or encode
@ -175,6 +178,7 @@ typedef struct {
#define ID_ALT_EXTENSION (ID_OPTIONAL_DATA | 0x8)
#define ID_ALT_MD5_CHECKSUM (ID_OPTIONAL_DATA | 0x9)
#define ID_NEW_CONFIG_BLOCK (ID_OPTIONAL_DATA | 0xa)
#define ID_BLOCK_CHECKSUM (ID_OPTIONAL_DATA | 0xf)
///////////////////////// WavPack Configuration ///////////////////////////////
@ -206,6 +210,7 @@ typedef struct {
#define CONFIG_CREATE_EXE 0x40000 // create executable
#define CONFIG_CREATE_WVC 0x80000 // create correction file
#define CONFIG_OPTIMIZE_WVC 0x100000 // maximize bybrid compression
#define CONFIG_COMPATIBLE_WRITE 0x400000 // write files for decoders < 4.3
#define CONFIG_CALC_NOISE 0x800000 // calc noise in hybrid mode
#define CONFIG_EXTRA_MODE 0x2000000 // extra processing mode
#define CONFIG_SKIP_WVX 0x4000000 // no wvx stream w/ floats & big ints
@ -275,7 +280,7 @@ typedef int (*WavpackBlockOutput)(void *id, void *data, int32_t bcount);
//////////////////////////// function prototypes /////////////////////////////
typedef void WavpackContext;
typedef struct WavpackContext WavpackContext;
#ifdef __cplusplus
extern "C" {
@ -283,6 +288,11 @@ extern "C" {
#define MAX_WAVPACK_SAMPLES ((1LL << 40) - 257)
WavpackContext *WavpackOpenRawDecoder (
void *main_data, int32_t main_size,
void *corr_data, int32_t corr_size,
int16_t version, char *error, int flags, int norm_offset);
WavpackContext *WavpackOpenFileInputEx64 (WavpackStreamReader64 *reader, void *wv_id, void *wvc_id, char *error, int flags, int norm_offset);
WavpackContext *WavpackOpenFileInputEx (WavpackStreamReader *reader, void *wv_id, void *wvc_id, char *error, int flags, int norm_offset);
WavpackContext *WavpackOpenFileInput (const char *infilename, char *error, int flags, int norm_offset);
@ -304,6 +314,7 @@ WavpackContext *WavpackOpenFileInput (const char *infilename, char *error, int f
#define OPEN_DSD_AS_PCM 0x200 // open DSD files as 24-bit PCM (decimated 8x)
#define OPEN_ALT_TYPES 0x400 // application is aware of alternate file types & qmode
// (just affects retrieving wrappers & MD5 checksums)
#define OPEN_NO_CHECKSUM 0x800 // don't verify block checksums before decoding
int WavpackGetMode (WavpackContext *wpc);
@ -322,6 +333,7 @@ int WavpackGetMode (WavpackContext *wpc);
#define MODE_XMODE 0x7000 // mask for extra level (1-6, 0=unknown)
#define MODE_DNS 0x8000
int WavpackVerifySingleBlock (unsigned char *buffer, int verify_checksum);
int WavpackGetQualifyMode (WavpackContext *wpc);
char *WavpackGetErrorMessage (WavpackContext *wpc);
int WavpackGetVersion (WavpackContext *wpc);
@ -330,6 +342,7 @@ unsigned char WavpackGetFileFormat (WavpackContext *wpc);
uint32_t WavpackUnpackSamples (WavpackContext *wpc, int32_t *buffer, uint32_t samples);
uint32_t WavpackGetNumSamples (WavpackContext *wpc);
int64_t WavpackGetNumSamples64 (WavpackContext *wpc);
uint32_t WavpackGetNumSamplesInFrame (WavpackContext *wpc);
uint32_t WavpackGetSampleIndex (WavpackContext *wpc);
int64_t WavpackGetSampleIndex64 (WavpackContext *wpc);
int WavpackGetNumErrors (WavpackContext *wpc);
@ -338,6 +351,7 @@ int WavpackSeekSample (WavpackContext *wpc, uint32_t sample);
int WavpackSeekSample64 (WavpackContext *wpc, int64_t sample);
WavpackContext *WavpackCloseFile (WavpackContext *wpc);
uint32_t WavpackGetSampleRate (WavpackContext *wpc);
uint32_t WavpackGetNativeSampleRate (WavpackContext *wpc);
int WavpackGetBitsPerSample (WavpackContext *wpc);
int WavpackGetBytesPerSample (WavpackContext *wpc);
int WavpackGetNumChannels (WavpackContext *wpc);
@ -345,6 +359,7 @@ int WavpackGetChannelMask (WavpackContext *wpc);
int WavpackGetReducedChannels (WavpackContext *wpc);
int WavpackGetFloatNormExp (WavpackContext *wpc);
int WavpackGetMD5Sum (WavpackContext *wpc, unsigned char data [16]);
void WavpackGetChannelIdentities (WavpackContext *wpc, unsigned char *identities);
uint32_t WavpackGetChannelLayout (WavpackContext *wpc, unsigned char *reorder);
uint32_t WavpackGetWrapperBytes (WavpackContext *wpc);
unsigned char *WavpackGetWrapperData (WavpackContext *wpc);
@ -377,7 +392,7 @@ void WavpackSetFileInformation (WavpackContext *wpc, char *file_extension, unsig
#define WP_FORMAT_DSF 4 // Sony DSD Format
int WavpackSetConfiguration (WavpackContext *wpc, WavpackConfig *config, uint32_t total_samples);
int WavpackSetConfiguration64 (WavpackContext *wpc, WavpackConfig *config, int64_t total_samples);
int WavpackSetConfiguration64 (WavpackContext *wpc, WavpackConfig *config, int64_t total_samples, const unsigned char *chan_ids);
int WavpackSetChannelLayout (WavpackContext *wpc, uint32_t layout_tag, const unsigned char *reorder);
int WavpackAddWrapper (WavpackContext *wpc, void *data, uint32_t bcount);
int WavpackStoreMD5Sum (WavpackContext *wpc, unsigned char data [16]);

View File

@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////////////////////
// **** WAVPACK **** //
// Hybrid Lossless Wavefile Compressor //
// Copyright (c) 1998 - 2013 Conifer Software. //
// Copyright (c) 1998 - 2019 David Bryant. //
// All Rights Reserved. //
// Distributed under the BSD Software License (see license.txt) //
////////////////////////////////////////////////////////////////////////////
@ -11,7 +11,10 @@
#ifndef WAVPACK_LOCAL_H
#define WAVPACK_LOCAL_H
#include "wavpack.h"
#if defined(_WIN32)
#define strdup(x) _strdup(x)
#define FASTCALL __fastcall
#else
#define FASTCALL
@ -96,120 +99,9 @@ typedef struct {
unsigned char *ape_tag_data;
} M_Tag;
// RIFF / wav header formats (these occur at the beginning of both wav files
// and pre-4.0 WavPack files that are not in the "raw" mode)
typedef struct {
char ckID [4];
uint32_t ckSize;
char formType [4];
} RiffChunkHeader;
typedef struct {
char ckID [4];
uint32_t ckSize;
} ChunkHeader;
#define ChunkHeaderFormat "4L"
typedef struct {
uint16_t FormatTag, NumChannels;
uint32_t SampleRate, BytesPerSecond;
uint16_t BlockAlign, BitsPerSample;
uint16_t cbSize, ValidBitsPerSample;
int32_t ChannelMask;
uint16_t SubFormat;
char GUID [14];
} WaveHeader;
#define WaveHeaderFormat "SSLLSSSSLS"
////////////////////////////// WavPack Header /////////////////////////////////
// Note that this is the ONLY structure that is written to (or read from)
// WavPack 4.0 files, and is the preamble to every block in both the .wv
// and .wvc files.
typedef struct {
char ckID [4];
uint32_t ckSize;
int16_t version;
unsigned char block_index_u8;
unsigned char total_samples_u8;
uint32_t total_samples, block_index, block_samples, flags, crc;
} WavpackHeader;
#define WavpackHeaderFormat "4LS2LLLLL"
// Macros to access the 40-bit block_index field
#define GET_BLOCK_INDEX(hdr) ( (int64_t) (hdr).block_index + ((int64_t) (hdr).block_index_u8 << 32) )
#define SET_BLOCK_INDEX(hdr,value) do { \
int64_t tmp = (value); \
(hdr).block_index = (uint32_t) tmp; \
(hdr).block_index_u8 = \
(unsigned char) (tmp >> 32); \
} while (0)
// Macros to access the 40-bit total_samples field, which is complicated by the fact that
// all 1's in the lower 32 bits indicates "unknown" (regardless of upper 8 bits)
#define GET_TOTAL_SAMPLES(hdr) ( ((hdr).total_samples == (uint32_t) -1) ? -1 : \
(int64_t) (hdr).total_samples + ((int64_t) (hdr).total_samples_u8 << 32) - (hdr).total_samples_u8 )
#define SET_TOTAL_SAMPLES(hdr,value) do { \
int64_t tmp = (value); \
if (tmp < 0) \
(hdr).total_samples = (uint32_t) -1; \
else { \
tmp += (tmp / 0xffffffffLL); \
(hdr).total_samples = (uint32_t) tmp; \
(hdr).total_samples_u8 = \
(unsigned char) (tmp >> 32); \
} \
} while (0)
// or-values for "flags"
#define BYTES_STORED 3 // 1-4 bytes/sample
#define MONO_FLAG 4 // not stereo
#define HYBRID_FLAG 8 // hybrid mode
#define JOINT_STEREO 0x10 // joint stereo
#define CROSS_DECORR 0x20 // no-delay cross decorrelation
#define HYBRID_SHAPE 0x40 // noise shape (hybrid mode only)
#define FLOAT_DATA 0x80 // ieee 32-bit floating point data
#define INT32_DATA 0x100 // special extended int handling
#define HYBRID_BITRATE 0x200 // bitrate noise (hybrid mode only)
#define HYBRID_BALANCE 0x400 // balance noise (hybrid stereo mode only)
#define INITIAL_BLOCK 0x800 // initial block of multichannel segment
#define FINAL_BLOCK 0x1000 // final block of multichannel segment
#define SHIFT_LSB 13
#define SHIFT_MASK (0x1fL << SHIFT_LSB)
#define MAG_LSB 18
#define MAG_MASK (0x1fL << MAG_LSB)
#define SRATE_LSB 23
#define SRATE_MASK (0xfL << SRATE_LSB)
#define FALSE_STEREO 0x40000000 // block is stereo, but data is mono
#define IGNORED_FLAGS 0x18000000 // reserved, but ignore if encountered
#define NEW_SHAPING 0x20000000 // use IIR filter for negative shaping
#define DSD_FLAG 0x80000000 // block is DSD encoded (introduced in
// WavPack 5.0)
#define UNKNOWN_FLAGS 0x00000000 // we no longer have any of these spares
#define MONO_DATA (MONO_FLAG | FALSE_STEREO)
#define MIN_STREAM_VERS 0x402 // lowest stream version we'll decode
#define MAX_STREAM_VERS 0x410 // highest stream version we'll decode or encode
#define CUR_STREAM_VERS 0x410 // stream version we are writing now
#define CUR_STREAM_VERS 0x407 // universally compatible stream version
//////////////////////////// WavPack Metadata /////////////////////////////////
@ -253,52 +145,15 @@ typedef struct {
#define ID_ALT_EXTENSION (ID_OPTIONAL_DATA | 0x8)
#define ID_ALT_MD5_CHECKSUM (ID_OPTIONAL_DATA | 0x9)
#define ID_NEW_CONFIG_BLOCK (ID_OPTIONAL_DATA | 0xa)
///////////////////////// WavPack Configuration ///////////////////////////////
// This internal structure is used during encode to provide configuration to
// the encoding engine and during decoding to provide fle information back to
// the higher level functions. Not all fields are used in both modes.
typedef struct {
float bitrate, shaping_weight;
int bits_per_sample, bytes_per_sample;
int qmode, flags, xmode, num_channels, float_norm_exp;
int32_t block_samples, extra_flags, sample_rate, channel_mask;
unsigned char md5_checksum [16], md5_read;
int num_tag_strings;
char **tag_strings;
} WavpackConfig;
#define ID_CHANNEL_IDENTITIES (ID_OPTIONAL_DATA | 0xb)
#define ID_BLOCK_CHECKSUM (ID_OPTIONAL_DATA | 0xf)
#define CONFIG_BYTES_STORED 3 // 1-4 bytes/sample
#define CONFIG_MONO_FLAG 4 // not stereo
#define CONFIG_HYBRID_FLAG 8 // hybrid mode
#define CONFIG_JOINT_STEREO 0x10 // joint stereo
#define CONFIG_CROSS_DECORR 0x20 // no-delay cross decorrelation
#define CONFIG_HYBRID_SHAPE 0x40 // noise shape (hybrid mode only)
#define CONFIG_FLOAT_DATA 0x80 // ieee 32-bit floating point data
#define CONFIG_FAST_FLAG 0x200 // fast mode
#define CONFIG_HIGH_FLAG 0x800 // high quality mode
#define CONFIG_VERY_HIGH_FLAG 0x1000 // very high
#define CONFIG_BITRATE_KBPS 0x2000 // bitrate is kbps, not bits / sample
#define CONFIG_AUTO_SHAPING 0x4000 // automatic noise shaping
#define CONFIG_SHAPE_OVERRIDE 0x8000 // shaping mode specified
#define CONFIG_JOINT_OVERRIDE 0x10000 // joint-stereo mode specified
#define CONFIG_DYNAMIC_SHAPING 0x20000 // dynamic noise shaping
#define CONFIG_CREATE_EXE 0x40000 // create executable
#define CONFIG_CREATE_WVC 0x80000 // create correction file
#define CONFIG_OPTIMIZE_WVC 0x100000 // maximize bybrid compression
#define CONFIG_CALC_NOISE 0x800000 // calc noise in hybrid mode
#define CONFIG_LOSSY_MODE 0x1000000 // obsolete (for information)
#define CONFIG_EXTRA_MODE 0x2000000 // extra processing mode
#define CONFIG_SKIP_WVX 0x4000000 // no wvx stream w/ floats & big ints
#define CONFIG_MD5_CHECKSUM 0x8000000 // compute & store MD5 signature
#define CONFIG_MERGE_BLOCKS 0x10000000 // merge blocks of equal redundancy (for lossyWAV)
#define CONFIG_PAIR_UNDEF_CHANS 0x20000000 // encode undefined channels in stereo pairs
#define CONFIG_OPTIMIZE_MONO 0x80000000 // optimize for mono streams posing as stereo
#define QMODE_DSD_AUDIO 0x30 // if either of these is set in qmode (version 5.0)
/*
* These config flags were never actually used, or are no longer used, or are
@ -356,6 +211,14 @@ typedef struct bs {
#define MAX_NTERMS 16
#define MAX_TERM 8
// DSD-specific definitions
#define MAX_HISTORY_BITS 5 // maximum number of history bits in DSD "fast" mode
// note that 5 history bits requires 32 history bins
#define MAX_BYTES_PER_BIN 1280 // maximum bytes for the value lookup array (per bin)
// such that the total storage per bin = 2K (also
// counting probabilities and summed_probabilities)
// Note that this structure is directly accessed in assembly files, so modify with care
struct decorr_pass {
@ -381,7 +244,7 @@ struct words_data {
};
typedef struct {
int32_t filter1, filter2, filter3, filter4, filter5, filter6, factor;
int32_t value, filter0, filter1, filter2, filter3, filter4, filter5, filter6, factor, byte;
} DSDfilters;
typedef struct {
@ -414,7 +277,7 @@ typedef struct {
const WavpackDecorrSpec *decorr_specs;
struct {
unsigned char *byteptr, *endptr, (*probabilities) [256], **value_lookup, mode, ready;
unsigned char *byteptr, *endptr, (*probabilities) [256], *lookup_buffer, **value_lookup, mode, ready;
int history_bins, p0, p1;
int16_t (*summed_probabilities) [256];
uint32_t low, high, value;
@ -439,38 +302,7 @@ typedef struct {
// files. It is recommended that direct access to this structure be minimized
// and the provided utilities used instead.
typedef struct {
int32_t (*read_bytes)(void *id, void *data, int32_t bcount);
uint32_t (*get_pos)(void *id);
int (*set_pos_abs)(void *id, uint32_t pos);
int (*set_pos_rel)(void *id, int32_t delta, int mode);
int (*push_back_byte)(void *id, int c);
uint32_t (*get_length)(void *id);
int (*can_seek)(void *id);
// this callback is for writing edited tags only
int32_t (*write_bytes)(void *id, void *data, int32_t bcount);
} WavpackStreamReader;
// Extended version of structure for handling large files and added
// functionality for truncating and closing files
typedef struct {
int32_t (*read_bytes)(void *id, void *data, int32_t bcount);
int32_t (*write_bytes)(void *id, void *data, int32_t bcount);
int64_t (*get_pos)(void *id); // new signature for large files
int (*set_pos_abs)(void *id, int64_t pos); // new signature for large files
int (*set_pos_rel)(void *id, int64_t delta, int mode); // new signature for large files
int (*push_back_byte)(void *id, int c);
int64_t (*get_length)(void *id); // new signature for large files
int (*can_seek)(void *id);
int (*truncate_here)(void *id); // new function to truncate file at current position
int (*close)(void *id); // new function to close file
} WavpackStreamReader64;
typedef int (*WavpackBlockOutput)(void *id, void *data, int32_t bcount);
typedef struct {
struct WavpackContext {
WavpackConfig config;
WavpackMetadata *metadata;
@ -498,13 +330,14 @@ typedef struct {
void *stream3;
// these items were added in 5.0 to support alternate file types (especially CAF & DSD)
unsigned char file_format, *channel_reordering;
unsigned char file_format, *channel_reordering, *channel_identities;
uint32_t channel_layout, dsd_multiplier;
void *decimation_context;
char file_extension [8];
void (*close_callback)(void *wpc);
char error_message [80];
} WavpackContext;
};
//////////////////////// function prototypes and macros //////////////////////
@ -554,9 +387,6 @@ typedef struct {
if (source && result) (source ^ result) < 0 ? (weight -= delta) : (weight += delta);
#endif
#define update_weight_d2(weight, delta, source, result) \
if (source && result) weight -= (((source ^ result) >> 29) & 4) - 2;
#define update_weight_clip(weight, delta, source, result) \
if (source && result) { \
const int32_t s = (source ^ result) >> 31; \
@ -564,13 +394,6 @@ typedef struct {
weight = (weight ^ s) - s; \
}
#define update_weight_clip_d2(weight, delta, source, result) \
if (source && result) { \
const int32_t s = (source ^ result) >> 31; \
if ((weight = (weight ^ s) + (2 - s)) > 1024) weight = 1024; \
weight = (weight ^ s) - s; \
}
void pack_init (WavpackContext *wpc);
int pack_block (WavpackContext *wpc, int32_t *buffer);
void send_general_metadata (WavpackContext *wpc);
@ -752,7 +575,7 @@ int FASTCALL wp_log2 (uint32_t avalue);
#ifdef OPT_ASM_X86
#define LOG2BUFFER log2buffer_x86
#elif defined(OPT_ASM_X64) && (defined (_WIN64) || defined(__CYGWIN__) || defined(__MINGW64__))
#elif defined(OPT_ASM_X64) && (defined (_WIN64) || defined(__CYGWIN__) || defined(__MINGW64__) || defined(__midipix__))
#define LOG2BUFFER log2buffer_x64win
#elif defined(OPT_ASM_X64)
#define LOG2BUFFER log2buffer_x64
@ -793,24 +616,10 @@ WavpackContext *WavpackOpenFileInput (const char *infilename, char *error, int f
#define OPEN_DSD_AS_PCM 0x200 // open DSD files as 24-bit PCM (decimated 8x)
#define OPEN_ALT_TYPES 0x400 // application is aware of alternate file types & qmode
// (just affects retrieving wrappers & MD5 checksums)
#define OPEN_NO_CHECKSUM 0x800 // don't verify block checksums before decoding
int WavpackGetMode (WavpackContext *wpc);
#define MODE_WVC 0x1
#define MODE_LOSSLESS 0x2
#define MODE_HYBRID 0x4
#define MODE_FLOAT 0x8
#define MODE_VALID_TAG 0x10
#define MODE_HIGH 0x20
#define MODE_FAST 0x40
#define MODE_EXTRA 0x80 // extra mode used, see MODE_XMODE for possible level
#define MODE_APETAG 0x100
#define MODE_SFX 0x200
#define MODE_VERY_HIGH 0x400
#define MODE_MD5 0x800
#define MODE_XMODE 0x7000 // mask for extra level (1-6, 0=unknown)
#define MODE_DNS 0x8000
int WavpackGetQualifyMode (WavpackContext *wpc);
int WavpackGetVersion (WavpackContext *wpc);
uint32_t WavpackUnpackSamples (WavpackContext *wpc, int32_t *buffer, uint32_t samples);
@ -818,6 +627,7 @@ int WavpackSeekSample (WavpackContext *wpc, uint32_t sample);
int WavpackSeekSample64 (WavpackContext *wpc, int64_t sample);
int WavpackGetMD5Sum (WavpackContext *wpc, unsigned char data [16]);
int WavpackVerifySingleBlock (unsigned char *buffer, int verify_checksum);
uint32_t read_next_header (WavpackStreamReader64 *reader, void *id, WavpackHeader *wphdr);
int read_wvc_block (WavpackContext *wpc);
@ -826,7 +636,7 @@ int read_wvc_block (WavpackContext *wpc);
WavpackContext *WavpackOpenFileOutput (WavpackBlockOutput blockout, void *wv_id, void *wvc_id);
int WavpackSetConfiguration (WavpackContext *wpc, WavpackConfig *config, uint32_t total_samples);
int WavpackSetConfiguration64 (WavpackContext *wpc, WavpackConfig *config, int64_t total_samples);
int WavpackSetConfiguration64 (WavpackContext *wpc, WavpackConfig *config, int64_t total_samples, const unsigned char *chan_ids);
int WavpackPackInit (WavpackContext *wpc);
int WavpackAddWrapper (WavpackContext *wpc, void *data, uint32_t bcount);
int WavpackPackSamples (WavpackContext *wpc, int32_t *sample_buffer, uint32_t sample_count);
@ -871,6 +681,8 @@ void WavpackNativeToLittleEndian (void *data, char *format);
void WavpackBigEndianToNative (void *data, char *format);
void WavpackNativeToBigEndian (void *data, char *format);
void install_close_callback (WavpackContext *wpc, void cb_func (void *wpc));
void free_dsd_tables (WavpackStream *wps);
void free_streams (WavpackContext *wpc);
/////////////////////////////////// tag utilities ////////////////////////////////////

View File

@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////////////////////
// **** WAVPACK **** //
// Hybrid Lossless Wavefile Compressor //
// Copyright (c) 1998 - 2006 Conifer Software. //
// Copyright (c) 1998 - 2019 David Bryant. //
// All Rights Reserved. //
// Distributed under the BSD Software License (see license.txt) //
////////////////////////////////////////////////////////////////////////////
@ -12,8 +12,8 @@
#define WAVPACK_VERSION_H
#define LIBWAVPACK_MAJOR 5
#define LIBWAVPACK_MINOR 0
#define LIBWAVPACK_MINOR 2
#define LIBWAVPACK_MICRO 0
#define LIBWAVPACK_VERSION_STRING "5.0.0-alpha4"
#define LIBWAVPACK_VERSION_STRING "5.2.0"
#endif

View File

@ -569,21 +569,19 @@ int32_t nosend_word (WavpackStream *wps, int32_t value, int chan)
}
// This function is used to scan some number of samples to set the variables
// "slow_level" and the "median" array. In pure symetrical encoding mode this
// "slow_level" and the "median" array. In pure symmetrical encoding mode this
// would not be needed because these values would simply be continued from the
// previous block. However, in the -X modes and the 32-bit modes we cannot do
// this because parameters may change between blocks and the variables might
// not apply. This function can work in mono or stereo and can scan a block
// in either direction.
void scan_word (WavpackStream *wps, int32_t *samples, uint32_t num_samples, int dir)
static void scan_word_pass (WavpackStream *wps, int32_t *samples, uint32_t num_samples, int dir)
{
uint32_t flags = wps->wphdr.flags, value, low;
struct entropy_data *c = wps->w.c;
int chan;
init_words (wps);
if (flags & MONO_DATA) {
if (dir < 0) {
samples += (num_samples - 1);
@ -672,3 +670,19 @@ void scan_word (WavpackStream *wps, int32_t *samples, uint32_t num_samples, int
}
}
// Wrapper for scan_word_pass() than ensures that at least 2048 samples are processed by
// potentially making multiple passes through the data. See description of scan_word_pass()
// for more details.
void scan_word (WavpackStream *wps, int32_t *samples, uint32_t num_samples, int dir)
{
init_words (wps);
if (num_samples) {
int passes = (2048 + num_samples - 1) / num_samples; // i.e., ceil (2048.0 / num_samples)
while (passes--)
scan_word_pass (wps, samples, num_samples, dir);
}
}

View File

@ -348,6 +348,8 @@
GCC_PREFIX_HEADER = "";
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
ENABLE_DSD,
ENABLE_LEGACY,
PACK,
UNPACK,
USE_FSTREAMS,
@ -356,8 +358,8 @@
VER3,
"PACKAGE_NAME='\"wavpack\"'",
"PACKAGE_TARNAME='\"wavpack\"'",
"PACKAGE_VERSION='\"4.70.0\"'",
"PACKAGE_STRING='\"wavpack 4.70.0\"'",
"PACKAGE_VERSION='\"5.2.0\"'",
"PACKAGE_STRING='\"wavpack 5.2.0\"'",
"PACKAGE_BUGREPORT='\"bryant@wavpack.com\"'",
"VERSION_OS='\"Darwin\"'",
);
@ -383,6 +385,8 @@
GCC_PRECOMPILE_PREFIX_HEADER = NO;
GCC_PREFIX_HEADER = "";
GCC_PREPROCESSOR_DEFINITIONS = (
ENABLE_DSD,
ENABLE_LEGACY,
PACK,
UNPACK,
USE_FSTREAMS,

View File

@ -124,13 +124,20 @@ int32_t WriteBytesProc(void *ds, void *data, int32_t bcount)
wv = [[WavPackReader alloc] initWithSource:s];
id audioSourceClass = NSClassFromString(@"AudioSource");
NSURL *wvcurl = [[s url] URLByDeletingPathExtension];
wvcurl = [wvcurl URLByAppendingPathExtension:@"wvc"];
id<CogSource> wvcsrc = [audioSourceClass audioSourceForURL:wvcurl];
if ([wvcsrc open:wvcurl])
if ([s seekable])
{
wvc = [[WavPackReader alloc] initWithSource:wvcsrc];
id audioSourceClass = NSClassFromString(@"AudioSource");
NSURL *wvcurl = [[s url] URLByDeletingPathExtension];
wvcurl = [wvcurl URLByAppendingPathExtension:@"wvc"];
id<CogSource> wvcsrc = [audioSourceClass audioSourceForURL:wvcurl];
if ([wvcsrc open:wvcurl])
{
wvc = [[WavPackReader alloc] initWithSource:wvcsrc];
}
else
{
wvc = nil;
}
}
else
{
@ -147,6 +154,9 @@ int32_t WriteBytesProc(void *ds, void *data, int32_t bcount)
reader.write_bytes = WriteBytesProc;
open_flags |= OPEN_DSD_AS_PCM | OPEN_ALT_TYPES;
if (![s seekable])
open_flags |= OPEN_STREAMING;
wpc = WavpackOpenFileInputEx(&reader, (__bridge void *)(wv), (__bridge void *)(wvc), error, open_flags, 0);
if (!wpc) {