If you have an issue with any of our projects. feel free to register.

Commit 9ca13ad4 authored by Christopher Snowhill's avatar Christopher Snowhill

Updated WavPack decoder to 5.2.0

parent 3e6d5994
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>
This diff is collapsed.
This diff is collapsed.
////////////////////////////////////////////////////////////////////////////
// **** 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
<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).
......@@ -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;
......
#! /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)