Updated WavPack to version 4.60.1
parent
63b8f55dcf
commit
43704d16ce
|
@ -1,85 +1,103 @@
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
// **** WAVPACK **** //
|
// **** WAVPACK **** //
|
||||||
// Hybrid Lossless Wavefile Compressor //
|
// Hybrid Lossless Wavefile Compressor //
|
||||||
// Copyright (c) 1998 - 2005 Conifer Software. //
|
// Copyright (c) 1998 - 2006 Conifer Software. //
|
||||||
// All Rights Reserved. //
|
// All Rights Reserved. //
|
||||||
// Distributed under the BSD Software License (see license.txt) //
|
// Distributed under the BSD Software License (see license.txt) //
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
This package contains all the source code required to build the WavPack
|
This package contains all the source code required to build the WavPack
|
||||||
command-line programs and the WavPack library and it has been tested on many
|
command-line programs and the WavPack library and it has been tested on many
|
||||||
platforms. For example code using the library you might want to check some
|
platforms.
|
||||||
of the plugin sources in the Windows source release.
|
|
||||||
|
|
||||||
To build everything, type:
|
On Windows there are solution and project files for Visual Studio 2005 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.
|
||||||
|
|
||||||
1. ./configure
|
To build everything on Linux, type:
|
||||||
|
|
||||||
|
1. ./configure [--enable-mmx]
|
||||||
2. make
|
2. make
|
||||||
3. make install (optionally, to install into /usr/local/bin)
|
3. make install (optionally, to install into /usr/local/bin)
|
||||||
|
|
||||||
|
If you are using the code directly from SVN (rather than a distribution)
|
||||||
|
then you will need to do a ./autogen.sh before the configure step. For
|
||||||
|
processors that support MMX, use the --enable-mmx switch to utilize MMX
|
||||||
|
intrinsics to speed up encoding of stereo 24-bit (and higher) audio.
|
||||||
|
|
||||||
Notes:
|
Notes:
|
||||||
|
|
||||||
1. This code is designed to be much easier to port to other platforms than
|
1. There are two documentation files contained in the distribution:
|
||||||
the previous version of WavPack. File I/O is done with streams and all file
|
|
||||||
functions (except "fopen") are handled in a wrapper in the "utils.c"
|
doc/library_use.txt contains a detailed description of the API provided
|
||||||
module. The code is even written to be endian-independent and a compile
|
by WavPack library appropriate for read and writing
|
||||||
option is provided to eliminate the DOS-specific directory searches.
|
WavPack files
|
||||||
|
|
||||||
|
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. File I/O is
|
||||||
|
done with streams and all file functions (except "fopen") are handled in
|
||||||
|
a wrapper in the "utils.c" module. The code is endian-independent.
|
||||||
|
|
||||||
To maintain compatibility on various platforms, the following conventions
|
To maintain compatibility on various platforms, the following conventions
|
||||||
are used:
|
are used: A "short" must be 16-bits and an "int" must be 32-bits.
|
||||||
|
The "long" type is not used. The "char" type must be 8-bits, signed or
|
||||||
|
unsigned.
|
||||||
|
|
||||||
a "short" must be 16-bits
|
3. For WavPack file decoding, a library interface in "wputils.c" provides all
|
||||||
an "int" must be at least 16-bits, but may be larger
|
|
||||||
|
|
||||||
For version 4.2 references to "long" variables were eliminated to allow
|
|
||||||
compilation on 64-bit machines. For version 4.3 "char" types may default
|
|
||||||
to signed or unsigned.
|
|
||||||
|
|
||||||
2. For WavPack file decoding, a library interface in "wputils.c" provides all
|
|
||||||
the functionality required for both the winamp plugin and the "wvunpack"
|
the functionality required for both the winamp plugin and the "wvunpack"
|
||||||
command-line program (including the transparent decoding of "correction"
|
command-line program (including the transparent decoding of "correction"
|
||||||
files). There is also an alternate entry point that uses reader callbacks
|
files). There is also an alternate entry point that uses reader callbacks
|
||||||
for all input, although in this case it is the caller's responsibility to
|
for all input, although in this case it is the caller's responsibility to
|
||||||
to open the "correction" file. It is no longer necessary to manipulate the
|
to open the "correction" file. The header file "include/wavpack.h"
|
||||||
WavPack structures directly; everything is handled with function calls. In
|
includes everything needed while hiding all the WavPack internals from the
|
||||||
fact, a new header file called "wputils.h" can be used that hides all the
|
application.
|
||||||
WavPack internals from the application.
|
|
||||||
|
|
||||||
3. For WavPack file creation, the library interface in "wputils.c" provides
|
4. For WavPack file creation, the library interface in "wputils.c" provides
|
||||||
all the functionality for both the Audition filter and the "wavpack"
|
all the functionality for both the Audition filter and the "wavpack"
|
||||||
command-line program. No file I/O is performed by the library when creating
|
command-line program. No file I/O is performed by the library when creating
|
||||||
WavPack files. Instead, the user supplies a "write_block" function that
|
WavPack files. Instead, the user supplies a "write_block" function that
|
||||||
accepts completed WavPack blocks. For version 4.2 limited functionality
|
accepts completed WavPack blocks. It is also possible to append APEv2 tags
|
||||||
has been added to append APEv2 tags to WavPack files during creation.
|
to WavPack files during creation and edit APEv2 tags on existing files
|
||||||
|
(although there is no support currently for "binary" fields in the tags).
|
||||||
|
|
||||||
4. The following #define's are used to control the optimum configuration of
|
5. The following #define's can be optionally used to eliminate some functionality
|
||||||
the library for the desired application and must be the same for the
|
to create smaller binaries. It is important that they must be specified
|
||||||
compilation of ALL files:
|
the same for the compilation of ALL files:
|
||||||
|
|
||||||
UNPACK to unpack audio samples from WavPack files
|
NO_UNPACK no unpacking of audio samples from WavPack files
|
||||||
PACK to create WavPack files from raw audio data
|
(also don't include unpack.c)
|
||||||
|
NO_PACK no creating WavPack files from raw audio data
|
||||||
|
(also don't include pack.c, extra1.c and extra2.c)
|
||||||
INFO_ONLY to obtain information from WavPack files, but not audio
|
INFO_ONLY to obtain information from WavPack files, but not audio
|
||||||
SEEKING to allow seeking to a specific sample index (unpack only)
|
(also don't include pack.c, extra1.c and extra2.c)
|
||||||
USE_FSTREAMS to open WavPack files by name using fstreams (via fopen)
|
NO_SEEKING to not allow seeking to a specific sample index (unpack only)
|
||||||
TAGS to read specified fields from ID3v1 and APEv2 tags and
|
NO_USE_FSTREAMS to not open WavPack files by name using fstreams
|
||||||
|
NO_TAGS to not read specified fields from ID3v1 and APEv2 tags and
|
||||||
create APEv2 tags
|
create APEv2 tags
|
||||||
VER3 to handle WavPack files from versions prior to 4.0
|
VER4_ONLY to only handle WavPack files from versions 4.0 onward
|
||||||
WIN32 required for Win32 platform
|
WIN32 required for Win32 platform
|
||||||
|
|
||||||
The following files are required for various configurations:
|
6. 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.
|
||||||
|
|
||||||
UNPACK or
|
For applications requiring very low latency, there is a special version of
|
||||||
INFO_ONLY: wputils.c unpack.c words.c bits.c metadata.c float.c
|
the library that supports a variation on the regular WavPack block format
|
||||||
|
to facilitate this.
|
||||||
|
|
||||||
PACK: wputils.c pack.c extra1.c extra2.c
|
7. Questions or comments should be directed to david@wavpack.com
|
||||||
words.c bits.c metadata.c float.c
|
|
||||||
|
|
||||||
PACK and
|
|
||||||
UNPACK: wputils.c unpack.c pack.c extra1.c extra2.c
|
|
||||||
words.c bits.c metadata.c float.c
|
|
||||||
|
|
||||||
5. An alternate version of this library is available specifically designed
|
|
||||||
for "resource limited" CPUs or hardware decoding. This "tiny" decoder
|
|
||||||
library works with less than 32k of code and less than 4k of data.
|
|
||||||
|
|
||||||
6. Questions or comments should be directed to david@wavpack.com
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
// **** WAVPACK **** //
|
// **** WAVPACK **** //
|
||||||
// Hybrid Lossless Wavefile Compressor //
|
// Hybrid Lossless Wavefile Compressor //
|
||||||
// Copyright (c) 1998 - 2005 Conifer Software. //
|
// Copyright (c) 1998 - 2006 Conifer Software. //
|
||||||
// All Rights Reserved. //
|
// All Rights Reserved. //
|
||||||
// Distributed under the BSD Software License (see license.txt) //
|
// Distributed under the BSD Software License (see license.txt) //
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -14,7 +14,7 @@
|
||||||
// endian-ness, both for enhancing portability. Finally, a debug wrapper for
|
// endian-ness, both for enhancing portability. Finally, a debug wrapper for
|
||||||
// the malloc() system is provided.
|
// the malloc() system is provided.
|
||||||
|
|
||||||
#include "wavpack.h"
|
#include "wavpack_local.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -24,18 +24,21 @@
|
||||||
#if defined(WIN32)
|
#if defined(WIN32)
|
||||||
#include <io.h>
|
#include <io.h>
|
||||||
#else
|
#else
|
||||||
|
#if defined(__OS2__)
|
||||||
|
#include <io.h>
|
||||||
|
#endif
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
////////////////////////// Bitstream functions ////////////////////////////////
|
////////////////////////// Bitstream functions ////////////////////////////////
|
||||||
|
|
||||||
#if defined(UNPACK) || defined(INFO_ONLY)
|
#if !defined(NO_UNPACK) || defined(INFO_ONLY)
|
||||||
|
|
||||||
// Open the specified BitStream and associate with the specified buffer.
|
// Open the specified BitStream and associate with the specified buffer.
|
||||||
|
|
||||||
static void bs_read (Bitstream *bs);
|
static void bs_read (Bitstream *bs);
|
||||||
|
|
||||||
void bs_open_read (Bitstream *bs, uchar *buffer_start, uchar *buffer_end)
|
void bs_open_read (Bitstream *bs, void *buffer_start, void *buffer_end)
|
||||||
{
|
{
|
||||||
bs->error = bs->sr = bs->bc = 0;
|
bs->error = bs->sr = bs->bc = 0;
|
||||||
bs->ptr = (bs->buf = buffer_start) - 1;
|
bs->ptr = (bs->buf = buffer_start) - 1;
|
||||||
|
@ -61,20 +64,21 @@ uint32_t bs_close_read (Bitstream *bs)
|
||||||
{
|
{
|
||||||
uint32_t bytes_read;
|
uint32_t bytes_read;
|
||||||
|
|
||||||
if (bs->bc < 8)
|
if (bs->bc < sizeof (*(bs->ptr)) * 8)
|
||||||
bs->ptr++;
|
bs->ptr++;
|
||||||
|
|
||||||
if ((bs->buf - bs->ptr) & 1)
|
bytes_read = (uint32_t)(bs->ptr - bs->buf) * sizeof (*(bs->ptr));
|
||||||
bs->ptr++;
|
|
||||||
|
if (!(bytes_read & 1))
|
||||||
|
++bytes_read;
|
||||||
|
|
||||||
bytes_read = bs->ptr - bs->buf;
|
|
||||||
CLEAR (*bs);
|
CLEAR (*bs);
|
||||||
return bytes_read;
|
return bytes_read;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef PACK
|
#ifndef NO_PACK
|
||||||
|
|
||||||
// Open the specified BitStream using the specified buffer pointers. It is
|
// Open the specified BitStream using the specified buffer pointers. It is
|
||||||
// assumed that enough buffer space has been allocated for all data that will
|
// assumed that enough buffer space has been allocated for all data that will
|
||||||
|
@ -82,7 +86,7 @@ uint32_t bs_close_read (Bitstream *bs)
|
||||||
|
|
||||||
static void bs_write (Bitstream *bs);
|
static void bs_write (Bitstream *bs);
|
||||||
|
|
||||||
void bs_open_write (Bitstream *bs, uchar *buffer_start, uchar *buffer_end)
|
void bs_open_write (Bitstream *bs, void *buffer_start, void *buffer_end)
|
||||||
{
|
{
|
||||||
bs->error = bs->sr = bs->bc = 0;
|
bs->error = bs->sr = bs->bc = 0;
|
||||||
bs->ptr = bs->buf = buffer_start;
|
bs->ptr = bs->buf = buffer_start;
|
||||||
|
@ -107,10 +111,21 @@ uint32_t bs_close_write (Bitstream *bs)
|
||||||
uint32_t bytes_written;
|
uint32_t bytes_written;
|
||||||
|
|
||||||
if (bs->error)
|
if (bs->error)
|
||||||
return (uint32_t) -1;
|
return (uint32_t) -1;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
while (bs->bc)
|
||||||
|
putbit_1 (bs);
|
||||||
|
|
||||||
|
bytes_written = (uint32_t)(bs->ptr - bs->buf) * sizeof (*(bs->ptr));
|
||||||
|
|
||||||
|
if (bytes_written & 1) {
|
||||||
|
putbit_1 (bs);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
while (bs->bc || ((bs->ptr - bs->buf) & 1)) putbit_1 (bs);
|
|
||||||
bytes_written = bs->ptr - bs->buf;
|
|
||||||
CLEAR (*bs);
|
CLEAR (*bs);
|
||||||
return bytes_written;
|
return bytes_written;
|
||||||
}
|
}
|
||||||
|
@ -121,63 +136,63 @@ uint32_t bs_close_write (Bitstream *bs)
|
||||||
|
|
||||||
void little_endian_to_native (void *data, char *format)
|
void little_endian_to_native (void *data, char *format)
|
||||||
{
|
{
|
||||||
uchar *cp = (uchar *) data;
|
unsigned char *cp = (unsigned char *) data;
|
||||||
int32_t temp;
|
int32_t temp;
|
||||||
|
|
||||||
while (*format) {
|
while (*format) {
|
||||||
switch (*format) {
|
switch (*format) {
|
||||||
case 'L':
|
case 'L':
|
||||||
temp = cp [0] + ((int32_t) cp [1] << 8) + ((int32_t) cp [2] << 16) + ((int32_t) cp [3] << 24);
|
temp = cp [0] + ((int32_t) cp [1] << 8) + ((int32_t) cp [2] << 16) + ((int32_t) cp [3] << 24);
|
||||||
* (int32_t *) cp = temp;
|
* (int32_t *) cp = temp;
|
||||||
cp += 4;
|
cp += 4;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'S':
|
case 'S':
|
||||||
temp = cp [0] + (cp [1] << 8);
|
temp = cp [0] + (cp [1] << 8);
|
||||||
* (short *) cp = (short) temp;
|
* (short *) cp = (short) temp;
|
||||||
cp += 2;
|
cp += 2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (isdigit (*format))
|
if (isdigit (*format))
|
||||||
cp += *format - '0';
|
cp += *format - '0';
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
format++;
|
format++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void native_to_little_endian (void *data, char *format)
|
void native_to_little_endian (void *data, char *format)
|
||||||
{
|
{
|
||||||
uchar *cp = (uchar *) data;
|
unsigned char *cp = (unsigned char *) data;
|
||||||
int32_t temp;
|
int32_t temp;
|
||||||
|
|
||||||
while (*format) {
|
while (*format) {
|
||||||
switch (*format) {
|
switch (*format) {
|
||||||
case 'L':
|
case 'L':
|
||||||
temp = * (int32_t *) cp;
|
temp = * (int32_t *) cp;
|
||||||
*cp++ = (uchar) temp;
|
*cp++ = (unsigned char) temp;
|
||||||
*cp++ = (uchar) (temp >> 8);
|
*cp++ = (unsigned char) (temp >> 8);
|
||||||
*cp++ = (uchar) (temp >> 16);
|
*cp++ = (unsigned char) (temp >> 16);
|
||||||
*cp++ = (uchar) (temp >> 24);
|
*cp++ = (unsigned char) (temp >> 24);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'S':
|
case 'S':
|
||||||
temp = * (short *) cp;
|
temp = * (short *) cp;
|
||||||
*cp++ = (uchar) temp;
|
*cp++ = (unsigned char) temp;
|
||||||
*cp++ = (uchar) (temp >> 8);
|
*cp++ = (unsigned char) (temp >> 8);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (isdigit (*format))
|
if (isdigit (*format))
|
||||||
cp += *format - '0';
|
cp += *format - '0';
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
format++;
|
format++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,13 +207,13 @@ static void *add_ptr (void *ptr)
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < 512; ++i)
|
for (i = 0; i < 512; ++i)
|
||||||
if (!vptrs [i]) {
|
if (!vptrs [i]) {
|
||||||
vptrs [i] = ptr;
|
vptrs [i] = ptr;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i == 512)
|
if (i == 512)
|
||||||
error_line ("too many mallocs!");
|
error_line ("too many mallocs!");
|
||||||
|
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
@ -208,13 +223,13 @@ static void *del_ptr (void *ptr)
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < 512; ++i)
|
for (i = 0; i < 512; ++i)
|
||||||
if (vptrs [i] == ptr) {
|
if (vptrs [i] == ptr) {
|
||||||
vptrs [i] = NULL;
|
vptrs [i] = NULL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i == 512)
|
if (i == 512)
|
||||||
error_line ("free invalid ptr!");
|
error_line ("free invalid ptr!");
|
||||||
|
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
@ -222,25 +237,25 @@ static void *del_ptr (void *ptr)
|
||||||
void *malloc_db (uint32_t size)
|
void *malloc_db (uint32_t size)
|
||||||
{
|
{
|
||||||
if (size)
|
if (size)
|
||||||
return add_ptr (malloc (size));
|
return add_ptr (malloc (size));
|
||||||
else
|
else
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void free_db (void *ptr)
|
void free_db (void *ptr)
|
||||||
{
|
{
|
||||||
if (ptr)
|
if (ptr)
|
||||||
free (del_ptr (ptr));
|
free (del_ptr (ptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
void *realloc_db (void *ptr, uint32_t size)
|
void *realloc_db (void *ptr, uint32_t size)
|
||||||
{
|
{
|
||||||
if (ptr && size)
|
if (ptr && size)
|
||||||
return add_ptr (realloc (del_ptr (ptr), size));
|
return add_ptr (realloc (del_ptr (ptr), size));
|
||||||
else if (size)
|
else if (size)
|
||||||
return malloc_db (size);
|
return malloc_db (size);
|
||||||
else
|
else
|
||||||
free_db (ptr);
|
free_db (ptr);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -250,8 +265,8 @@ int32_t dump_alloc (void)
|
||||||
int i, j;
|
int i, j;
|
||||||
|
|
||||||
for (j = i = 0; i < 512; ++i)
|
for (j = i = 0; i < 512; ++i)
|
||||||
if (vptrs [i])
|
if (vptrs [i])
|
||||||
j++;
|
j++;
|
||||||
|
|
||||||
return j;
|
return j;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#! /bin/sh
|
#! /bin/sh
|
||||||
# Wrapper for compilers which do not understand `-c -o'.
|
# Wrapper for compilers which do not understand `-c -o'.
|
||||||
|
|
||||||
scriptversion=2005-02-03.08
|
scriptversion=2005-05-14.22
|
||||||
|
|
||||||
# Copyright (C) 1999, 2000, 2003, 2004, 2005 Free Software Foundation, Inc.
|
# Copyright (C) 1999, 2000, 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||||
# Written by Tom Tromey <tromey@cygnus.com>.
|
# Written by Tom Tromey <tromey@cygnus.com>.
|
||||||
|
@ -18,7 +18,7 @@ scriptversion=2005-02-03.08
|
||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program; if not, write to the Free Software
|
# along with this program; if not, write to the Free Software
|
||||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
# As a special exception to the GNU General Public License, if you
|
# As a special exception to the GNU General Public License, if you
|
||||||
# distribute this file as part of a program that contains a
|
# distribute this file as part of a program that contains a
|
||||||
|
|
|
@ -1,8 +1,32 @@
|
||||||
# wavpack 4.32 configure.ac
|
# wavpack 4.60.1 configure.ac
|
||||||
|
|
||||||
AC_INIT(wavpack, 4.32, bryant@wavpack.com)
|
AC_INIT(wavpack, 4.60.1, bryant@wavpack.com)
|
||||||
AM_INIT_AUTOMAKE(wavpack, 4.32, bryant@wavpack.com)
|
AM_INIT_AUTOMAKE(wavpack, 4.60.1, bryant@wavpack.com)
|
||||||
AC_CONFIG_SRCDIR([pack.c])
|
AC_CONFIG_SRCDIR([src/pack.c])
|
||||||
|
AM_MAINTAINER_MODE
|
||||||
|
|
||||||
|
LIBWAVPACK_MAJOR=4
|
||||||
|
LIBWAVPACK_MINOR=60
|
||||||
|
LIBWAVPACK_MICRO=1
|
||||||
|
LIBWAVPACK_VERSION_STRING=$LIBWAVPACK_MAJOR.$LIBWAVPACK_MINOR.$LIBWAVPACK_MICRO
|
||||||
|
|
||||||
|
AC_DEFINE_UNQUOTED(LIBWAVPACK_MAJOR, $LIBWAVPACK_MAJOR, [libwavpack major version])
|
||||||
|
AC_DEFINE_UNQUOTED(LIBWAVPACK_MINOR, $LIBWAVPACK_MINOR, [libwavpack minor version])
|
||||||
|
AC_DEFINE_UNQUOTED(LIBWAVPACK_MICRO, $LIBWAVPACK_MICRO, [libwavpack micro version])
|
||||||
|
AC_DEFINE_UNQUOTED(LIBWAVPACK_VERSION_STRING, "$LIBWAVPACK_VERSION_STRING", [libwavpack version string])
|
||||||
|
|
||||||
|
# set libtool versioning
|
||||||
|
# +1 : 0 : +1 == new interface that does not break old one.
|
||||||
|
# +1 : 0 : 0 == changed/removed an interface. Breaks old apps.
|
||||||
|
# ? : +1 : ? == internal changes that doesn't break anything.
|
||||||
|
# CURRENT : REVISION : AGE
|
||||||
|
LT_CURRENT=2
|
||||||
|
LT_REVISION=4
|
||||||
|
LT_AGE=1
|
||||||
|
|
||||||
|
AC_SUBST(LT_CURRENT)
|
||||||
|
AC_SUBST(LT_REVISION)
|
||||||
|
AC_SUBST(LT_AGE)
|
||||||
|
|
||||||
# Check for os version
|
# Check for os version
|
||||||
VERSION_OS=$(uname -s)
|
VERSION_OS=$(uname -s)
|
||||||
|
@ -13,18 +37,28 @@ AC_C_BIGENDIAN(AC_DEFINE([HIGHFIRST], [1], [big-endian machine]))
|
||||||
|
|
||||||
# Checks for programs.
|
# Checks for programs.
|
||||||
AC_PROG_CC
|
AC_PROG_CC
|
||||||
|
AC_LIBTOOL_WIN32_DLL
|
||||||
AC_PROG_LIBTOOL
|
AC_PROG_LIBTOOL
|
||||||
|
AC_PROG_INSTALL
|
||||||
|
AM_PROG_CC_C_O
|
||||||
|
|
||||||
|
AC_HEADER_STDC
|
||||||
|
|
||||||
# Checks for libraries.
|
# Checks for libraries.
|
||||||
AC_CHECK_LIB(m, log10, [], AC_MSG_ERROR(math library not found))
|
AC_CHECK_LIBM
|
||||||
|
AC_SUBST(LIBM)
|
||||||
|
|
||||||
|
# Check if cross-compiling on mingw
|
||||||
|
AC_MINGW32
|
||||||
|
|
||||||
|
if test "x$MINGW32" != "xyes" ; then
|
||||||
# Check for iconv
|
# Check for iconv
|
||||||
AC_ARG_WITH(iconv, [ --with-iconv[=DIR] Add ICONV support (on)])
|
AC_ARG_WITH(iconv, [[ --with-iconv[=DIR] add ICONV support [yes]]])
|
||||||
if test "$with_iconv" = "no" ; then
|
if test "$with_iconv" = "no" ; then
|
||||||
AC_MSG_ERROR([[Sorry, you can't deactivate iconv.]])
|
AC_MSG_ERROR([[Sorry, you can't deactivate iconv.]])
|
||||||
else
|
else
|
||||||
if test "$with_iconv" != "yes" -a "$with_iconv" != "" ; then
|
if test "$with_iconv" != "yes" -a "$with_iconv" != "" ; then
|
||||||
CPPFLAGS="${CPPFLAGS} -I$with_iconv/include"
|
ICONV_CFLAGS="${CPPFLAGS} -I$with_iconv/include"
|
||||||
ICONV_LIBS="-L$with_iconv/lib"
|
ICONV_LIBS="-L$with_iconv/lib"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -35,13 +69,12 @@ else
|
||||||
iconv_t cd = iconv_open ("","");
|
iconv_t cd = iconv_open ("","");
|
||||||
iconv (cd, NULL, NULL, NULL, NULL);],[
|
iconv (cd, NULL, NULL, NULL, NULL);],[
|
||||||
AC_MSG_RESULT(yes)
|
AC_MSG_RESULT(yes)
|
||||||
WITH_ICONV=1
|
WITH_ICONV=1],[
|
||||||
ICONV=""],[
|
|
||||||
AC_MSG_RESULT(no)
|
AC_MSG_RESULT(no)
|
||||||
AC_MSG_CHECKING(for iconv in -liconv)
|
AC_MSG_CHECKING(for iconv in -liconv)
|
||||||
|
|
||||||
_ldflags="${LDFLAGS}"
|
old_ldflags="${LDFLAGS}"
|
||||||
_libs="${LIBS}"
|
old_libs="${LIBS}"
|
||||||
LDFLAGS="${LDFLAGS} ${ICONV_LIBS}"
|
LDFLAGS="${LDFLAGS} ${ICONV_LIBS}"
|
||||||
LIBS="${LIBS} -liconv"
|
LIBS="${LIBS} -liconv"
|
||||||
|
|
||||||
|
@ -52,11 +85,51 @@ iconv (cd, NULL, NULL, NULL, NULL);],[
|
||||||
AC_MSG_RESULT(yes)
|
AC_MSG_RESULT(yes)
|
||||||
WITH_ICONV=1
|
WITH_ICONV=1
|
||||||
ICONV_LIBS="${ICONV_LIBS} -liconv"
|
ICONV_LIBS="${ICONV_LIBS} -liconv"
|
||||||
ICONV="${ICONV_LIBS}"],[
|
ICONV="-liconv"],[
|
||||||
AC_MSG_ERROR([[Can't find iconv libraries.]])])]),
|
AC_MSG_ERROR([[Can't find iconv libraries.]])])
|
||||||
AC_MSG_ERROR([[Can't find iconv headers.]]))
|
LDFLAGS=$old_ldflags
|
||||||
|
LIBS=$old_libs
|
||||||
|
]),
|
||||||
|
AC_MSG_ERROR([[Can't find iconv headers.]]))
|
||||||
fi
|
fi
|
||||||
AC_SUBST(ICONV)
|
|
||||||
AC_SUBST(ICONV_LIBS)
|
AC_SUBST(ICONV_LIBS)
|
||||||
|
AC_SUBST(ICONV)
|
||||||
|
fi
|
||||||
|
|
||||||
AC_OUTPUT(Makefile wavpack.pc)
|
AC_ARG_ENABLE(mmx, [[ --enable-mmx enable MMX optimizations [default=no]]])
|
||||||
|
if test "x$enable_mmx" = "xyes" ; then
|
||||||
|
AC_DEFINE([OPT_MMX], 1, [MMX optimization])
|
||||||
|
$CC $CFLAGS -mmmx -S -o /dev/null -xc /dev/null > /dev/null 2>&1 && CFLAGS="-mmmx $CFLAGS"
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(man,
|
||||||
|
[AC_HELP_STRING([--enable-man],
|
||||||
|
[regenerate man pages from Docbook [default=no]])],enable_man=yes,
|
||||||
|
enable_man=no)
|
||||||
|
|
||||||
|
if test "${enable_man}" != no; then
|
||||||
|
dnl
|
||||||
|
dnl Check for xsltproc
|
||||||
|
dnl
|
||||||
|
AC_PATH_PROG([XSLTPROC], [xsltproc])
|
||||||
|
if test -z "$XSLTPROC"; then
|
||||||
|
enable_man=no
|
||||||
|
fi
|
||||||
|
|
||||||
|
dnl check for DocBook DTD and stylesheets in the local catalog.
|
||||||
|
JH_CHECK_XML_CATALOG([-//OASIS//DTD DocBook XML V4.1.2//EN],
|
||||||
|
[DocBook XML DTD V4.1.2],,enable_man=no)
|
||||||
|
JH_CHECK_XML_CATALOG([http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl],
|
||||||
|
[DocBook XSL Stylesheets],,enable_man=no)
|
||||||
|
fi
|
||||||
|
|
||||||
|
AM_CONDITIONAL(ENABLE_MAN, test x$enable_man != xno)
|
||||||
|
|
||||||
|
AC_CONFIG_FILES(
|
||||||
|
Makefile
|
||||||
|
wavpack.pc
|
||||||
|
src/Makefile
|
||||||
|
include/Makefile
|
||||||
|
cli/Makefile
|
||||||
|
man/Makefile)
|
||||||
|
AC_OUTPUT
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
#! /bin/sh
|
#! /bin/sh
|
||||||
# depcomp - compile a program generating dependencies as side-effects
|
# depcomp - compile a program generating dependencies as side-effects
|
||||||
|
|
||||||
scriptversion=2005-02-09.22
|
scriptversion=2007-03-29.01
|
||||||
|
|
||||||
# Copyright (C) 1999, 2000, 2003, 2004, 2005 Free Software Foundation, Inc.
|
# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007 Free Software
|
||||||
|
# Foundation, Inc.
|
||||||
|
|
||||||
# This program is free software; you can redistribute it and/or modify
|
# 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
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
@ -17,8 +18,8 @@ scriptversion=2005-02-09.22
|
||||||
|
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program; if not, write to the Free Software
|
# along with this program; if not, write to the Free Software
|
||||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||||
# 02111-1307, USA.
|
# 02110-1301, USA.
|
||||||
|
|
||||||
# As a special exception to the GNU General Public License, if you
|
# As a special exception to the GNU General Public License, if you
|
||||||
# distribute this file as part of a program that contains a
|
# distribute this file as part of a program that contains a
|
||||||
|
@ -91,7 +92,20 @@ gcc3)
|
||||||
## gcc 3 implements dependency tracking that does exactly what
|
## gcc 3 implements dependency tracking that does exactly what
|
||||||
## we want. Yay! Note: for some reason libtool 1.4 doesn't like
|
## we want. Yay! Note: for some reason libtool 1.4 doesn't like
|
||||||
## it if -MD -MP comes after the -MF stuff. Hmm.
|
## it if -MD -MP comes after the -MF stuff. Hmm.
|
||||||
"$@" -MT "$object" -MD -MP -MF "$tmpdepfile"
|
## Unfortunately, FreeBSD c89 acceptance of flags depends upon
|
||||||
|
## the command line argument order; so add the flags where they
|
||||||
|
## appear in depend2.am. Note that the slowdown incurred here
|
||||||
|
## affects only configure: in makefiles, %FASTDEP% shortcuts this.
|
||||||
|
for arg
|
||||||
|
do
|
||||||
|
case $arg in
|
||||||
|
-c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;;
|
||||||
|
*) set fnord "$@" "$arg" ;;
|
||||||
|
esac
|
||||||
|
shift # fnord
|
||||||
|
shift # $arg
|
||||||
|
done
|
||||||
|
"$@"
|
||||||
stat=$?
|
stat=$?
|
||||||
if test $stat -eq 0; then :
|
if test $stat -eq 0; then :
|
||||||
else
|
else
|
||||||
|
@ -201,34 +215,39 @@ aix)
|
||||||
# current directory. Also, the AIX compiler puts `$object:' at the
|
# current directory. Also, the AIX compiler puts `$object:' at the
|
||||||
# start of each line; $object doesn't have directory information.
|
# start of each line; $object doesn't have directory information.
|
||||||
# Version 6 uses the directory in both cases.
|
# Version 6 uses the directory in both cases.
|
||||||
stripped=`echo "$object" | sed 's/\(.*\)\..*$/\1/'`
|
dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
|
||||||
tmpdepfile="$stripped.u"
|
test "x$dir" = "x$object" && dir=
|
||||||
|
base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
|
||||||
if test "$libtool" = yes; then
|
if test "$libtool" = yes; then
|
||||||
|
tmpdepfile1=$dir$base.u
|
||||||
|
tmpdepfile2=$base.u
|
||||||
|
tmpdepfile3=$dir.libs/$base.u
|
||||||
"$@" -Wc,-M
|
"$@" -Wc,-M
|
||||||
else
|
else
|
||||||
|
tmpdepfile1=$dir$base.u
|
||||||
|
tmpdepfile2=$dir$base.u
|
||||||
|
tmpdepfile3=$dir$base.u
|
||||||
"$@" -M
|
"$@" -M
|
||||||
fi
|
fi
|
||||||
stat=$?
|
stat=$?
|
||||||
|
|
||||||
if test -f "$tmpdepfile"; then :
|
|
||||||
else
|
|
||||||
stripped=`echo "$stripped" | sed 's,^.*/,,'`
|
|
||||||
tmpdepfile="$stripped.u"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test $stat -eq 0; then :
|
if test $stat -eq 0; then :
|
||||||
else
|
else
|
||||||
rm -f "$tmpdepfile"
|
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||||
exit $stat
|
exit $stat
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||||
|
do
|
||||||
|
test -f "$tmpdepfile" && break
|
||||||
|
done
|
||||||
if test -f "$tmpdepfile"; then
|
if test -f "$tmpdepfile"; then
|
||||||
outname="$stripped.o"
|
|
||||||
# Each line is of the form `foo.o: dependent.h'.
|
# Each line is of the form `foo.o: dependent.h'.
|
||||||
# Do two passes, one to just change these to
|
# Do two passes, one to just change these to
|
||||||
# `$object: dependent.h' and one to simply `dependent.h:'.
|
# `$object: dependent.h' and one to simply `dependent.h:'.
|
||||||
sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile"
|
sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
|
||||||
sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile"
|
# That's a tab and a space in the [].
|
||||||
|
sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
|
||||||
else
|
else
|
||||||
# The sourcefile does not contain any dependencies, so just
|
# The sourcefile does not contain any dependencies, so just
|
||||||
# store a dummy comment line, to avoid errors with the Makefile
|
# store a dummy comment line, to avoid errors with the Makefile
|
||||||
|
@ -276,6 +295,46 @@ icc)
|
||||||
rm -f "$tmpdepfile"
|
rm -f "$tmpdepfile"
|
||||||
;;
|
;;
|
||||||
|
|
||||||
|
hp2)
|
||||||
|
# The "hp" stanza above does not work with aCC (C++) and HP's ia64
|
||||||
|
# compilers, which have integrated preprocessors. The correct option
|
||||||
|
# to use with these is +Maked; it writes dependencies to a file named
|
||||||
|
# 'foo.d', which lands next to the object file, wherever that
|
||||||
|
# happens to be.
|
||||||
|
# Much of this is similar to the tru64 case; see comments there.
|
||||||
|
dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
|
||||||
|
test "x$dir" = "x$object" && dir=
|
||||||
|
base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
|
||||||
|
if test "$libtool" = yes; then
|
||||||
|
tmpdepfile1=$dir$base.d
|
||||||
|
tmpdepfile2=$dir.libs/$base.d
|
||||||
|
"$@" -Wc,+Maked
|
||||||
|
else
|
||||||
|
tmpdepfile1=$dir$base.d
|
||||||
|
tmpdepfile2=$dir$base.d
|
||||||
|
"$@" +Maked
|
||||||
|
fi
|
||||||
|
stat=$?
|
||||||
|
if test $stat -eq 0; then :
|
||||||
|
else
|
||||||
|
rm -f "$tmpdepfile1" "$tmpdepfile2"
|
||||||
|
exit $stat
|
||||||
|
fi
|
||||||
|
|
||||||
|
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2"
|
||||||
|
do
|
||||||
|
test -f "$tmpdepfile" && break
|
||||||
|
done
|
||||||
|
if test -f "$tmpdepfile"; then
|
||||||
|
sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile"
|
||||||
|
# Add `dependent.h:' lines.
|
||||||
|
sed -ne '2,${; s/^ *//; s/ \\*$//; s/$/:/; p;}' "$tmpdepfile" >> "$depfile"
|
||||||
|
else
|
||||||
|
echo "#dummy" > "$depfile"
|
||||||
|
fi
|
||||||
|
rm -f "$tmpdepfile" "$tmpdepfile2"
|
||||||
|
;;
|
||||||
|
|
||||||
tru64)
|
tru64)
|
||||||
# The Tru64 compiler uses -MD to generate dependencies as a side
|
# The Tru64 compiler uses -MD to generate dependencies as a side
|
||||||
# effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'.
|
# effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'.
|
||||||
|
@ -288,13 +347,13 @@ tru64)
|
||||||
|
|
||||||
if test "$libtool" = yes; then
|
if test "$libtool" = yes; then
|
||||||
# With Tru64 cc, shared objects can also be used to make a
|
# With Tru64 cc, shared objects can also be used to make a
|
||||||
# static library. This mecanism is used in libtool 1.4 series to
|
# static library. This mechanism is used in libtool 1.4 series to
|
||||||
# handle both shared and static libraries in a single compilation.
|
# handle both shared and static libraries in a single compilation.
|
||||||
# With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d.
|
# With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d.
|
||||||
#
|
#
|
||||||
# With libtool 1.5 this exception was removed, and libtool now
|
# With libtool 1.5 this exception was removed, and libtool now
|
||||||
# generates 2 separate objects for the 2 libraries. These two
|
# generates 2 separate objects for the 2 libraries. These two
|
||||||
# compilations output dependencies in in $dir.libs/$base.o.d and
|
# compilations output dependencies in $dir.libs/$base.o.d and
|
||||||
# in $dir$base.o.d. We have to check for both files, because
|
# in $dir$base.o.d. We have to check for both files, because
|
||||||
# one of the two compilations can be disabled. We should prefer
|
# one of the two compilations can be disabled. We should prefer
|
||||||
# $dir$base.o.d over $dir.libs/$base.o.d because the latter is
|
# $dir$base.o.d over $dir.libs/$base.o.d because the latter is
|
||||||
|
@ -467,7 +526,8 @@ cpp)
|
||||||
done
|
done
|
||||||
|
|
||||||
"$@" -E |
|
"$@" -E |
|
||||||
sed -n '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' |
|
sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
|
||||||
|
-e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' |
|
||||||
sed '$ s: \\$::' > "$tmpdepfile"
|
sed '$ s: \\$::' > "$tmpdepfile"
|
||||||
rm -f "$depfile"
|
rm -f "$depfile"
|
||||||
echo "$object : \\" > "$depfile"
|
echo "$object : \\" > "$depfile"
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
// **** WAVPACK **** //
|
// **** WAVPACK **** //
|
||||||
// Hybrid Lossless Wavefile Compressor //
|
// Hybrid Lossless Wavefile Compressor //
|
||||||
// Copyright (c) 1998 - 2005 Conifer Software. //
|
// Copyright (c) 1998 - 2006 Conifer Software. //
|
||||||
// All Rights Reserved. //
|
// All Rights Reserved. //
|
||||||
// Distributed under the BSD Software License (see license.txt) //
|
// Distributed under the BSD Software License (see license.txt) //
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@ -10,15 +10,16 @@
|
||||||
|
|
||||||
// This module handles the "extra" mode for mono files.
|
// This module handles the "extra" mode for mono files.
|
||||||
|
|
||||||
#include "wavpack.h"
|
#include "wavpack_local.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
|
//#define USE_OVERHEAD
|
||||||
#define LOG_LIMIT 6912
|
#define LOG_LIMIT 6912
|
||||||
// #define EXTRA_DUMP
|
//#define EXTRA_DUMP
|
||||||
|
|
||||||
#ifdef DEBUG_ALLOC
|
#ifdef DEBUG_ALLOC
|
||||||
#define malloc malloc_db
|
#define malloc malloc_db
|
||||||
|
@ -39,8 +40,6 @@ typedef struct {
|
||||||
uint32_t best_bits;
|
uint32_t best_bits;
|
||||||
} WavpackExtraInfo;
|
} WavpackExtraInfo;
|
||||||
|
|
||||||
extern const signed char default_terms [], high_terms [], fast_terms [];
|
|
||||||
|
|
||||||
static void decorr_mono_pass (int32_t *in_samples, int32_t *out_samples, uint32_t num_samples, struct decorr_pass *dpp, int dir)
|
static void decorr_mono_pass (int32_t *in_samples, int32_t *out_samples, uint32_t num_samples, struct decorr_pass *dpp, int dir)
|
||||||
{
|
{
|
||||||
int m = 0, i;
|
int m = 0, i;
|
||||||
|
@ -48,101 +47,101 @@ static void decorr_mono_pass (int32_t *in_samples, int32_t *out_samples, uint32_
|
||||||
dpp->sum_A = 0;
|
dpp->sum_A = 0;
|
||||||
|
|
||||||
if (dir < 0) {
|
if (dir < 0) {
|
||||||
out_samples += (num_samples - 1);
|
out_samples += (num_samples - 1);
|
||||||
in_samples += (num_samples - 1);
|
in_samples += (num_samples - 1);
|
||||||
dir = -1;
|
dir = -1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
dir = 1;
|
dir = 1;
|
||||||
|
|
||||||
dpp->weight_A = restore_weight (store_weight (dpp->weight_A));
|
dpp->weight_A = restore_weight (store_weight (dpp->weight_A));
|
||||||
|
|
||||||
for (i = 0; i < 8; ++i)
|
for (i = 0; i < 8; ++i)
|
||||||
dpp->samples_A [i] = exp2s (log2s (dpp->samples_A [i]));
|
dpp->samples_A [i] = exp2s (log2s (dpp->samples_A [i]));
|
||||||
|
|
||||||
if (dpp->term > MAX_TERM) {
|
if (dpp->term > MAX_TERM) {
|
||||||
while (num_samples--) {
|
while (num_samples--) {
|
||||||
int32_t left, sam_A;
|
int32_t left, sam_A;
|
||||||
|
|
||||||
if (dpp->term & 1)
|
if (dpp->term & 1)
|
||||||
sam_A = 2 * dpp->samples_A [0] - dpp->samples_A [1];
|
sam_A = 2 * dpp->samples_A [0] - dpp->samples_A [1];
|
||||||
else
|
else
|
||||||
sam_A = (3 * dpp->samples_A [0] - dpp->samples_A [1]) >> 1;
|
sam_A = (3 * dpp->samples_A [0] - dpp->samples_A [1]) >> 1;
|
||||||
|
|
||||||
dpp->samples_A [1] = dpp->samples_A [0];
|
dpp->samples_A [1] = dpp->samples_A [0];
|
||||||
dpp->samples_A [0] = left = in_samples [0];
|
dpp->samples_A [0] = left = in_samples [0];
|
||||||
|
|
||||||
left -= apply_weight (dpp->weight_A, sam_A);
|
left -= apply_weight (dpp->weight_A, sam_A);
|
||||||
update_weight (dpp->weight_A, dpp->delta, sam_A, left);
|
update_weight (dpp->weight_A, dpp->delta, sam_A, left);
|
||||||
dpp->sum_A += dpp->weight_A;
|
dpp->sum_A += dpp->weight_A;
|
||||||
out_samples [0] = left;
|
out_samples [0] = left;
|
||||||
in_samples += dir;
|
in_samples += dir;
|
||||||
out_samples += dir;
|
out_samples += dir;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (dpp->term > 0) {
|
else if (dpp->term > 0) {
|
||||||
while (num_samples--) {
|
while (num_samples--) {
|
||||||
int k = (m + dpp->term) & (MAX_TERM - 1);
|
int k = (m + dpp->term) & (MAX_TERM - 1);
|
||||||
int32_t left, sam_A;
|
int32_t left, sam_A;
|
||||||
|
|
||||||
sam_A = dpp->samples_A [m];
|
sam_A = dpp->samples_A [m];
|
||||||
dpp->samples_A [k] = left = in_samples [0];
|
dpp->samples_A [k] = left = in_samples [0];
|
||||||
m = (m + 1) & (MAX_TERM - 1);
|
m = (m + 1) & (MAX_TERM - 1);
|
||||||
|
|
||||||
left -= apply_weight (dpp->weight_A, sam_A);
|
left -= apply_weight (dpp->weight_A, sam_A);
|
||||||
update_weight (dpp->weight_A, dpp->delta, sam_A, left);
|
update_weight (dpp->weight_A, dpp->delta, sam_A, left);
|
||||||
dpp->sum_A += dpp->weight_A;
|
dpp->sum_A += dpp->weight_A;
|
||||||
out_samples [0] = left;
|
out_samples [0] = left;
|
||||||
in_samples += dir;
|
in_samples += dir;
|
||||||
out_samples += dir;
|
out_samples += dir;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m && dpp->term > 0 && dpp->term <= MAX_TERM) {
|
if (m && dpp->term > 0 && dpp->term <= MAX_TERM) {
|
||||||
int32_t temp_A [MAX_TERM];
|
int32_t temp_A [MAX_TERM];
|
||||||
int k;
|
int k;
|
||||||
|
|
||||||
memcpy (temp_A, dpp->samples_A, sizeof (dpp->samples_A));
|
memcpy (temp_A, dpp->samples_A, sizeof (dpp->samples_A));
|
||||||
|
|
||||||
for (k = 0; k < MAX_TERM; k++) {
|
for (k = 0; k < MAX_TERM; k++) {
|
||||||
dpp->samples_A [k] = temp_A [m];
|
dpp->samples_A [k] = temp_A [m];
|
||||||
m = (m + 1) & (MAX_TERM - 1);
|
m = (m + 1) & (MAX_TERM - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void reverse_mono_decorr (struct decorr_pass *dpp)
|
static void reverse_mono_decorr (struct decorr_pass *dpp)
|
||||||
{
|
{
|
||||||
if (dpp->term > MAX_TERM) {
|
if (dpp->term > MAX_TERM) {
|
||||||
int32_t sam_A;
|
int32_t sam_A;
|
||||||
|
|
||||||
if (dpp->term & 1)
|
if (dpp->term & 1)
|
||||||
sam_A = 2 * dpp->samples_A [0] - dpp->samples_A [1];
|
sam_A = 2 * dpp->samples_A [0] - dpp->samples_A [1];
|
||||||
else
|
else
|
||||||
sam_A = (3 * dpp->samples_A [0] - dpp->samples_A [1]) >> 1;
|
sam_A = (3 * dpp->samples_A [0] - dpp->samples_A [1]) >> 1;
|
||||||
|
|
||||||
dpp->samples_A [1] = dpp->samples_A [0];
|
dpp->samples_A [1] = dpp->samples_A [0];
|
||||||
dpp->samples_A [0] = sam_A;
|
dpp->samples_A [0] = sam_A;
|
||||||
|
|
||||||
if (dpp->term & 1)
|
if (dpp->term & 1)
|
||||||
sam_A = 2 * dpp->samples_A [0] - dpp->samples_A [1];
|
sam_A = 2 * dpp->samples_A [0] - dpp->samples_A [1];
|
||||||
else
|
else
|
||||||
sam_A = (3 * dpp->samples_A [0] - dpp->samples_A [1]) >> 1;
|
sam_A = (3 * dpp->samples_A [0] - dpp->samples_A [1]) >> 1;
|
||||||
|
|
||||||
dpp->samples_A [1] = sam_A;
|
dpp->samples_A [1] = sam_A;
|
||||||
}
|
}
|
||||||
else if (dpp->term > 1) {
|
else if (dpp->term > 1) {
|
||||||
int i = 0, j = dpp->term - 1, cnt = dpp->term / 2;
|
int i = 0, j = dpp->term - 1, cnt = dpp->term / 2;
|
||||||
|
|
||||||
while (cnt--) {
|
while (cnt--) {
|
||||||
i &= (MAX_TERM - 1);
|
i &= (MAX_TERM - 1);
|
||||||
j &= (MAX_TERM - 1);
|
j &= (MAX_TERM - 1);
|
||||||
dpp->samples_A [i] ^= dpp->samples_A [j];
|
dpp->samples_A [i] ^= dpp->samples_A [j];
|
||||||
dpp->samples_A [j] ^= dpp->samples_A [i];
|
dpp->samples_A [j] ^= dpp->samples_A [i];
|
||||||
dpp->samples_A [i++] ^= dpp->samples_A [j--];
|
dpp->samples_A [i++] ^= dpp->samples_A [j--];
|
||||||
}
|
}
|
||||||
|
|
||||||
// CLEAR (dpp->samples_A);
|
// CLEAR (dpp->samples_A);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,11 +151,11 @@ static void decorr_mono_buffer (int32_t *samples, int32_t *outsamples, uint32_t
|
||||||
int delta = dppi->delta, pre_delta, term = dppi->term;
|
int delta = dppi->delta, pre_delta, term = dppi->term;
|
||||||
|
|
||||||
if (delta == 7)
|
if (delta == 7)
|
||||||
pre_delta = 7;
|
pre_delta = 7;
|
||||||
else if (delta < 2)
|
else if (delta < 2)
|
||||||
pre_delta = 3;
|
pre_delta = 3;
|
||||||
else
|
else
|
||||||
pre_delta = delta + 1;
|
pre_delta = delta + 1;
|
||||||
|
|
||||||
CLEAR (dp);
|
CLEAR (dp);
|
||||||
dp.term = term;
|
dp.term = term;
|
||||||
|
@ -167,25 +166,37 @@ static void decorr_mono_buffer (int32_t *samples, int32_t *outsamples, uint32_t
|
||||||
if (tindex == 0)
|
if (tindex == 0)
|
||||||
reverse_mono_decorr (&dp);
|
reverse_mono_decorr (&dp);
|
||||||
else
|
else
|
||||||
CLEAR (dp.samples_A);
|
CLEAR (dp.samples_A);
|
||||||
|
|
||||||
memcpy (dppi->samples_A, dp.samples_A, sizeof (dp.samples_A));
|
memcpy (dppi->samples_A, dp.samples_A, sizeof (dp.samples_A));
|
||||||
dppi->weight_A = dp.weight_A;
|
dppi->weight_A = dp.weight_A;
|
||||||
|
|
||||||
if (delta == 0) {
|
if (delta == 0) {
|
||||||
dp.delta = 1;
|
dp.delta = 1;
|
||||||
decorr_mono_pass (samples, outsamples, num_samples, &dp, 1);
|
decorr_mono_pass (samples, outsamples, num_samples, &dp, 1);
|
||||||
dp.delta = 0;
|
dp.delta = 0;
|
||||||
memcpy (dp.samples_A, dppi->samples_A, sizeof (dp.samples_A));
|
memcpy (dp.samples_A, dppi->samples_A, sizeof (dp.samples_A));
|
||||||
dppi->weight_A = dp.weight_A = dp.sum_A / num_samples;
|
dppi->weight_A = dp.weight_A = dp.sum_A / num_samples;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (memcmp (dppi, &dp, sizeof (dp)))
|
// if (memcmp (dppi, &dp, sizeof (dp)))
|
||||||
// error_line ("decorr_passes don't match, delta = %d", delta);
|
// error_line ("decorr_passes don't match, delta = %d", delta);
|
||||||
|
|
||||||
decorr_mono_pass (samples, outsamples, num_samples, &dp, 1);
|
decorr_mono_pass (samples, outsamples, num_samples, &dp, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int log2overhead (int first_term, int num_terms)
|
||||||
|
{
|
||||||
|
#ifdef USE_OVERHEAD
|
||||||
|
if (first_term > MAX_TERM)
|
||||||
|
return (4 + num_terms * 2) << 11;
|
||||||
|
else
|
||||||
|
return (2 + num_terms * 2) << 11;
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static void recurse_mono (WavpackContext *wpc, WavpackExtraInfo *info, int depth, int delta, uint32_t input_bits)
|
static void recurse_mono (WavpackContext *wpc, WavpackExtraInfo *info, int depth, int delta, uint32_t input_bits)
|
||||||
{
|
{
|
||||||
WavpackStream *wps = wpc->streams [wpc->current_stream];
|
WavpackStream *wps = wpc->streams [wpc->current_stream];
|
||||||
|
@ -194,60 +205,64 @@ static void recurse_mono (WavpackContext *wpc, WavpackExtraInfo *info, int depth
|
||||||
uint32_t term_bits [22], bits;
|
uint32_t term_bits [22], bits;
|
||||||
|
|
||||||
if (branches < 1 || depth + 1 == info->nterms)
|
if (branches < 1 || depth + 1 == info->nterms)
|
||||||
branches = 1;
|
branches = 1;
|
||||||
|
|
||||||
CLEAR (term_bits);
|
CLEAR (term_bits);
|
||||||
samples = info->sampleptrs [depth];
|
samples = info->sampleptrs [depth];
|
||||||
outsamples = info->sampleptrs [depth + 1];
|
outsamples = info->sampleptrs [depth + 1];
|
||||||
|
|
||||||
for (term = 1; term <= 18; ++term) {
|
for (term = 1; term <= 18; ++term) {
|
||||||
if (term == 17 && branches == 1 && depth + 1 < info->nterms)
|
if (term == 17 && branches == 1 && depth + 1 < info->nterms)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (term >= 9 && term <= 16)
|
if (term > 8 && term < 17)
|
||||||
if (term > MAX_TERM || !(wpc->config.flags & CONFIG_HIGH_FLAG) || (wpc->config.extra_flags & EXTRA_SKIP_8TO16))
|
continue;
|
||||||
continue;
|
|
||||||
|
|
||||||
if ((wpc->config.flags & CONFIG_FAST_FLAG) && (term >= 5 && term <= 16))
|
if ((wpc->config.flags & CONFIG_FAST_FLAG) && (term > 4 && term < 17))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
info->dps [depth].term = term;
|
info->dps [depth].term = term;
|
||||||
info->dps [depth].delta = delta;
|
info->dps [depth].delta = delta;
|
||||||
decorr_mono_buffer (samples, outsamples, wps->wphdr.block_samples, info->dps, depth);
|
decorr_mono_buffer (samples, outsamples, wps->wphdr.block_samples, info->dps, depth);
|
||||||
bits = log2buffer (outsamples, wps->wphdr.block_samples, info->log_limit);
|
bits = log2buffer (outsamples, wps->wphdr.block_samples, info->log_limit);
|
||||||
|
|
||||||
if (bits < info->best_bits) {
|
if (bits != (uint32_t) -1)
|
||||||
info->best_bits = bits;
|
bits += log2overhead (info->dps [0].term, depth + 1);
|
||||||
CLEAR (wps->decorr_passes);
|
|
||||||
memcpy (wps->decorr_passes, info->dps, sizeof (info->dps [0]) * (depth + 1));
|
|
||||||
memcpy (info->sampleptrs [info->nterms + 1], info->sampleptrs [depth + 1], wps->wphdr.block_samples * 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
term_bits [term + 3] = bits;
|
if (bits < info->best_bits) {
|
||||||
|
info->best_bits = bits;
|
||||||
|
CLEAR (wps->decorr_passes);
|
||||||
|
memcpy (wps->decorr_passes, info->dps, sizeof (info->dps [0]) * (depth + 1));
|
||||||
|
memcpy (info->sampleptrs [info->nterms + 1], info->sampleptrs [depth + 1], wps->wphdr.block_samples * 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
term_bits [term + 3] = bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (depth + 1 < info->nterms && branches--) {
|
while (depth + 1 < info->nterms && branches--) {
|
||||||
uint32_t local_best_bits = input_bits;
|
uint32_t local_best_bits = input_bits;
|
||||||
int best_term = 0, i;
|
int best_term = 0, i;
|
||||||
|
|
||||||
for (i = 0; i < 22; ++i)
|
for (i = 0; i < 22; ++i)
|
||||||
if (term_bits [i] && term_bits [i] < local_best_bits) {
|
if (term_bits [i] && term_bits [i] < local_best_bits) {
|
||||||
local_best_bits = term_bits [i];
|
local_best_bits = term_bits [i];
|
||||||
term_bits [i] = 0;
|
// term_bits [i] = 0;
|
||||||
best_term = i - 3;
|
best_term = i - 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!best_term)
|
if (!best_term)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
info->dps [depth].term = best_term;
|
term_bits [best_term + 3] = 0;
|
||||||
info->dps [depth].delta = delta;
|
|
||||||
decorr_mono_buffer (samples, outsamples, wps->wphdr.block_samples, info->dps, depth);
|
|
||||||
|
|
||||||
// if (log2buffer (outsamples, wps->wphdr.block_samples * 2, 0) != local_best_bits)
|
info->dps [depth].term = best_term;
|
||||||
// error_line ("data doesn't match!");
|
info->dps [depth].delta = delta;
|
||||||
|
decorr_mono_buffer (samples, outsamples, wps->wphdr.block_samples, info->dps, depth);
|
||||||
|
|
||||||
recurse_mono (wpc, info, depth + 1, delta, local_best_bits);
|
// if (log2buffer (outsamples, wps->wphdr.block_samples * 2, 0) != local_best_bits)
|
||||||
|
// error_line ("data doesn't match!");
|
||||||
|
|
||||||
|
recurse_mono (wpc, info, depth + 1, delta, local_best_bits);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -258,54 +273,60 @@ static void delta_mono (WavpackContext *wpc, WavpackExtraInfo *info)
|
||||||
uint32_t bits;
|
uint32_t bits;
|
||||||
|
|
||||||
if (wps->decorr_passes [0].term)
|
if (wps->decorr_passes [0].term)
|
||||||
delta = wps->decorr_passes [0].delta;
|
delta = wps->decorr_passes [0].delta;
|
||||||
else
|
else
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (d = delta - 1; d >= 0; --d) {
|
for (d = delta - 1; d >= 0; --d) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (!d && (wps->wphdr.flags & HYBRID_FLAG))
|
if (!d && (wps->wphdr.flags & HYBRID_FLAG))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
for (i = 0; i < info->nterms && wps->decorr_passes [i].term; ++i) {
|
for (i = 0; i < info->nterms && wps->decorr_passes [i].term; ++i) {
|
||||||
info->dps [i].term = wps->decorr_passes [i].term;
|
info->dps [i].term = wps->decorr_passes [i].term;
|
||||||
info->dps [i].delta = d;
|
info->dps [i].delta = d;
|
||||||
decorr_mono_buffer (info->sampleptrs [i], info->sampleptrs [i+1], wps->wphdr.block_samples, info->dps, i);
|
decorr_mono_buffer (info->sampleptrs [i], info->sampleptrs [i+1], wps->wphdr.block_samples, info->dps, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
bits = log2buffer (info->sampleptrs [i], wps->wphdr.block_samples, info->log_limit);
|
bits = log2buffer (info->sampleptrs [i], wps->wphdr.block_samples, info->log_limit);
|
||||||
|
|
||||||
if (bits < info->best_bits) {
|
if (bits != (uint32_t) -1)
|
||||||
lower = TRUE;
|
bits += log2overhead (wps->decorr_passes [0].term, i);
|
||||||
info->best_bits = bits;
|
|
||||||
CLEAR (wps->decorr_passes);
|
if (bits < info->best_bits) {
|
||||||
memcpy (wps->decorr_passes, info->dps, sizeof (info->dps [0]) * i);
|
lower = TRUE;
|
||||||
memcpy (info->sampleptrs [info->nterms + 1], info->sampleptrs [i], wps->wphdr.block_samples * 4);
|
info->best_bits = bits;
|
||||||
}
|
CLEAR (wps->decorr_passes);
|
||||||
else
|
memcpy (wps->decorr_passes, info->dps, sizeof (info->dps [0]) * i);
|
||||||
break;
|
memcpy (info->sampleptrs [info->nterms + 1], info->sampleptrs [i], wps->wphdr.block_samples * 4);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (d = delta + 1; !lower && d <= 7; ++d) {
|
for (d = delta + 1; !lower && d <= 7; ++d) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < info->nterms && wps->decorr_passes [i].term; ++i) {
|
for (i = 0; i < info->nterms && wps->decorr_passes [i].term; ++i) {
|
||||||
info->dps [i].term = wps->decorr_passes [i].term;
|
info->dps [i].term = wps->decorr_passes [i].term;
|
||||||
info->dps [i].delta = d;
|
info->dps [i].delta = d;
|
||||||
decorr_mono_buffer (info->sampleptrs [i], info->sampleptrs [i+1], wps->wphdr.block_samples, info->dps, i);
|
decorr_mono_buffer (info->sampleptrs [i], info->sampleptrs [i+1], wps->wphdr.block_samples, info->dps, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
bits = log2buffer (info->sampleptrs [i], wps->wphdr.block_samples, info->log_limit);
|
bits = log2buffer (info->sampleptrs [i], wps->wphdr.block_samples, info->log_limit);
|
||||||
|
|
||||||
if (bits < info->best_bits) {
|
if (bits != (uint32_t) -1)
|
||||||
info->best_bits = bits;
|
bits += log2overhead (wps->decorr_passes [0].term, i);
|
||||||
CLEAR (wps->decorr_passes);
|
|
||||||
memcpy (wps->decorr_passes, info->dps, sizeof (info->dps [0]) * i);
|
if (bits < info->best_bits) {
|
||||||
memcpy (info->sampleptrs [info->nterms + 1], info->sampleptrs [i], wps->wphdr.block_samples * 4);
|
info->best_bits = bits;
|
||||||
}
|
CLEAR (wps->decorr_passes);
|
||||||
else
|
memcpy (wps->decorr_passes, info->dps, sizeof (info->dps [0]) * i);
|
||||||
break;
|
memcpy (info->sampleptrs [info->nterms + 1], info->sampleptrs [i], wps->wphdr.block_samples * 4);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -316,244 +337,335 @@ static void sort_mono (WavpackContext *wpc, WavpackExtraInfo *info)
|
||||||
uint32_t bits;
|
uint32_t bits;
|
||||||
|
|
||||||
while (reversed) {
|
while (reversed) {
|
||||||
int ri, i;
|
int ri, i;
|
||||||
|
|
||||||
memcpy (info->dps, wps->decorr_passes, sizeof (wps->decorr_passes));
|
memcpy (info->dps, wps->decorr_passes, sizeof (wps->decorr_passes));
|
||||||
reversed = FALSE;
|
reversed = FALSE;
|
||||||
|
|
||||||
for (ri = 0; ri < info->nterms && wps->decorr_passes [ri].term; ++ri) {
|
for (ri = 0; ri < info->nterms && wps->decorr_passes [ri].term; ++ri) {
|
||||||
|
|
||||||
if (ri + 1 >= info->nterms || !wps->decorr_passes [ri+1].term)
|
if (ri + 1 >= info->nterms || !wps->decorr_passes [ri+1].term)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (wps->decorr_passes [ri].term == wps->decorr_passes [ri+1].term) {
|
if (wps->decorr_passes [ri].term == wps->decorr_passes [ri+1].term) {
|
||||||
decorr_mono_buffer (info->sampleptrs [ri], info->sampleptrs [ri+1], wps->wphdr.block_samples, info->dps, ri);
|
decorr_mono_buffer (info->sampleptrs [ri], info->sampleptrs [ri+1], wps->wphdr.block_samples, info->dps, ri);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
info->dps [ri] = wps->decorr_passes [ri+1];
|
info->dps [ri] = wps->decorr_passes [ri+1];
|
||||||
info->dps [ri+1] = wps->decorr_passes [ri];
|
info->dps [ri+1] = wps->decorr_passes [ri];
|
||||||
|
|
||||||
for (i = ri; i < info->nterms && wps->decorr_passes [i].term; ++i)
|
for (i = ri; i < info->nterms && wps->decorr_passes [i].term; ++i)
|
||||||
decorr_mono_buffer (info->sampleptrs [i], info->sampleptrs [i+1], wps->wphdr.block_samples, info->dps, i);
|
decorr_mono_buffer (info->sampleptrs [i], info->sampleptrs [i+1], wps->wphdr.block_samples, info->dps, i);
|
||||||
|
|
||||||
bits = log2buffer (info->sampleptrs [i], wps->wphdr.block_samples, info->log_limit);
|
bits = log2buffer (info->sampleptrs [i], wps->wphdr.block_samples, info->log_limit);
|
||||||
|
|
||||||
if (bits < info->best_bits) {
|
if (bits != (uint32_t) -1)
|
||||||
reversed = TRUE;
|
bits += log2overhead (wps->decorr_passes [0].term, i);
|
||||||
info->best_bits = bits;
|
|
||||||
CLEAR (wps->decorr_passes);
|
if (bits < info->best_bits) {
|
||||||
memcpy (wps->decorr_passes, info->dps, sizeof (info->dps [0]) * i);
|
reversed = TRUE;
|
||||||
memcpy (info->sampleptrs [info->nterms + 1], info->sampleptrs [i], wps->wphdr.block_samples * 4);
|
info->best_bits = bits;
|
||||||
}
|
CLEAR (wps->decorr_passes);
|
||||||
else {
|
memcpy (wps->decorr_passes, info->dps, sizeof (info->dps [0]) * i);
|
||||||
info->dps [ri] = wps->decorr_passes [ri];
|
memcpy (info->sampleptrs [info->nterms + 1], info->sampleptrs [i], wps->wphdr.block_samples * 4);
|
||||||
info->dps [ri+1] = wps->decorr_passes [ri+1];
|
}
|
||||||
decorr_mono_buffer (info->sampleptrs [ri], info->sampleptrs [ri+1], wps->wphdr.block_samples, info->dps, ri);
|
else {
|
||||||
}
|
info->dps [ri] = wps->decorr_passes [ri];
|
||||||
}
|
info->dps [ri+1] = wps->decorr_passes [ri+1];
|
||||||
|
decorr_mono_buffer (info->sampleptrs [ri], info->sampleptrs [ri+1], wps->wphdr.block_samples, info->dps, ri);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define EXTRA_ADVANCED (EXTRA_BRANCHES | EXTRA_SORT_FIRST | EXTRA_SORT_LAST | EXTRA_TRY_DELTAS)
|
static const uint32_t xtable [] = { 91, 123, 187, 251 };
|
||||||
|
|
||||||
//extern uint32_t crc3;
|
static void analyze_mono (WavpackContext *wpc, int32_t *samples, int do_samples)
|
||||||
|
|
||||||
void analyze_mono (WavpackContext *wpc, int32_t *samples)
|
|
||||||
{
|
{
|
||||||
WavpackStream *wps = wpc->streams [wpc->current_stream];
|
WavpackStream *wps = wpc->streams [wpc->current_stream];
|
||||||
#ifdef EXTRA_DUMP
|
|
||||||
uint32_t bits, default_bits, cnt;
|
|
||||||
#else
|
|
||||||
uint32_t bits, cnt;
|
|
||||||
#endif
|
|
||||||
const signed char *decorr_terms = default_terms, *tp;
|
|
||||||
WavpackExtraInfo info;
|
WavpackExtraInfo info;
|
||||||
int32_t *lptr;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
#ifdef LOG_LIMIT
|
#ifdef LOG_LIMIT
|
||||||
info.log_limit = (((wps->wphdr.flags & MAG_MASK) >> MAG_LSB) + 4) * 256;
|
info.log_limit = (((wps->wphdr.flags & MAG_MASK) >> MAG_LSB) + 4) * 256;
|
||||||
|
|
||||||
if (info.log_limit > LOG_LIMIT)
|
if (info.log_limit > LOG_LIMIT)
|
||||||
info.log_limit = LOG_LIMIT;
|
info.log_limit = LOG_LIMIT;
|
||||||
#else
|
#else
|
||||||
info.log_limit = 0;
|
info.log_limit = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
CLEAR (wps->decorr_passes);
|
if (wpc->config.flags & (CONFIG_HIGH_FLAG | CONFIG_VERY_HIGH_FLAG))
|
||||||
cnt = wps->wphdr.block_samples;
|
wpc->config.extra_flags = xtable [wpc->config.xmode - 4];
|
||||||
lptr = samples;
|
else
|
||||||
|
wpc->config.extra_flags = xtable [wpc->config.xmode - 3];
|
||||||
|
|
||||||
while (cnt--)
|
info.nterms = wps->num_terms;
|
||||||
if (*lptr++)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (cnt == (uint32_t) -1) {
|
|
||||||
scan_word (wps, samples, wps->wphdr.block_samples, -1);
|
|
||||||
wps->num_terms = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wpc->config.flags & CONFIG_HIGH_FLAG)
|
|
||||||
decorr_terms = high_terms;
|
|
||||||
else if (wpc->config.flags & CONFIG_FAST_FLAG)
|
|
||||||
decorr_terms = fast_terms;
|
|
||||||
|
|
||||||
for (info.nterms = 0, tp = decorr_terms; *tp; tp++)
|
|
||||||
if (*tp > 0)
|
|
||||||
++info.nterms;
|
|
||||||
|
|
||||||
if (wpc->config.extra_flags & EXTRA_TERMS)
|
|
||||||
if ((info.nterms += (wpc->config.extra_flags & EXTRA_TERMS) >> 10) > MAX_NTERMS)
|
|
||||||
info.nterms = MAX_NTERMS;
|
|
||||||
|
|
||||||
for (i = 0; i < info.nterms + 2; ++i)
|
for (i = 0; i < info.nterms + 2; ++i)
|
||||||
info.sampleptrs [i] = malloc (wps->wphdr.block_samples * 4);
|
info.sampleptrs [i] = malloc (wps->wphdr.block_samples * 4);
|
||||||
|
|
||||||
memcpy (info.sampleptrs [info.nterms + 1], samples, wps->wphdr.block_samples * 4);
|
memcpy (info.dps, wps->decorr_passes, sizeof (info.dps));
|
||||||
info.best_bits = log2buffer (info.sampleptrs [info.nterms + 1], wps->wphdr.block_samples, 0);
|
|
||||||
memcpy (info.sampleptrs [0], samples, wps->wphdr.block_samples * 4);
|
memcpy (info.sampleptrs [0], samples, wps->wphdr.block_samples * 4);
|
||||||
CLEAR (info.dps);
|
|
||||||
|
|
||||||
for (tp = decorr_terms, i = 0; *tp; tp++)
|
for (i = 0; i < info.nterms && info.dps [i].term; ++i)
|
||||||
if (*tp > 0) {
|
decorr_mono_pass (info.sampleptrs [i], info.sampleptrs [i + 1], wps->wphdr.block_samples, info.dps + i, 1);
|
||||||
info.dps [i].term = *tp;
|
|
||||||
info.dps [i].delta = 2;
|
|
||||||
decorr_mono_buffer (info.sampleptrs [i], info.sampleptrs [i+1], wps->wphdr.block_samples, info.dps, i);
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef EXTRA_DUMP
|
info.best_bits = log2buffer (info.sampleptrs [info.nterms], wps->wphdr.block_samples, 0) * 1;
|
||||||
default_bits = bits = log2buffer (info.sampleptrs [i], wps->wphdr.block_samples, 0);
|
info.best_bits += log2overhead (info.dps [0].term, i);
|
||||||
#else
|
memcpy (info.sampleptrs [info.nterms + 1], info.sampleptrs [i], wps->wphdr.block_samples * 4);
|
||||||
bits = log2buffer (info.sampleptrs [i], wps->wphdr.block_samples, 0);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (bits < info.best_bits) {
|
|
||||||
info.best_bits = bits;
|
|
||||||
CLEAR (wps->decorr_passes);
|
|
||||||
memcpy (wps->decorr_passes, info.dps, sizeof (info.dps [0]) * i);
|
|
||||||
memcpy (info.sampleptrs [info.nterms + 1], info.sampleptrs [i], wps->wphdr.block_samples * 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((wps->wphdr.flags & HYBRID_FLAG) && (wpc->config.extra_flags & EXTRA_ADVANCED)) {
|
|
||||||
int shaping_weight, new = wps->wphdr.flags & NEW_SHAPING;
|
|
||||||
int32_t *rptr = info.sampleptrs [info.nterms + 1], error = 0, temp;
|
|
||||||
|
|
||||||
scan_word (wps, rptr, wps->wphdr.block_samples, -1);
|
|
||||||
cnt = wps->wphdr.block_samples;
|
|
||||||
lptr = info.sampleptrs [0];
|
|
||||||
|
|
||||||
if (wps->wphdr.flags & HYBRID_SHAPE) {
|
|
||||||
while (cnt--) {
|
|
||||||
shaping_weight = (wps->dc.shaping_acc [0] += wps->dc.shaping_delta [0]) >> 16;
|
|
||||||
temp = -apply_weight (shaping_weight, error);
|
|
||||||
|
|
||||||
if (new && shaping_weight < 0 && temp) {
|
|
||||||
if (temp == error)
|
|
||||||
temp = (temp < 0) ? temp + 1 : temp - 1;
|
|
||||||
|
|
||||||
lptr [0] += (error = nosend_word (wps, rptr [0], 0) - rptr [0] + temp);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
lptr [0] += (error = nosend_word (wps, rptr [0], 0) - rptr [0]) + temp;
|
|
||||||
|
|
||||||
lptr++;
|
|
||||||
rptr++;
|
|
||||||
}
|
|
||||||
|
|
||||||
wps->dc.shaping_acc [0] -= wps->dc.shaping_delta [0] * wps->wphdr.block_samples;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
while (cnt--) {
|
|
||||||
lptr [0] += nosend_word (wps, rptr [0], 0) - rptr [0];
|
|
||||||
lptr++;
|
|
||||||
rptr++;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy (info.dps, wps->decorr_passes, sizeof (info.dps));
|
|
||||||
|
|
||||||
for (i = 0; i < info.nterms && info.dps [i].term; ++i)
|
|
||||||
decorr_mono_buffer (info.sampleptrs [i], info.sampleptrs [i + 1], wps->wphdr.block_samples, info.dps, i);
|
|
||||||
|
|
||||||
#ifdef EXTRA_DUMP
|
|
||||||
info.best_bits = default_bits = log2buffer (info.sampleptrs [i], wps->wphdr.block_samples, 0);
|
|
||||||
#else
|
|
||||||
info.best_bits = log2buffer (info.sampleptrs [i], wps->wphdr.block_samples, 0);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
CLEAR (wps->decorr_passes);
|
|
||||||
memcpy (wps->decorr_passes, info.dps, sizeof (info.dps [0]) * i);
|
|
||||||
memcpy (info.sampleptrs [info.nterms + 1], info.sampleptrs [i], wps->wphdr.block_samples * 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wpc->config.extra_flags & EXTRA_BRANCHES)
|
if (wpc->config.extra_flags & EXTRA_BRANCHES)
|
||||||
recurse_mono (wpc, &info, 0, (int) floor (wps->delta_decay + 0.5),
|
recurse_mono (wpc, &info, 0, (int) floor (wps->delta_decay + 0.5),
|
||||||
log2buffer (info.sampleptrs [0], wps->wphdr.block_samples, 0));
|
log2buffer (info.sampleptrs [0], wps->wphdr.block_samples, 0));
|
||||||
|
|
||||||
if (wpc->config.extra_flags & EXTRA_SORT_FIRST)
|
if (wpc->config.extra_flags & EXTRA_SORT_FIRST)
|
||||||
sort_mono (wpc, &info);
|
sort_mono (wpc, &info);
|
||||||
|
|
||||||
if (wpc->config.extra_flags & EXTRA_TRY_DELTAS) {
|
if (wpc->config.extra_flags & EXTRA_TRY_DELTAS) {
|
||||||
delta_mono (wpc, &info);
|
delta_mono (wpc, &info);
|
||||||
|
|
||||||
if ((wpc->config.extra_flags & EXTRA_ADJUST_DELTAS) && wps->decorr_passes [0].term)
|
if ((wpc->config.extra_flags & EXTRA_ADJUST_DELTAS) && wps->decorr_passes [0].term)
|
||||||
wps->delta_decay = (wps->delta_decay * 2.0 + wps->decorr_passes [0].delta) / 3.0;
|
wps->delta_decay = (float)((wps->delta_decay * 2.0 + wps->decorr_passes [0].delta) / 3.0);
|
||||||
else
|
else
|
||||||
wps->delta_decay = 2.0;
|
wps->delta_decay = 2.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wpc->config.extra_flags & EXTRA_SORT_LAST)
|
if (wpc->config.extra_flags & EXTRA_SORT_LAST)
|
||||||
sort_mono (wpc, &info);
|
sort_mono (wpc, &info);
|
||||||
|
|
||||||
#if 0
|
if (do_samples)
|
||||||
memcpy (info.dps, wps->decorr_passes, sizeof (info.dps));
|
memcpy (samples, info.sampleptrs [info.nterms + 1], wps->wphdr.block_samples * 4);
|
||||||
|
|
||||||
for (i = 0; i < info.nterms && info.dps [i].term; ++i)
|
|
||||||
decorr_mono_pass (info.sampleptrs [i], info.sampleptrs [i + 1], wps->wphdr.block_samples, info.dps + i, 1);
|
|
||||||
|
|
||||||
if (log2buffer (info.sampleptrs [i], wps->wphdr.block_samples, 0) != info.best_bits)
|
|
||||||
error_line ("(1) samples do not match!");
|
|
||||||
|
|
||||||
if (log2buffer (info.sampleptrs [info.nterms + 1], wps->wphdr.block_samples, 0) != info.best_bits)
|
|
||||||
error_line ("(2) samples do not match!");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
scan_word (wps, info.sampleptrs [info.nterms + 1], wps->wphdr.block_samples, -1);
|
|
||||||
|
|
||||||
#ifdef EXTRA_DUMP
|
|
||||||
if (1) {
|
|
||||||
char string [256], substring [20];
|
|
||||||
int i;
|
|
||||||
|
|
||||||
sprintf (string, "M: delta = %.4f%%, terms =",
|
|
||||||
((double) info.best_bits - default_bits) / 256.0 / wps->wphdr.block_samples / 32.0 * 100.0);
|
|
||||||
|
|
||||||
for (i = 0; i < info.nterms; ++i) {
|
|
||||||
if (wps->decorr_passes [i].term) {
|
|
||||||
if (i && wps->decorr_passes [i-1].delta == wps->decorr_passes [i].delta)
|
|
||||||
sprintf (substring, " %d", wps->decorr_passes [i].term);
|
|
||||||
else
|
|
||||||
sprintf (substring, " %d->%d", wps->decorr_passes [i].term,
|
|
||||||
wps->decorr_passes [i].delta);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
sprintf (substring, " *");
|
|
||||||
|
|
||||||
strcat (string, substring);
|
|
||||||
}
|
|
||||||
|
|
||||||
error_line (string);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for (i = 0; i < info.nterms; ++i)
|
for (i = 0; i < info.nterms; ++i)
|
||||||
if (!wps->decorr_passes [i].term)
|
if (!wps->decorr_passes [i].term)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
wps->num_terms = i;
|
wps->num_terms = i;
|
||||||
|
|
||||||
for (i = 0; i < info.nterms + 2; ++i)
|
for (i = 0; i < info.nterms + 2; ++i)
|
||||||
free (info.sampleptrs [i]);
|
free (info.sampleptrs [i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void mono_add_noise (WavpackStream *wps, int32_t *lptr, int32_t *rptr)
|
||||||
|
{
|
||||||
|
int shaping_weight, new = wps->wphdr.flags & NEW_SHAPING;
|
||||||
|
short *shaping_array = wps->dc.shaping_array;
|
||||||
|
int32_t error = 0, temp, cnt;
|
||||||
|
|
||||||
|
scan_word (wps, rptr, wps->wphdr.block_samples, -1);
|
||||||
|
cnt = wps->wphdr.block_samples;
|
||||||
|
|
||||||
|
if (wps->wphdr.flags & HYBRID_SHAPE) {
|
||||||
|
while (cnt--) {
|
||||||
|
if (shaping_array)
|
||||||
|
shaping_weight = *shaping_array++;
|
||||||
|
else
|
||||||
|
shaping_weight = (wps->dc.shaping_acc [0] += wps->dc.shaping_delta [0]) >> 16;
|
||||||
|
|
||||||
|
temp = -apply_weight (shaping_weight, error);
|
||||||
|
|
||||||
|
if (new && shaping_weight < 0 && temp) {
|
||||||
|
if (temp == error)
|
||||||
|
temp = (temp < 0) ? temp + 1 : temp - 1;
|
||||||
|
|
||||||
|
lptr [0] += (error = nosend_word (wps, rptr [0], 0) - rptr [0] + temp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
lptr [0] += (error = nosend_word (wps, rptr [0], 0) - rptr [0]) + temp;
|
||||||
|
|
||||||
|
lptr++;
|
||||||
|
rptr++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!shaping_array)
|
||||||
|
wps->dc.shaping_acc [0] -= wps->dc.shaping_delta [0] * wps->wphdr.block_samples;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
while (cnt--) {
|
||||||
|
lptr [0] += nosend_word (wps, rptr [0], 0) - rptr [0];
|
||||||
|
lptr++;
|
||||||
|
rptr++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void execute_mono (WavpackContext *wpc, int32_t *samples, int no_history, int do_samples)
|
||||||
|
{
|
||||||
|
int32_t *temp_buffer [2], *best_buffer, *noisy_buffer = NULL;
|
||||||
|
struct decorr_pass temp_decorr_pass, save_decorr_passes [MAX_NTERMS];
|
||||||
|
WavpackStream *wps = wpc->streams [wpc->current_stream];
|
||||||
|
int32_t num_samples = wps->wphdr.block_samples;
|
||||||
|
int32_t buf_size = sizeof (int32_t) * num_samples;
|
||||||
|
uint32_t best_size = (uint32_t) -1, size;
|
||||||
|
int log_limit, pi, i;
|
||||||
|
|
||||||
|
for (i = 0; i < num_samples; ++i)
|
||||||
|
if (samples [i])
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (i == num_samples) {
|
||||||
|
CLEAR (wps->decorr_passes);
|
||||||
|
wps->num_terms = 0;
|
||||||
|
init_words (wps);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef LOG_LIMIT
|
||||||
|
log_limit = (((wps->wphdr.flags & MAG_MASK) >> MAG_LSB) + 4) * 256;
|
||||||
|
|
||||||
|
if (log_limit > LOG_LIMIT)
|
||||||
|
log_limit = LOG_LIMIT;
|
||||||
|
#else
|
||||||
|
log_limit = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
CLEAR (save_decorr_passes);
|
||||||
|
temp_buffer [0] = malloc (buf_size);
|
||||||
|
temp_buffer [1] = malloc (buf_size);
|
||||||
|
best_buffer = malloc (buf_size);
|
||||||
|
|
||||||
|
if (wps->num_passes > 1 && (wps->wphdr.flags & HYBRID_FLAG)) {
|
||||||
|
CLEAR (temp_decorr_pass);
|
||||||
|
temp_decorr_pass.delta = 2;
|
||||||
|
temp_decorr_pass.term = 18;
|
||||||
|
|
||||||
|
decorr_mono_pass (samples, temp_buffer [0],
|
||||||
|
num_samples > 2048 ? 2048 : num_samples, &temp_decorr_pass, -1);
|
||||||
|
|
||||||
|
reverse_mono_decorr (&temp_decorr_pass);
|
||||||
|
decorr_mono_pass (samples, temp_buffer [0], num_samples, &temp_decorr_pass, 1);
|
||||||
|
CLEAR (temp_decorr_pass);
|
||||||
|
temp_decorr_pass.delta = 2;
|
||||||
|
temp_decorr_pass.term = 17;
|
||||||
|
|
||||||
|
decorr_mono_pass (temp_buffer [0], temp_buffer [1],
|
||||||
|
num_samples > 2048 ? 2048 : num_samples, &temp_decorr_pass, -1);
|
||||||
|
|
||||||
|
decorr_mono_pass (temp_buffer [0], temp_buffer [1], num_samples, &temp_decorr_pass, 1);
|
||||||
|
noisy_buffer = malloc (buf_size);
|
||||||
|
memcpy (noisy_buffer, samples, buf_size);
|
||||||
|
mono_add_noise (wps, noisy_buffer, temp_buffer [1]);
|
||||||
|
no_history = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (no_history || wps->num_passes >= 7)
|
||||||
|
wps->best_decorr = wps->mask_decorr = 0;
|
||||||
|
|
||||||
|
for (pi = 0; pi < wps->num_passes;) {
|
||||||
|
const WavpackDecorrSpec *wpds;
|
||||||
|
int nterms, c, j;
|
||||||
|
|
||||||
|
if (!pi)
|
||||||
|
c = wps->best_decorr;
|
||||||
|
else {
|
||||||
|
if (wps->mask_decorr == 0)
|
||||||
|
c = 0;
|
||||||
|
else
|
||||||
|
c = (wps->best_decorr & (wps->mask_decorr - 1)) | wps->mask_decorr;
|
||||||
|
|
||||||
|
if (c == wps->best_decorr) {
|
||||||
|
wps->mask_decorr = wps->mask_decorr ? ((wps->mask_decorr << 1) & (wps->num_decorrs - 1)) : 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wpds = &wps->decorr_specs [c];
|
||||||
|
nterms = (int) strlen (wpds->terms);
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
memcpy (temp_buffer [0], noisy_buffer ? noisy_buffer : samples, buf_size);
|
||||||
|
CLEAR (save_decorr_passes);
|
||||||
|
|
||||||
|
for (j = 0; j < nterms; ++j) {
|
||||||
|
CLEAR (temp_decorr_pass);
|
||||||
|
temp_decorr_pass.delta = wpds->delta;
|
||||||
|
temp_decorr_pass.term = wpds->terms [j];
|
||||||
|
|
||||||
|
if (temp_decorr_pass.term < 0)
|
||||||
|
temp_decorr_pass.term = 1;
|
||||||
|
|
||||||
|
decorr_mono_pass (temp_buffer [j&1], temp_buffer [~j&1],
|
||||||
|
num_samples > 2048 ? 2048 : num_samples, &temp_decorr_pass, -1);
|
||||||
|
|
||||||
|
if (j) {
|
||||||
|
CLEAR (temp_decorr_pass.samples_A);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
reverse_mono_decorr (&temp_decorr_pass);
|
||||||
|
|
||||||
|
memcpy (save_decorr_passes + j, &temp_decorr_pass, sizeof (struct decorr_pass));
|
||||||
|
decorr_mono_pass (temp_buffer [j&1], temp_buffer [~j&1], num_samples, &temp_decorr_pass, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
size = log2buffer (temp_buffer [j&1], num_samples, log_limit);
|
||||||
|
|
||||||
|
if (size == (uint32_t) -1 && nterms)
|
||||||
|
nterms >>= 1;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
size += log2overhead (wpds->terms [0], nterms);
|
||||||
|
|
||||||
|
if (size < best_size) {
|
||||||
|
memcpy (best_buffer, temp_buffer [j&1], buf_size);
|
||||||
|
memcpy (wps->decorr_passes, save_decorr_passes, sizeof (struct decorr_pass) * MAX_NTERMS);
|
||||||
|
wps->num_terms = nterms;
|
||||||
|
wps->best_decorr = c;
|
||||||
|
best_size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pi++)
|
||||||
|
wps->mask_decorr = wps->mask_decorr ? ((wps->mask_decorr << 1) & (wps->num_decorrs - 1)) : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wpc->config.xmode > 3) {
|
||||||
|
if (noisy_buffer) {
|
||||||
|
analyze_mono (wpc, noisy_buffer, do_samples);
|
||||||
|
|
||||||
|
if (do_samples)
|
||||||
|
memcpy (samples, noisy_buffer, buf_size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
analyze_mono (wpc, samples, do_samples);
|
||||||
|
}
|
||||||
|
else if (do_samples)
|
||||||
|
memcpy (samples, best_buffer, buf_size);
|
||||||
|
|
||||||
|
if (no_history || wpc->config.xmode > 3)
|
||||||
|
scan_word (wps, best_buffer, num_samples, -1);
|
||||||
|
|
||||||
|
if (noisy_buffer)
|
||||||
|
free (noisy_buffer);
|
||||||
|
|
||||||
|
free (temp_buffer [1]);
|
||||||
|
free (temp_buffer [0]);
|
||||||
|
free (best_buffer);
|
||||||
|
|
||||||
|
#ifdef EXTRA_DUMP
|
||||||
|
if (1) {
|
||||||
|
char string [256], substring [20];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
sprintf (string, "M: terms =");
|
||||||
|
|
||||||
|
for (i = 0; i < wps->num_terms; ++i) {
|
||||||
|
if (wps->decorr_passes [i].term) {
|
||||||
|
if (i && wps->decorr_passes [i-1].delta == wps->decorr_passes [i].delta)
|
||||||
|
sprintf (substring, " %d", wps->decorr_passes [i].term);
|
||||||
|
else
|
||||||
|
sprintf (substring, " %d->%d", wps->decorr_passes [i].term,
|
||||||
|
wps->decorr_passes [i].delta);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
sprintf (substring, " *");
|
||||||
|
|
||||||
|
strcat (string, substring);
|
||||||
|
}
|
||||||
|
|
||||||
|
error_line (string);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,242 @@
|
||||||
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
// **** 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
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
// **** WAVPACK **** //
|
// **** WAVPACK **** //
|
||||||
// Hybrid Lossless Wavefile Compressor //
|
// Hybrid Lossless Wavefile Compressor //
|
||||||
// Copyright (c) 1998 - 2005 Conifer Software. //
|
// Copyright (c) 1998 - 2006 Conifer Software. //
|
||||||
// All Rights Reserved. //
|
// All Rights Reserved. //
|
||||||
// Distributed under the BSD Software License (see license.txt) //
|
// Distributed under the BSD Software License (see license.txt) //
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// float.c
|
// float.c
|
||||||
|
|
||||||
#include "wavpack.h"
|
#include "wavpack_local.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ void free_db (void *ptr);
|
||||||
int32_t dump_alloc (void);
|
int32_t dump_alloc (void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef PACK
|
#ifndef NO_PACK
|
||||||
|
|
||||||
void write_float_info (WavpackStream *wps, WavpackMetadata *wpmd)
|
void write_float_info (WavpackStream *wps, WavpackMetadata *wpmd)
|
||||||
{
|
{
|
||||||
|
@ -34,7 +34,7 @@ void write_float_info (WavpackStream *wps, WavpackMetadata *wpmd)
|
||||||
*byteptr++ = wps->float_shift;
|
*byteptr++ = wps->float_shift;
|
||||||
*byteptr++ = wps->float_max_exp;
|
*byteptr++ = wps->float_max_exp;
|
||||||
*byteptr++ = wps->float_norm_exp;
|
*byteptr++ = wps->float_norm_exp;
|
||||||
wpmd->byte_length = byteptr - (char *) wpmd->data;
|
wpmd->byte_length = (int32_t)(byteptr - (char *) wpmd->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
int scan_float_data (WavpackStream *wps, f32 *values, int32_t num_values)
|
int scan_float_data (WavpackStream *wps, f32 *values, int32_t num_values)
|
||||||
|
@ -42,102 +42,102 @@ int scan_float_data (WavpackStream *wps, f32 *values, int32_t num_values)
|
||||||
int32_t shifted_ones = 0, shifted_zeros = 0, shifted_both = 0;
|
int32_t shifted_ones = 0, shifted_zeros = 0, shifted_both = 0;
|
||||||
int32_t false_zeros = 0, neg_zeros = 0;
|
int32_t false_zeros = 0, neg_zeros = 0;
|
||||||
uint32_t ordata = 0, crc = 0xffffffff;
|
uint32_t ordata = 0, crc = 0xffffffff;
|
||||||
int max_exp = 0, shift_count;
|
int32_t count, value, shift_count;
|
||||||
int32_t count, value;
|
int max_exp = 0;
|
||||||
f32 *dp;
|
f32 *dp;
|
||||||
|
|
||||||
wps->float_shift = wps->float_flags = 0;
|
wps->float_shift = wps->float_flags = 0;
|
||||||
|
|
||||||
for (dp = values, count = num_values; count--; dp++) {
|
for (dp = values, count = num_values; count--; dp++) {
|
||||||
crc = crc * 27 + dp->mantissa * 9 + dp->exponent * 3 + dp->sign;
|
crc = crc * 27 + get_mantissa (*dp) * 9 + get_exponent (*dp) * 3 + get_sign (*dp);
|
||||||
|
|
||||||
if (dp->exponent > max_exp && dp->exponent < 255)
|
if (get_exponent (*dp) > max_exp && get_exponent (*dp) < 255)
|
||||||
max_exp = dp->exponent;
|
max_exp = get_exponent (*dp);
|
||||||
}
|
}
|
||||||
|
|
||||||
wps->crc_x = crc;
|
wps->crc_x = crc;
|
||||||
|
|
||||||
for (dp = values, count = num_values; count--; dp++) {
|
for (dp = values, count = num_values; count--; dp++) {
|
||||||
if (dp->exponent == 255) {
|
if (get_exponent (*dp) == 255) {
|
||||||
wps->float_flags |= FLOAT_EXCEPTIONS;
|
wps->float_flags |= FLOAT_EXCEPTIONS;
|
||||||
value = 0x1000000;
|
value = 0x1000000;
|
||||||
shift_count = 0;
|
shift_count = 0;
|
||||||
}
|
}
|
||||||
else if (dp->exponent) {
|
else if (get_exponent (*dp)) {
|
||||||
shift_count = max_exp - dp->exponent;
|
shift_count = max_exp - get_exponent (*dp);
|
||||||
value = 0x800000 + dp->mantissa;
|
value = 0x800000 + get_mantissa (*dp);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
shift_count = max_exp ? max_exp - 1 : 0;
|
shift_count = max_exp ? max_exp - 1 : 0;
|
||||||
value = dp->mantissa;
|
value = get_mantissa (*dp);
|
||||||
|
|
||||||
// if (dp->mantissa)
|
// if (get_mantissa (*dp))
|
||||||
// denormals++;
|
// denormals++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shift_count < 25)
|
if (shift_count < 25)
|
||||||
value >>= shift_count;
|
value >>= shift_count;
|
||||||
else
|
else
|
||||||
value = 0;
|
value = 0;
|
||||||
|
|
||||||
if (!value) {
|
if (!value) {
|
||||||
if (dp->exponent || dp->mantissa)
|
if (get_exponent (*dp) || get_mantissa (*dp))
|
||||||
++false_zeros;
|
++false_zeros;
|
||||||
else if (dp->sign)
|
else if (get_sign (*dp))
|
||||||
++neg_zeros;
|
++neg_zeros;
|
||||||
}
|
}
|
||||||
else if (shift_count) {
|
else if (shift_count) {
|
||||||
int32_t mask = (1 << shift_count) - 1;
|
int32_t mask = (1 << shift_count) - 1;
|
||||||
|
|
||||||
if (!(dp->mantissa & mask))
|
if (!(get_mantissa (*dp) & mask))
|
||||||
shifted_zeros++;
|
shifted_zeros++;
|
||||||
else if ((dp->mantissa & mask) == mask)
|
else if ((get_mantissa (*dp) & mask) == mask)
|
||||||
shifted_ones++;
|
shifted_ones++;
|
||||||
else
|
else
|
||||||
shifted_both++;
|
shifted_both++;
|
||||||
}
|
}
|
||||||
|
|
||||||
ordata |= value;
|
ordata |= value;
|
||||||
* (int32_t *) dp = (dp->sign) ? -value : value;
|
* (int32_t *) dp = (get_sign (*dp)) ? -value : value;
|
||||||
}
|
}
|
||||||
|
|
||||||
wps->float_max_exp = max_exp;
|
wps->float_max_exp = max_exp;
|
||||||
|
|
||||||
if (shifted_both)
|
if (shifted_both)
|
||||||
wps->float_flags |= FLOAT_SHIFT_SENT;
|
wps->float_flags |= FLOAT_SHIFT_SENT;
|
||||||
else if (shifted_ones && !shifted_zeros)
|
else if (shifted_ones && !shifted_zeros)
|
||||||
wps->float_flags |= FLOAT_SHIFT_ONES;
|
wps->float_flags |= FLOAT_SHIFT_ONES;
|
||||||
else if (shifted_ones && shifted_zeros)
|
else if (shifted_ones && shifted_zeros)
|
||||||
wps->float_flags |= FLOAT_SHIFT_SAME;
|
wps->float_flags |= FLOAT_SHIFT_SAME;
|
||||||
else if (ordata && !(ordata & 1)) {
|
else if (ordata && !(ordata & 1)) {
|
||||||
while (!(ordata & 1)) {
|
while (!(ordata & 1)) {
|
||||||
wps->float_shift++;
|
wps->float_shift++;
|
||||||
ordata >>= 1;
|
ordata >>= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (dp = values, count = num_values; count--; dp++)
|
for (dp = values, count = num_values; count--; dp++)
|
||||||
* (int32_t *) dp >>= wps->float_shift;
|
* (int32_t *) dp >>= wps->float_shift;
|
||||||
}
|
}
|
||||||
|
|
||||||
wps->wphdr.flags &= ~MAG_MASK;
|
wps->wphdr.flags &= ~MAG_MASK;
|
||||||
|
|
||||||
while (ordata) {
|
while (ordata) {
|
||||||
wps->wphdr.flags += 1 << MAG_LSB;
|
wps->wphdr.flags += 1 << MAG_LSB;
|
||||||
ordata >>= 1;
|
ordata >>= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (false_zeros || neg_zeros)
|
if (false_zeros || neg_zeros)
|
||||||
wps->float_flags |= FLOAT_ZEROS_SENT;
|
wps->float_flags |= FLOAT_ZEROS_SENT;
|
||||||
|
|
||||||
if (neg_zeros)
|
if (neg_zeros)
|
||||||
wps->float_flags |= FLOAT_NEG_ZEROS;
|
wps->float_flags |= FLOAT_NEG_ZEROS;
|
||||||
|
|
||||||
// error_line ("samples = %d, max exp = %d, pre-shift = %d, denormals = %d",
|
// error_line ("samples = %d, max exp = %d, pre-shift = %d, denormals = %d",
|
||||||
// num_values, max_exp, wps->float_shift, denormals);
|
// num_values, max_exp, wps->float_shift, denormals);
|
||||||
// if (wps->float_flags & FLOAT_EXCEPTIONS)
|
// if (wps->float_flags & FLOAT_EXCEPTIONS)
|
||||||
// error_line ("exceptions!");
|
// error_line ("exceptions!");
|
||||||
// error_line ("shifted ones/zeros/both = %d/%d/%d, true/neg/false zeros = %d/%d/%d",
|
// error_line ("shifted ones/zeros/both = %d/%d/%d, true/neg/false zeros = %d/%d/%d",
|
||||||
// shifted_ones, shifted_zeros, shifted_both, true_zeros, neg_zeros, false_zeros);
|
// shifted_ones, shifted_zeros, shifted_both, true_zeros, neg_zeros, false_zeros);
|
||||||
|
|
||||||
return wps->float_flags & (FLOAT_EXCEPTIONS | FLOAT_ZEROS_SENT | FLOAT_SHIFT_SENT | FLOAT_SHIFT_SAME);
|
return wps->float_flags & (FLOAT_EXCEPTIONS | FLOAT_ZEROS_SENT | FLOAT_SHIFT_SENT | FLOAT_SHIFT_SAME);
|
||||||
}
|
}
|
||||||
|
@ -149,67 +149,67 @@ void send_float_data (WavpackStream *wps, f32 *values, int32_t num_values)
|
||||||
f32 *dp;
|
f32 *dp;
|
||||||
|
|
||||||
for (dp = values, count = num_values; count--; dp++) {
|
for (dp = values, count = num_values; count--; dp++) {
|
||||||
if (dp->exponent == 255) {
|
if (get_exponent (*dp) == 255) {
|
||||||
if (dp->mantissa) {
|
if (get_mantissa (*dp)) {
|
||||||
putbit_1 (&wps->wvxbits);
|
putbit_1 (&wps->wvxbits);
|
||||||
putbits (dp->mantissa, 23, &wps->wvxbits);
|
putbits (get_mantissa (*dp), 23, &wps->wvxbits);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
putbit_0 (&wps->wvxbits);
|
putbit_0 (&wps->wvxbits);
|
||||||
}
|
}
|
||||||
|
|
||||||
value = 0x1000000;
|
value = 0x1000000;
|
||||||
shift_count = 0;
|
shift_count = 0;
|
||||||
}
|
}
|
||||||
else if (dp->exponent) {
|
else if (get_exponent (*dp)) {
|
||||||
shift_count = max_exp - dp->exponent;
|
shift_count = max_exp - get_exponent (*dp);
|
||||||
value = 0x800000 + dp->mantissa;
|
value = 0x800000 + get_mantissa (*dp);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
shift_count = max_exp ? max_exp - 1 : 0;
|
shift_count = max_exp ? max_exp - 1 : 0;
|
||||||
value = dp->mantissa;
|
value = get_mantissa (*dp);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shift_count < 25)
|
if (shift_count < 25)
|
||||||
value >>= shift_count;
|
value >>= shift_count;
|
||||||
else
|
else
|
||||||
value = 0;
|
value = 0;
|
||||||
|
|
||||||
if (!value) {
|
if (!value) {
|
||||||
if (wps->float_flags & FLOAT_ZEROS_SENT) {
|
if (wps->float_flags & FLOAT_ZEROS_SENT) {
|
||||||
if (dp->exponent || dp->mantissa) {
|
if (get_exponent (*dp) || get_mantissa (*dp)) {
|
||||||
putbit_1 (&wps->wvxbits);
|
putbit_1 (&wps->wvxbits);
|
||||||
putbits (dp->mantissa, 23, &wps->wvxbits);
|
putbits (get_mantissa (*dp), 23, &wps->wvxbits);
|
||||||
|
|
||||||
if (max_exp >= 25) {
|
if (max_exp >= 25) {
|
||||||
putbits (dp->exponent, 8, &wps->wvxbits);
|
putbits (get_exponent (*dp), 8, &wps->wvxbits);
|
||||||
}
|
}
|
||||||
|
|
||||||
putbit (dp->sign, &wps->wvxbits);
|
putbit (get_sign (*dp), &wps->wvxbits);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
putbit_0 (&wps->wvxbits);
|
putbit_0 (&wps->wvxbits);
|
||||||
|
|
||||||
if (wps->float_flags & FLOAT_NEG_ZEROS)
|
if (wps->float_flags & FLOAT_NEG_ZEROS)
|
||||||
putbit (dp->sign, &wps->wvxbits);
|
putbit (get_sign (*dp), &wps->wvxbits);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (shift_count) {
|
else if (shift_count) {
|
||||||
if (wps->float_flags & FLOAT_SHIFT_SENT) {
|
if (wps->float_flags & FLOAT_SHIFT_SENT) {
|
||||||
int32_t data = dp->mantissa & ((1 << shift_count) - 1);
|
int32_t data = get_mantissa (*dp) & ((1 << shift_count) - 1);
|
||||||
putbits (data, shift_count, &wps->wvxbits);
|
putbits (data, shift_count, &wps->wvxbits);
|
||||||
}
|
}
|
||||||
else if (wps->float_flags & FLOAT_SHIFT_SAME) {
|
else if (wps->float_flags & FLOAT_SHIFT_SAME) {
|
||||||
putbit (dp->mantissa & 1, &wps->wvxbits);
|
putbit (get_mantissa (*dp) & 1, &wps->wvxbits);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(UNPACK) || defined(INFO_ONLY)
|
#if !defined(NO_UNPACK) || defined(INFO_ONLY)
|
||||||
|
|
||||||
int read_float_info (WavpackStream *wps, WavpackMetadata *wpmd)
|
int read_float_info (WavpackStream *wps, WavpackMetadata *wpmd)
|
||||||
{
|
{
|
||||||
|
@ -217,7 +217,7 @@ int read_float_info (WavpackStream *wps, WavpackMetadata *wpmd)
|
||||||
char *byteptr = wpmd->data;
|
char *byteptr = wpmd->data;
|
||||||
|
|
||||||
if (bytecnt != 4)
|
if (bytecnt != 4)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
wps->float_flags = *byteptr++;
|
wps->float_flags = *byteptr++;
|
||||||
wps->float_shift = *byteptr++;
|
wps->float_shift = *byteptr++;
|
||||||
|
@ -228,7 +228,7 @@ int read_float_info (WavpackStream *wps, WavpackMetadata *wpmd)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef UNPACK
|
#ifndef NO_UNPACK
|
||||||
|
|
||||||
static void float_values_nowvx (WavpackStream *wps, int32_t *values, int32_t num_values);
|
static void float_values_nowvx (WavpackStream *wps, int32_t *values, int32_t num_values);
|
||||||
|
|
||||||
|
@ -237,72 +237,72 @@ void float_values (WavpackStream *wps, int32_t *values, int32_t num_values)
|
||||||
uint32_t crc = wps->crc_x;
|
uint32_t crc = wps->crc_x;
|
||||||
|
|
||||||
if (!bs_is_open (&wps->wvxbits)) {
|
if (!bs_is_open (&wps->wvxbits)) {
|
||||||
float_values_nowvx (wps, values, num_values);
|
float_values_nowvx (wps, values, num_values);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (num_values--) {
|
while (num_values--) {
|
||||||
int shift_count = 0, exp = wps->float_max_exp;
|
int shift_count = 0, exp = wps->float_max_exp;
|
||||||
f32 outval = { 0, 0, 0 };
|
f32 outval = 0;
|
||||||
uint32_t temp;
|
uint32_t temp;
|
||||||
|
|
||||||
if (*values == 0) {
|
if (*values == 0) {
|
||||||
if (wps->float_flags & FLOAT_ZEROS_SENT) {
|
if (wps->float_flags & FLOAT_ZEROS_SENT) {
|
||||||
if (getbit (&wps->wvxbits)) {
|
if (getbit (&wps->wvxbits)) {
|
||||||
getbits (&temp, 23, &wps->wvxbits);
|
getbits (&temp, 23, &wps->wvxbits);
|
||||||
outval.mantissa = temp;
|
set_mantissa (outval, temp);
|
||||||
|
|
||||||
if (exp >= 25) {
|
if (exp >= 25) {
|
||||||
getbits (&temp, 8, &wps->wvxbits);
|
getbits (&temp, 8, &wps->wvxbits);
|
||||||
outval.exponent = temp;
|
set_exponent (outval, temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
outval.sign = getbit (&wps->wvxbits);
|
set_sign (outval, getbit (&wps->wvxbits));
|
||||||
}
|
}
|
||||||
else if (wps->float_flags & FLOAT_NEG_ZEROS)
|
else if (wps->float_flags & FLOAT_NEG_ZEROS)
|
||||||
outval.sign = getbit (&wps->wvxbits);
|
set_sign (outval, getbit (&wps->wvxbits));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
*values <<= wps->float_shift;
|
*values <<= wps->float_shift;
|
||||||
|
|
||||||
if (*values < 0) {
|
if (*values < 0) {
|
||||||
*values = -*values;
|
*values = -*values;
|
||||||
outval.sign = 1;
|
set_sign (outval, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*values == 0x1000000) {
|
if (*values == 0x1000000) {
|
||||||
if (getbit (&wps->wvxbits)) {
|
if (getbit (&wps->wvxbits)) {
|
||||||
getbits (&temp, 23, &wps->wvxbits);
|
getbits (&temp, 23, &wps->wvxbits);
|
||||||
outval.mantissa = temp;
|
set_mantissa (outval, temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
outval.exponent = 255;
|
set_exponent (outval, 255);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (exp)
|
if (exp)
|
||||||
while (!(*values & 0x800000) && --exp) {
|
while (!(*values & 0x800000) && --exp) {
|
||||||
shift_count++;
|
shift_count++;
|
||||||
*values <<= 1;
|
*values <<= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shift_count) {
|
if (shift_count) {
|
||||||
if ((wps->float_flags & FLOAT_SHIFT_ONES) ||
|
if ((wps->float_flags & FLOAT_SHIFT_ONES) ||
|
||||||
((wps->float_flags & FLOAT_SHIFT_SAME) && getbit (&wps->wvxbits)))
|
((wps->float_flags & FLOAT_SHIFT_SAME) && getbit (&wps->wvxbits)))
|
||||||
*values |= ((1 << shift_count) - 1);
|
*values |= ((1 << shift_count) - 1);
|
||||||
else if (wps->float_flags & FLOAT_SHIFT_SENT) {
|
else if (wps->float_flags & FLOAT_SHIFT_SENT) {
|
||||||
getbits (&temp, shift_count, &wps->wvxbits);
|
getbits (&temp, shift_count, &wps->wvxbits);
|
||||||
*values |= temp & ((1 << shift_count) - 1);
|
*values |= temp & ((1 << shift_count) - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
outval.mantissa = *values;
|
set_mantissa (outval, *values);
|
||||||
outval.exponent = exp;
|
set_exponent (outval, exp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
crc = crc * 27 + outval.mantissa * 9 + outval.exponent * 3 + outval.sign;
|
crc = crc * 27 + get_mantissa (outval) * 9 + get_exponent (outval) * 3 + get_sign (outval);
|
||||||
* (f32 *) values++ = outval;
|
* (f32 *) values++ = outval;
|
||||||
}
|
}
|
||||||
|
|
||||||
wps->crc_x = crc;
|
wps->crc_x = crc;
|
||||||
|
@ -311,61 +311,61 @@ void float_values (WavpackStream *wps, int32_t *values, int32_t num_values)
|
||||||
static void float_values_nowvx (WavpackStream *wps, int32_t *values, int32_t num_values)
|
static void float_values_nowvx (WavpackStream *wps, int32_t *values, int32_t num_values)
|
||||||
{
|
{
|
||||||
while (num_values--) {
|
while (num_values--) {
|
||||||
int shift_count = 0, exp = wps->float_max_exp;
|
int shift_count = 0, exp = wps->float_max_exp;
|
||||||
f32 outval = { 0, 0, 0 };
|
f32 outval = 0;
|
||||||
|
|
||||||
if (*values) {
|
if (*values) {
|
||||||
*values <<= wps->float_shift;
|
*values <<= wps->float_shift;
|
||||||
|
|
||||||
if (*values < 0) {
|
if (*values < 0) {
|
||||||
*values = -*values;
|
*values = -*values;
|
||||||
outval.sign = 1;
|
set_sign (outval, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*values >= 0x1000000) {
|
if (*values >= 0x1000000) {
|
||||||
while (*values & 0xf000000) {
|
while (*values & 0xf000000) {
|
||||||
*values >>= 1;
|
*values >>= 1;
|
||||||
++exp;
|
++exp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (exp) {
|
else if (exp) {
|
||||||
while (!(*values & 0x800000) && --exp) {
|
while (!(*values & 0x800000) && --exp) {
|
||||||
shift_count++;
|
shift_count++;
|
||||||
*values <<= 1;
|
*values <<= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shift_count && (wps->float_flags & FLOAT_SHIFT_ONES))
|
if (shift_count && (wps->float_flags & FLOAT_SHIFT_ONES))
|
||||||
*values |= ((1 << shift_count) - 1);
|
*values |= ((1 << shift_count) - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
outval.mantissa = *values;
|
set_mantissa (outval, *values);
|
||||||
outval.exponent = exp;
|
set_exponent (outval, exp);
|
||||||
}
|
}
|
||||||
|
|
||||||
* (f32 *) values++ = outval;
|
* (f32 *) values++ = outval;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void float_normalize (int32_t *values, int32_t num_values, int delta_exp)
|
void WavpackFloatNormalize (int32_t *values, int32_t num_values, int delta_exp)
|
||||||
{
|
{
|
||||||
f32 *fvalues = (f32 *) values, fzero = { 0, 0, 0 };
|
f32 *fvalues = (f32 *) values;
|
||||||
int exp;
|
int exp;
|
||||||
|
|
||||||
if (!delta_exp)
|
if (!delta_exp)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
while (num_values--) {
|
while (num_values--) {
|
||||||
if ((exp = fvalues->exponent) == 0 || exp + delta_exp <= 0)
|
if ((exp = get_exponent (*fvalues)) == 0 || exp + delta_exp <= 0)
|
||||||
*fvalues = fzero;
|
*fvalues = 0;
|
||||||
else if (exp == 255 || (exp += delta_exp) >= 255) {
|
else if (exp == 255 || (exp += delta_exp) >= 255) {
|
||||||
fvalues->exponent = 255;
|
set_exponent (*fvalues, 255);
|
||||||
fvalues->mantissa = 0;
|
set_mantissa (*fvalues, 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
fvalues->exponent = exp;
|
set_exponent (*fvalues, exp);
|
||||||
|
|
||||||
fvalues++;
|
fvalues++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,96 +0,0 @@
|
||||||
////////////////////////////////////////////////////////////////////////////
|
|
||||||
// **** WAVPACK **** //
|
|
||||||
// Hybrid Lossless Wavefile Compressor //
|
|
||||||
// Copyright (c) 1998 - 2005 Conifer Software. //
|
|
||||||
// All Rights Reserved. //
|
|
||||||
// Distributed under the BSD Software License (see license.txt) //
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
WavPack 4.0 File / Block Format
|
|
||||||
-------------------------------
|
|
||||||
|
|
||||||
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. There are no seek tables.
|
|
||||||
|
|
||||||
The blocks (or frames, if you prefer) are completely independent in that they
|
|
||||||
can be decoded to mono or stereo audio all by themselves. A single function
|
|
||||||
is provided to convert a whole block into its corresponding audio data.
|
|
||||||
Similarly, a function is provided to convert a block of audio samples into
|
|
||||||
a finished WavPack block. These all work in memory; disk I/O is handled
|
|
||||||
outside. It is also possible to decode or encode blocks in smaller increments
|
|
||||||
if it is important to distribute CPU load more evenly over time. The blocks may
|
|
||||||
also be decoded without reading the whole block into memory, although this
|
|
||||||
would only be important for hardware decoding.
|
|
||||||
|
|
||||||
The blocks may contain any number of samples, either stereo or mono. Obviously,
|
|
||||||
putting more samples in each block is more efficient, 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 lossy modes are basically CBR, but I am planning a quality
|
|
||||||
based VBR version also).
|
|
||||||
|
|
||||||
For multichannel audio, the data is divided into some number of stereo and mono
|
|
||||||
streams and multiplexed into separate blocks. Because blocks are independent
|
|
||||||
there can be a mix of sampling rates, but all the streams must be sliced at
|
|
||||||
the same point in time which is a multiple of all the sampling rates. The
|
|
||||||
metadata contains source information (like front, center, rear, etc.).
|
|
||||||
|
|
||||||
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 CRC value, although it is easy to
|
|
||||||
tell the blocks apart by looking at the metadata ids.
|
|
||||||
|
|
||||||
Here is the 32-byte header at the front of every block:
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char ckID [4]; // "wvpk"
|
|
||||||
long ckSize; // size of entire frame (minus 8, of course)
|
|
||||||
short version; // 0x403 for now
|
|
||||||
uchar track_no; // track number (0 if not used, like now)
|
|
||||||
uchar index_no; // track sub-index (0 if not used, like now)
|
|
||||||
ulong total_samples; // for entire file (-1 if unknown)
|
|
||||||
ulong block_index; // index of first sample in block (to file begin)
|
|
||||||
ulong block_samples; // # samples in this block
|
|
||||||
ulong flags; // various flags for id and decoding
|
|
||||||
ulong crc; // crc for actual decoded data
|
|
||||||
} WavpackHeader;
|
|
||||||
|
|
||||||
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. This structure is stored "little-endian".
|
|
||||||
|
|
||||||
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). Currently these
|
|
||||||
mostly contain extra information needed to decode the audio, but may also
|
|
||||||
contain user information. The only non-audio information I currently have
|
|
||||||
implemented is a copy of the original wave RIFF header (or trailer if present),
|
|
||||||
and the MD5 checksums, but there is plenty of flexibility here. For example,
|
|
||||||
these metadata blocks could store cuesheets, artist/title information,
|
|
||||||
replaygain values, even pictures or lyrics. The final metadata sub-blocks are
|
|
||||||
the actual audio bitstreams, which have ids for standard audio (wvbits),
|
|
||||||
correction data (wvcbits), and a special extension for large integer and
|
|
||||||
floating-point data (wvxbits).
|
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
ushort data [word_size]; // data, padded to an even # of bytes
|
|
|
@ -1,4 +1,4 @@
|
||||||
Copyright (c) 1998 - 2005 Conifer Software
|
Copyright (c) 1998 - 2009 Conifer Software
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This code implements the MD5 message-digest algorithm.
|
* This code implements the MD5 message-digest algorithm.
|
||||||
* The algorithm is due to Ron Rivest. This code was
|
* The algorithm is due to Ron Rivest. This code was
|
||||||
* written by Colin Plumb in 1993, no copyright is claimed.
|
* written by Colin Plumb in 1993, no copyright is claimed.
|
||||||
* This code is in the public domain; do with it what you wish.
|
* This code is in the public domain; do with it what you wish.
|
||||||
*
|
*
|
||||||
|
@ -19,7 +19,7 @@
|
||||||
prototypes) to maintain the tradition that Netfone will compile
|
prototypes) to maintain the tradition that Netfone will compile
|
||||||
with Sun's original "cc". */
|
with Sun's original "cc". */
|
||||||
|
|
||||||
#include <memory.h> /* for memcpy() */
|
#include <memory.h> /* for memcpy() */
|
||||||
#include "md5.h"
|
#include "md5.h"
|
||||||
|
|
||||||
#ifdef sgi
|
#ifdef sgi
|
||||||
|
@ -31,7 +31,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef HIGHFIRST
|
#ifndef HIGHFIRST
|
||||||
#define byteReverse(buf, len) /* Nothing */
|
#define byteReverse(buf, len) /* Nothing */
|
||||||
#else
|
#else
|
||||||
/*
|
/*
|
||||||
* Note: this code is harmless on little-endian machines.
|
* Note: this code is harmless on little-endian machines.
|
||||||
|
@ -41,10 +41,10 @@ void byteReverse(buf, longs)
|
||||||
{
|
{
|
||||||
uint32 t;
|
uint32 t;
|
||||||
do {
|
do {
|
||||||
t = (uint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
|
t = (uint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
|
||||||
((unsigned) buf[1] << 8 | buf[0]);
|
((unsigned) buf[1] << 8 | buf[0]);
|
||||||
*(uint32 *) buf = t;
|
*(uint32 *) buf = t;
|
||||||
buf += 4;
|
buf += 4;
|
||||||
} while (--longs);
|
} while (--longs);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -78,35 +78,35 @@ void MD5Update(ctx, buf, len)
|
||||||
|
|
||||||
t = ctx->bits[0];
|
t = ctx->bits[0];
|
||||||
if ((ctx->bits[0] = t + ((uint32) len << 3)) < t)
|
if ((ctx->bits[0] = t + ((uint32) len << 3)) < t)
|
||||||
ctx->bits[1]++; /* Carry from low to high */
|
ctx->bits[1]++; /* Carry from low to high */
|
||||||
ctx->bits[1] += len >> 29;
|
ctx->bits[1] += len >> 29;
|
||||||
|
|
||||||
t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
|
t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
|
||||||
|
|
||||||
/* Handle any leading odd-sized chunks */
|
/* Handle any leading odd-sized chunks */
|
||||||
|
|
||||||
if (t) {
|
if (t) {
|
||||||
unsigned char *p = (unsigned char *) ctx->in + t;
|
unsigned char *p = (unsigned char *) ctx->in + t;
|
||||||
|
|
||||||
t = 64 - t;
|
t = 64 - t;
|
||||||
if (len < t) {
|
if (len < t) {
|
||||||
memcpy(p, buf, len);
|
memcpy(p, buf, len);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
memcpy(p, buf, t);
|
memcpy(p, buf, t);
|
||||||
byteReverse(ctx->in, 16);
|
byteReverse(ctx->in, 16);
|
||||||
MD5Transform(ctx->buf, (uint32 *) ctx->in);
|
MD5Transform(ctx->buf, (uint32 *) ctx->in);
|
||||||
buf += t;
|
buf += t;
|
||||||
len -= t;
|
len -= t;
|
||||||
}
|
}
|
||||||
/* Process data in 64-byte chunks */
|
/* Process data in 64-byte chunks */
|
||||||
|
|
||||||
while (len >= 64) {
|
while (len >= 64) {
|
||||||
memcpy(ctx->in, buf, 64);
|
memcpy(ctx->in, buf, 64);
|
||||||
byteReverse(ctx->in, 16);
|
byteReverse(ctx->in, 16);
|
||||||
MD5Transform(ctx->buf, (uint32 *) ctx->in);
|
MD5Transform(ctx->buf, (uint32 *) ctx->in);
|
||||||
buf += 64;
|
buf += 64;
|
||||||
len -= 64;
|
len -= 64;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle any remaining bytes of data. */
|
/* Handle any remaining bytes of data. */
|
||||||
|
@ -137,16 +137,16 @@ void MD5Final(digest, ctx)
|
||||||
|
|
||||||
/* Pad out to 56 mod 64 */
|
/* Pad out to 56 mod 64 */
|
||||||
if (count < 8) {
|
if (count < 8) {
|
||||||
/* Two lots of padding: Pad the first block to 64 bytes */
|
/* Two lots of padding: Pad the first block to 64 bytes */
|
||||||
memset(p, 0, count);
|
memset(p, 0, count);
|
||||||
byteReverse(ctx->in, 16);
|
byteReverse(ctx->in, 16);
|
||||||
MD5Transform(ctx->buf, (uint32 *) ctx->in);
|
MD5Transform(ctx->buf, (uint32 *) ctx->in);
|
||||||
|
|
||||||
/* Now fill the next block with 56 bytes */
|
/* Now fill the next block with 56 bytes */
|
||||||
memset(ctx->in, 0, 56);
|
memset(ctx->in, 0, 56);
|
||||||
} else {
|
} else {
|
||||||
/* Pad block to 56 bytes */
|
/* Pad block to 56 bytes */
|
||||||
memset(p, 0, count - 8);
|
memset(p, 0, count - 8);
|
||||||
}
|
}
|
||||||
byteReverse(ctx->in, 14);
|
byteReverse(ctx->in, 14);
|
||||||
|
|
||||||
|
@ -157,7 +157,7 @@ void MD5Final(digest, ctx)
|
||||||
MD5Transform(ctx->buf, (uint32 *) ctx->in);
|
MD5Transform(ctx->buf, (uint32 *) ctx->in);
|
||||||
byteReverse((unsigned char *) ctx->buf, 4);
|
byteReverse((unsigned char *) ctx->buf, 4);
|
||||||
memcpy(digest, ctx->buf, 16);
|
memcpy(digest, ctx->buf, 16);
|
||||||
memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
|
memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -171,7 +171,7 @@ void MD5Final(digest, ctx)
|
||||||
|
|
||||||
/* This is the central step in the MD5 algorithm. */
|
/* This is the central step in the MD5 algorithm. */
|
||||||
#define MD5STEP(f, w, x, y, z, data, s) \
|
#define MD5STEP(f, w, x, y, z, data, s) \
|
||||||
( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
|
( 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
|
* The core of the MD5 algorithm, this alters an existing MD5 hash to
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
// **** WAVPACK **** //
|
// **** WAVPACK **** //
|
||||||
// Hybrid Lossless Wavefile Compressor //
|
// Hybrid Lossless Wavefile Compressor //
|
||||||
// Copyright (c) 1998 - 2005 Conifer Software. //
|
// Copyright (c) 1998 - 2006 Conifer Software. //
|
||||||
// All Rights Reserved. //
|
// All Rights Reserved. //
|
||||||
// Distributed under the BSD Software License (see license.txt) //
|
// Distributed under the BSD Software License (see license.txt) //
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
// This module handles the metadata structure introduced in WavPack 4.0
|
// This module handles the metadata structure introduced in WavPack 4.0
|
||||||
|
|
||||||
#include "wavpack.h"
|
#include "wavpack_local.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -25,45 +25,45 @@ void free_db (void *ptr);
|
||||||
int32_t dump_alloc (void);
|
int32_t dump_alloc (void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(UNPACK) || defined(INFO_ONLY)
|
#if !defined(NO_UNPACK) || defined(INFO_ONLY)
|
||||||
|
|
||||||
int read_metadata_buff (WavpackMetadata *wpmd, uchar *blockbuff, uchar **buffptr)
|
int read_metadata_buff (WavpackMetadata *wpmd, unsigned char *blockbuff, unsigned char **buffptr)
|
||||||
{
|
{
|
||||||
WavpackHeader *wphdr = (WavpackHeader *) blockbuff;
|
WavpackHeader *wphdr = (WavpackHeader *) blockbuff;
|
||||||
uchar *buffend = blockbuff + wphdr->ckSize + 8;
|
unsigned char *buffend = blockbuff + wphdr->ckSize + 8;
|
||||||
|
|
||||||
if (buffend - *buffptr < 2)
|
if (buffend - *buffptr < 2)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
wpmd->id = *(*buffptr)++;
|
wpmd->id = *(*buffptr)++;
|
||||||
wpmd->byte_length = *(*buffptr)++ << 1;
|
wpmd->byte_length = *(*buffptr)++ << 1;
|
||||||
|
|
||||||
if (wpmd->id & ID_LARGE) {
|
if (wpmd->id & ID_LARGE) {
|
||||||
wpmd->id &= ~ID_LARGE;
|
wpmd->id &= ~ID_LARGE;
|
||||||
|
|
||||||
if (buffend - *buffptr < 2)
|
if (buffend - *buffptr < 2)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
wpmd->byte_length += *(*buffptr)++ << 9;
|
wpmd->byte_length += *(*buffptr)++ << 9;
|
||||||
wpmd->byte_length += *(*buffptr)++ << 17;
|
wpmd->byte_length += *(*buffptr)++ << 17;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wpmd->id & ID_ODD_SIZE) {
|
if (wpmd->id & ID_ODD_SIZE) {
|
||||||
wpmd->id &= ~ID_ODD_SIZE;
|
wpmd->id &= ~ID_ODD_SIZE;
|
||||||
wpmd->byte_length--;
|
wpmd->byte_length--;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wpmd->byte_length) {
|
if (wpmd->byte_length) {
|
||||||
if (buffend - *buffptr < wpmd->byte_length + (wpmd->byte_length & 1)) {
|
if (buffend - *buffptr < wpmd->byte_length + (wpmd->byte_length & 1)) {
|
||||||
wpmd->data = NULL;
|
wpmd->data = NULL;
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
wpmd->data = *buffptr;
|
wpmd->data = *buffptr;
|
||||||
(*buffptr) += wpmd->byte_length + (wpmd->byte_length & 1);
|
(*buffptr) += wpmd->byte_length + (wpmd->byte_length & 1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
wpmd->data = NULL;
|
wpmd->data = NULL;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -73,144 +73,144 @@ int process_metadata (WavpackContext *wpc, WavpackMetadata *wpmd)
|
||||||
WavpackStream *wps = wpc->streams [wpc->current_stream];
|
WavpackStream *wps = wpc->streams [wpc->current_stream];
|
||||||
|
|
||||||
switch (wpmd->id) {
|
switch (wpmd->id) {
|
||||||
case ID_DUMMY:
|
case ID_DUMMY:
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
case ID_DECORR_TERMS:
|
case ID_DECORR_TERMS:
|
||||||
return read_decorr_terms (wps, wpmd);
|
return read_decorr_terms (wps, wpmd);
|
||||||
|
|
||||||
case ID_DECORR_WEIGHTS:
|
case ID_DECORR_WEIGHTS:
|
||||||
return read_decorr_weights (wps, wpmd);
|
return read_decorr_weights (wps, wpmd);
|
||||||
|
|
||||||
case ID_DECORR_SAMPLES:
|
case ID_DECORR_SAMPLES:
|
||||||
return read_decorr_samples (wps, wpmd);
|
return read_decorr_samples (wps, wpmd);
|
||||||
|
|
||||||
case ID_ENTROPY_VARS:
|
case ID_ENTROPY_VARS:
|
||||||
return read_entropy_vars (wps, wpmd);
|
return read_entropy_vars (wps, wpmd);
|
||||||
|
|
||||||
case ID_HYBRID_PROFILE:
|
case ID_HYBRID_PROFILE:
|
||||||
return read_hybrid_profile (wps, wpmd);
|
return read_hybrid_profile (wps, wpmd);
|
||||||
|
|
||||||
case ID_SHAPING_WEIGHTS:
|
case ID_SHAPING_WEIGHTS:
|
||||||
return read_shaping_info (wps, wpmd);
|
return read_shaping_info (wps, wpmd);
|
||||||
|
|
||||||
case ID_FLOAT_INFO:
|
case ID_FLOAT_INFO:
|
||||||
return read_float_info (wps, wpmd);
|
return read_float_info (wps, wpmd);
|
||||||
|
|
||||||
case ID_INT32_INFO:
|
case ID_INT32_INFO:
|
||||||
return read_int32_info (wps, wpmd);
|
return read_int32_info (wps, wpmd);
|
||||||
|
|
||||||
case ID_CHANNEL_INFO:
|
case ID_CHANNEL_INFO:
|
||||||
return read_channel_info (wpc, wpmd);
|
return read_channel_info (wpc, wpmd);
|
||||||
|
|
||||||
case ID_CONFIG_BLOCK:
|
case ID_CONFIG_BLOCK:
|
||||||
return read_config_info (wpc, wpmd);
|
return read_config_info (wpc, wpmd);
|
||||||
|
|
||||||
case ID_SAMPLE_RATE:
|
case ID_SAMPLE_RATE:
|
||||||
return read_sample_rate (wpc, wpmd);
|
return read_sample_rate (wpc, wpmd);
|
||||||
|
|
||||||
case ID_WV_BITSTREAM:
|
case ID_WV_BITSTREAM:
|
||||||
return init_wv_bitstream (wps, wpmd);
|
return init_wv_bitstream (wps, wpmd);
|
||||||
|
|
||||||
case ID_WVC_BITSTREAM:
|
case ID_WVC_BITSTREAM:
|
||||||
return init_wvc_bitstream (wps, wpmd);
|
return init_wvc_bitstream (wps, wpmd);
|
||||||
|
|
||||||
case ID_WVX_BITSTREAM:
|
case ID_WVX_BITSTREAM:
|
||||||
return init_wvx_bitstream (wps, wpmd);
|
return init_wvx_bitstream (wps, wpmd);
|
||||||
|
|
||||||
case ID_RIFF_HEADER: case ID_RIFF_TRAILER:
|
case ID_RIFF_HEADER: case ID_RIFF_TRAILER:
|
||||||
return read_wrapper_data (wpc, wpmd);
|
return read_wrapper_data (wpc, wpmd);
|
||||||
|
|
||||||
case ID_MD5_CHECKSUM:
|
case ID_MD5_CHECKSUM:
|
||||||
if (wpmd->byte_length == 16) {
|
if (wpmd->byte_length == 16) {
|
||||||
memcpy (wpc->config.md5_checksum, wpmd->data, 16);
|
memcpy (wpc->config.md5_checksum, wpmd->data, 16);
|
||||||
wpc->config.flags |= CONFIG_MD5_CHECKSUM;
|
wpc->config.flags |= CONFIG_MD5_CHECKSUM;
|
||||||
wpc->config.md5_read = 1;
|
wpc->config.md5_read = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return (wpmd->id & ID_OPTIONAL_DATA) ? TRUE : FALSE;
|
return (wpmd->id & ID_OPTIONAL_DATA) ? TRUE : FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef PACK
|
#ifndef NO_PACK
|
||||||
|
|
||||||
int copy_metadata (WavpackMetadata *wpmd, uchar *buffer_start, uchar *buffer_end)
|
int copy_metadata (WavpackMetadata *wpmd, unsigned char *buffer_start, unsigned char *buffer_end)
|
||||||
{
|
{
|
||||||
uint32_t mdsize = wpmd->byte_length + (wpmd->byte_length & 1);
|
uint32_t mdsize = wpmd->byte_length + (wpmd->byte_length & 1);
|
||||||
WavpackHeader *wphdr = (WavpackHeader *) buffer_start;
|
WavpackHeader *wphdr = (WavpackHeader *) buffer_start;
|
||||||
|
|
||||||
if (wpmd->byte_length & 1)
|
if (wpmd->byte_length & 1)
|
||||||
((char *) wpmd->data) [wpmd->byte_length] = 0;
|
((char *) wpmd->data) [wpmd->byte_length] = 0;
|
||||||
|
|
||||||
mdsize += (wpmd->byte_length > 510) ? 4 : 2;
|
mdsize += (wpmd->byte_length > 510) ? 4 : 2;
|
||||||
buffer_start += wphdr->ckSize + 8;
|
buffer_start += wphdr->ckSize + 8;
|
||||||
|
|
||||||
if (buffer_start + mdsize >= buffer_end)
|
if (buffer_start + mdsize >= buffer_end)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
buffer_start [0] = wpmd->id | (wpmd->byte_length & 1 ? ID_ODD_SIZE : 0);
|
buffer_start [0] = wpmd->id | (wpmd->byte_length & 1 ? ID_ODD_SIZE : 0);
|
||||||
buffer_start [1] = (wpmd->byte_length + 1) >> 1;
|
buffer_start [1] = (wpmd->byte_length + 1) >> 1;
|
||||||
|
|
||||||
if (wpmd->byte_length > 510) {
|
if (wpmd->byte_length > 510) {
|
||||||
buffer_start [0] |= ID_LARGE;
|
buffer_start [0] |= ID_LARGE;
|
||||||
buffer_start [2] = (wpmd->byte_length + 1) >> 9;
|
buffer_start [2] = (wpmd->byte_length + 1) >> 9;
|
||||||
buffer_start [3] = (wpmd->byte_length + 1) >> 17;
|
buffer_start [3] = (wpmd->byte_length + 1) >> 17;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wpmd->data && wpmd->byte_length) {
|
if (wpmd->data && wpmd->byte_length) {
|
||||||
if (wpmd->byte_length > 510) {
|
if (wpmd->byte_length > 510) {
|
||||||
buffer_start [0] |= ID_LARGE;
|
buffer_start [0] |= ID_LARGE;
|
||||||
buffer_start [2] = (wpmd->byte_length + 1) >> 9;
|
buffer_start [2] = (wpmd->byte_length + 1) >> 9;
|
||||||
buffer_start [3] = (wpmd->byte_length + 1) >> 17;
|
buffer_start [3] = (wpmd->byte_length + 1) >> 17;
|
||||||
memcpy (buffer_start + 4, wpmd->data, mdsize - 4);
|
memcpy (buffer_start + 4, wpmd->data, mdsize - 4);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
memcpy (buffer_start + 2, wpmd->data, mdsize - 2);
|
memcpy (buffer_start + 2, wpmd->data, mdsize - 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
wphdr->ckSize += mdsize;
|
wphdr->ckSize += mdsize;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
int add_to_metadata (WavpackContext *wpc, void *data, uint32_t bcount, uchar id)
|
int add_to_metadata (WavpackContext *wpc, void *data, uint32_t bcount, unsigned char id)
|
||||||
{
|
{
|
||||||
WavpackMetadata *mdp;
|
WavpackMetadata *mdp;
|
||||||
uchar *src = data;
|
unsigned char *src = data;
|
||||||
|
|
||||||
while (bcount) {
|
while (bcount) {
|
||||||
if (wpc->metacount) {
|
if (wpc->metacount) {
|
||||||
uint32_t bc = bcount;
|
uint32_t bc = bcount;
|
||||||
|
|
||||||
mdp = wpc->metadata + wpc->metacount - 1;
|
mdp = wpc->metadata + wpc->metacount - 1;
|
||||||
|
|
||||||
if (mdp->id == id) {
|
if (mdp->id == id) {
|
||||||
if (wpc->metabytes + bcount > 1000000)
|
if (wpc->metabytes + bcount > 1000000)
|
||||||
bc = 1000000 - wpc->metabytes;
|
bc = 1000000 - wpc->metabytes;
|
||||||
|
|
||||||
mdp->data = realloc (mdp->data, mdp->byte_length + bc);
|
mdp->data = realloc (mdp->data, mdp->byte_length + bc);
|
||||||
memcpy ((char *) mdp->data + mdp->byte_length, src, bc);
|
memcpy ((char *) mdp->data + mdp->byte_length, src, bc);
|
||||||
mdp->byte_length += bc;
|
mdp->byte_length += bc;
|
||||||
wpc->metabytes += bc;
|
wpc->metabytes += bc;
|
||||||
bcount -= bc;
|
bcount -= bc;
|
||||||
src += bc;
|
src += bc;
|
||||||
|
|
||||||
if (wpc->metabytes >= 1000000 && !write_metadata_block (wpc))
|
if (wpc->metabytes >= 1000000 && !write_metadata_block (wpc))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bcount) {
|
if (bcount) {
|
||||||
wpc->metadata = realloc (wpc->metadata, (wpc->metacount + 1) * sizeof (WavpackMetadata));
|
wpc->metadata = realloc (wpc->metadata, (wpc->metacount + 1) * sizeof (WavpackMetadata));
|
||||||
mdp = wpc->metadata + wpc->metacount++;
|
mdp = wpc->metadata + wpc->metacount++;
|
||||||
mdp->byte_length = 0;
|
mdp->byte_length = 0;
|
||||||
mdp->data = NULL;
|
mdp->data = NULL;
|
||||||
mdp->id = id;
|
mdp->id = id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -218,34 +218,34 @@ int add_to_metadata (WavpackContext *wpc, void *data, uint32_t bcount, uchar id)
|
||||||
|
|
||||||
static char *write_metadata (WavpackMetadata *wpmd, char *outdata)
|
static char *write_metadata (WavpackMetadata *wpmd, char *outdata)
|
||||||
{
|
{
|
||||||
uchar id = wpmd->id, wordlen [3];
|
unsigned char id = wpmd->id, wordlen [3];
|
||||||
|
|
||||||
wordlen [0] = (wpmd->byte_length + 1) >> 1;
|
wordlen [0] = (wpmd->byte_length + 1) >> 1;
|
||||||
wordlen [1] = (wpmd->byte_length + 1) >> 9;
|
wordlen [1] = (wpmd->byte_length + 1) >> 9;
|
||||||
wordlen [2] = (wpmd->byte_length + 1) >> 17;
|
wordlen [2] = (wpmd->byte_length + 1) >> 17;
|
||||||
|
|
||||||
if (wpmd->byte_length & 1) {
|
if (wpmd->byte_length & 1) {
|
||||||
// ((char *) wpmd->data) [wpmd->byte_length] = 0;
|
// ((char *) wpmd->data) [wpmd->byte_length] = 0;
|
||||||
id |= ID_ODD_SIZE;
|
id |= ID_ODD_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wordlen [1] || wordlen [2])
|
if (wordlen [1] || wordlen [2])
|
||||||
id |= ID_LARGE;
|
id |= ID_LARGE;
|
||||||
|
|
||||||
*outdata++ = id;
|
*outdata++ = id;
|
||||||
*outdata++ = wordlen [0];
|
*outdata++ = wordlen [0];
|
||||||
|
|
||||||
if (id & ID_LARGE) {
|
if (id & ID_LARGE) {
|
||||||
*outdata++ = wordlen [1];
|
*outdata++ = wordlen [1];
|
||||||
*outdata++ = wordlen [2];
|
*outdata++ = wordlen [2];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wpmd->data && wpmd->byte_length) {
|
if (wpmd->data && wpmd->byte_length) {
|
||||||
memcpy (outdata, wpmd->data, wpmd->byte_length);
|
memcpy (outdata, wpmd->data, wpmd->byte_length);
|
||||||
outdata += wpmd->byte_length;
|
outdata += wpmd->byte_length;
|
||||||
|
|
||||||
if (wpmd->byte_length & 1)
|
if (wpmd->byte_length & 1)
|
||||||
*outdata++ = 0;
|
*outdata++ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return outdata;
|
return outdata;
|
||||||
|
@ -257,46 +257,46 @@ int write_metadata_block (WavpackContext *wpc)
|
||||||
WavpackHeader *wphdr;
|
WavpackHeader *wphdr;
|
||||||
|
|
||||||
if (wpc->metacount) {
|
if (wpc->metacount) {
|
||||||
int metacount = wpc->metacount, block_size = sizeof (WavpackHeader);
|
int metacount = wpc->metacount, block_size = sizeof (WavpackHeader);
|
||||||
WavpackMetadata *wpmdp = wpc->metadata;
|
WavpackMetadata *wpmdp = wpc->metadata;
|
||||||
|
|
||||||
while (metacount--) {
|
while (metacount--) {
|
||||||
block_size += wpmdp->byte_length + (wpmdp->byte_length & 1);
|
block_size += wpmdp->byte_length + (wpmdp->byte_length & 1);
|
||||||
block_size += (wpmdp->byte_length > 510) ? 4 : 2;
|
block_size += (wpmdp->byte_length > 510) ? 4 : 2;
|
||||||
wpmdp++;
|
wpmdp++;
|
||||||
}
|
}
|
||||||
|
|
||||||
wphdr = (WavpackHeader *) (block_buff = malloc (block_size));
|
wphdr = (WavpackHeader *) (block_buff = malloc (block_size));
|
||||||
|
|
||||||
CLEAR (*wphdr);
|
CLEAR (*wphdr);
|
||||||
memcpy (wphdr->ckID, "wvpk", 4);
|
memcpy (wphdr->ckID, "wvpk", 4);
|
||||||
wphdr->total_samples = wpc->total_samples;
|
wphdr->total_samples = wpc->total_samples;
|
||||||
wphdr->version = wpc->stream_version;
|
wphdr->version = wpc->stream_version;
|
||||||
wphdr->ckSize = block_size - 8;
|
wphdr->ckSize = block_size - 8;
|
||||||
wphdr->block_samples = 0;
|
wphdr->block_samples = 0;
|
||||||
|
|
||||||
block_ptr = (char *)(wphdr + 1);
|
block_ptr = (char *)(wphdr + 1);
|
||||||
|
|
||||||
wpmdp = wpc->metadata;
|
wpmdp = wpc->metadata;
|
||||||
|
|
||||||
while (wpc->metacount) {
|
while (wpc->metacount) {
|
||||||
block_ptr = write_metadata (wpmdp, block_ptr);
|
block_ptr = write_metadata (wpmdp, block_ptr);
|
||||||
wpc->metabytes -= wpmdp->byte_length;
|
wpc->metabytes -= wpmdp->byte_length;
|
||||||
free_metadata (wpmdp++);
|
free_metadata (wpmdp++);
|
||||||
wpc->metacount--;
|
wpc->metacount--;
|
||||||
}
|
}
|
||||||
|
|
||||||
free (wpc->metadata);
|
free (wpc->metadata);
|
||||||
wpc->metadata = NULL;
|
wpc->metadata = NULL;
|
||||||
native_to_little_endian ((WavpackHeader *) block_buff, WavpackHeaderFormat);
|
native_to_little_endian ((WavpackHeader *) block_buff, WavpackHeaderFormat);
|
||||||
|
|
||||||
if (!wpc->blockout (wpc->wv_out, block_buff, block_size)) {
|
if (!wpc->blockout (wpc->wv_out, block_buff, block_size)) {
|
||||||
free (block_buff);
|
free (block_buff);
|
||||||
strcpy (wpc->error_message, "can't write WavPack data, disk probably full!");
|
strcpy (wpc->error_message, "can't write WavPack data, disk probably full!");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
free (block_buff);
|
free (block_buff);
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -307,7 +307,7 @@ int write_metadata_block (WavpackContext *wpc)
|
||||||
void free_metadata (WavpackMetadata *wpmd)
|
void free_metadata (WavpackMetadata *wpmd)
|
||||||
{
|
{
|
||||||
if (wpmd->data) {
|
if (wpmd->data) {
|
||||||
free (wpmd->data);
|
free (wpmd->data);
|
||||||
wpmd->data = NULL;
|
wpmd->data = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
#! /bin/sh
|
#! /bin/sh
|
||||||
# Common stub for a few missing GNU programs while installing.
|
# Common stub for a few missing GNU programs while installing.
|
||||||
|
|
||||||
scriptversion=2005-02-08.22
|
scriptversion=2006-05-10.23
|
||||||
|
|
||||||
# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005
|
# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006
|
||||||
# Free Software Foundation, Inc.
|
# Free Software Foundation, Inc.
|
||||||
# Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
|
# Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
|
||||||
|
|
||||||
|
@ -19,8 +19,8 @@ scriptversion=2005-02-08.22
|
||||||
|
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program; if not, write to the Free Software
|
# along with this program; if not, write to the Free Software
|
||||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||||
# 02111-1307, USA.
|
# 02110-1301, USA.
|
||||||
|
|
||||||
# As a special exception to the GNU General Public License, if you
|
# As a special exception to the GNU General Public License, if you
|
||||||
# distribute this file as part of a program that contains a
|
# distribute this file as part of a program that contains a
|
||||||
|
@ -33,6 +33,8 @@ if test $# -eq 0; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
run=:
|
run=:
|
||||||
|
sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p'
|
||||||
|
sed_minuso='s/.* -o \([^ ]*\).*/\1/p'
|
||||||
|
|
||||||
# In the cases where this matters, `missing' is being run in the
|
# In the cases where this matters, `missing' is being run in the
|
||||||
# srcdir already.
|
# srcdir already.
|
||||||
|
@ -44,7 +46,7 @@ fi
|
||||||
|
|
||||||
msg="missing on your system"
|
msg="missing on your system"
|
||||||
|
|
||||||
case "$1" in
|
case $1 in
|
||||||
--run)
|
--run)
|
||||||
# Try to run requested program, and just exit if it succeeds.
|
# Try to run requested program, and just exit if it succeeds.
|
||||||
run=
|
run=
|
||||||
|
@ -77,6 +79,7 @@ Supported PROGRAM values:
|
||||||
aclocal touch file \`aclocal.m4'
|
aclocal touch file \`aclocal.m4'
|
||||||
autoconf touch file \`configure'
|
autoconf touch file \`configure'
|
||||||
autoheader touch file \`config.h.in'
|
autoheader touch file \`config.h.in'
|
||||||
|
autom4te touch the output file, or create a stub one
|
||||||
automake touch all \`Makefile.in' files
|
automake touch all \`Makefile.in' files
|
||||||
bison create \`y.tab.[ch]', if possible, from existing .[ch]
|
bison create \`y.tab.[ch]', if possible, from existing .[ch]
|
||||||
flex create \`lex.yy.c', if possible, from existing .c
|
flex create \`lex.yy.c', if possible, from existing .c
|
||||||
|
@ -106,7 +109,7 @@ esac
|
||||||
# Now exit if we have it, but it failed. Also exit now if we
|
# Now exit if we have it, but it failed. Also exit now if we
|
||||||
# don't have it and --version was passed (most likely to detect
|
# don't have it and --version was passed (most likely to detect
|
||||||
# the program).
|
# the program).
|
||||||
case "$1" in
|
case $1 in
|
||||||
lex|yacc)
|
lex|yacc)
|
||||||
# Not GNU programs, they don't have --version.
|
# Not GNU programs, they don't have --version.
|
||||||
;;
|
;;
|
||||||
|
@ -135,7 +138,7 @@ esac
|
||||||
|
|
||||||
# If it does not exist, or fails to run (possibly an outdated version),
|
# If it does not exist, or fails to run (possibly an outdated version),
|
||||||
# try to emulate it.
|
# try to emulate it.
|
||||||
case "$1" in
|
case $1 in
|
||||||
aclocal*)
|
aclocal*)
|
||||||
echo 1>&2 "\
|
echo 1>&2 "\
|
||||||
WARNING: \`$1' is $msg. You should only need it if
|
WARNING: \`$1' is $msg. You should only need it if
|
||||||
|
@ -164,7 +167,7 @@ WARNING: \`$1' is $msg. You should only need it if
|
||||||
test -z "$files" && files="config.h"
|
test -z "$files" && files="config.h"
|
||||||
touch_files=
|
touch_files=
|
||||||
for f in $files; do
|
for f in $files; do
|
||||||
case "$f" in
|
case $f in
|
||||||
*:*) touch_files="$touch_files "`echo "$f" |
|
*:*) touch_files="$touch_files "`echo "$f" |
|
||||||
sed -e 's/^[^:]*://' -e 's/:.*//'`;;
|
sed -e 's/^[^:]*://' -e 's/:.*//'`;;
|
||||||
*) touch_files="$touch_files $f.in";;
|
*) touch_files="$touch_files $f.in";;
|
||||||
|
@ -192,8 +195,8 @@ WARNING: \`$1' is needed, but is $msg.
|
||||||
You can get \`$1' as part of \`Autoconf' from any GNU
|
You can get \`$1' as part of \`Autoconf' from any GNU
|
||||||
archive site."
|
archive site."
|
||||||
|
|
||||||
file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'`
|
file=`echo "$*" | sed -n "$sed_output"`
|
||||||
test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'`
|
test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
|
||||||
if test -f "$file"; then
|
if test -f "$file"; then
|
||||||
touch $file
|
touch $file
|
||||||
else
|
else
|
||||||
|
@ -214,25 +217,25 @@ WARNING: \`$1' $msg. You should only need it if
|
||||||
in order for those modifications to take effect. You can get
|
in order for those modifications to take effect. You can get
|
||||||
\`Bison' from any GNU archive site."
|
\`Bison' from any GNU archive site."
|
||||||
rm -f y.tab.c y.tab.h
|
rm -f y.tab.c y.tab.h
|
||||||
if [ $# -ne 1 ]; then
|
if test $# -ne 1; then
|
||||||
eval LASTARG="\${$#}"
|
eval LASTARG="\${$#}"
|
||||||
case "$LASTARG" in
|
case $LASTARG in
|
||||||
*.y)
|
*.y)
|
||||||
SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
|
SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
|
||||||
if [ -f "$SRCFILE" ]; then
|
if test -f "$SRCFILE"; then
|
||||||
cp "$SRCFILE" y.tab.c
|
cp "$SRCFILE" y.tab.c
|
||||||
fi
|
fi
|
||||||
SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
|
SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
|
||||||
if [ -f "$SRCFILE" ]; then
|
if test -f "$SRCFILE"; then
|
||||||
cp "$SRCFILE" y.tab.h
|
cp "$SRCFILE" y.tab.h
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
fi
|
fi
|
||||||
if [ ! -f y.tab.h ]; then
|
if test ! -f y.tab.h; then
|
||||||
echo >y.tab.h
|
echo >y.tab.h
|
||||||
fi
|
fi
|
||||||
if [ ! -f y.tab.c ]; then
|
if test ! -f y.tab.c; then
|
||||||
echo 'main() { return 0; }' >y.tab.c
|
echo 'main() { return 0; }' >y.tab.c
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
|
@ -244,18 +247,18 @@ WARNING: \`$1' is $msg. You should only need it if
|
||||||
in order for those modifications to take effect. You can get
|
in order for those modifications to take effect. You can get
|
||||||
\`Flex' from any GNU archive site."
|
\`Flex' from any GNU archive site."
|
||||||
rm -f lex.yy.c
|
rm -f lex.yy.c
|
||||||
if [ $# -ne 1 ]; then
|
if test $# -ne 1; then
|
||||||
eval LASTARG="\${$#}"
|
eval LASTARG="\${$#}"
|
||||||
case "$LASTARG" in
|
case $LASTARG in
|
||||||
*.l)
|
*.l)
|
||||||
SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
|
SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
|
||||||
if [ -f "$SRCFILE" ]; then
|
if test -f "$SRCFILE"; then
|
||||||
cp "$SRCFILE" lex.yy.c
|
cp "$SRCFILE" lex.yy.c
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
fi
|
fi
|
||||||
if [ ! -f lex.yy.c ]; then
|
if test ! -f lex.yy.c; then
|
||||||
echo 'main() { return 0; }' >lex.yy.c
|
echo 'main() { return 0; }' >lex.yy.c
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
|
@ -267,11 +270,9 @@ WARNING: \`$1' is $msg. You should only need it if
|
||||||
\`Help2man' package in order for those modifications to take
|
\`Help2man' package in order for those modifications to take
|
||||||
effect. You can get \`Help2man' from any GNU archive site."
|
effect. You can get \`Help2man' from any GNU archive site."
|
||||||
|
|
||||||
file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
|
file=`echo "$*" | sed -n "$sed_output"`
|
||||||
if test -z "$file"; then
|
test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
|
||||||
file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'`
|
if test -f "$file"; then
|
||||||
fi
|
|
||||||
if [ -f "$file" ]; then
|
|
||||||
touch $file
|
touch $file
|
||||||
else
|
else
|
||||||
test -z "$file" || exec >$file
|
test -z "$file" || exec >$file
|
||||||
|
@ -289,14 +290,23 @@ WARNING: \`$1' is $msg. You should only need it if
|
||||||
DU, IRIX). You might want to install the \`Texinfo' package or
|
DU, IRIX). You might want to install the \`Texinfo' package or
|
||||||
the \`GNU make' package. Grab either from any GNU archive site."
|
the \`GNU make' package. Grab either from any GNU archive site."
|
||||||
# The file to touch is that specified with -o ...
|
# The file to touch is that specified with -o ...
|
||||||
file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
|
file=`echo "$*" | sed -n "$sed_output"`
|
||||||
|
test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
|
||||||
if test -z "$file"; then
|
if test -z "$file"; then
|
||||||
# ... or it is the one specified with @setfilename ...
|
# ... or it is the one specified with @setfilename ...
|
||||||
infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
|
infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
|
||||||
file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $infile`
|
file=`sed -n '
|
||||||
|
/^@setfilename/{
|
||||||
|
s/.* \([^ ]*\) *$/\1/
|
||||||
|
p
|
||||||
|
q
|
||||||
|
}' $infile`
|
||||||
# ... or it is derived from the source name (dir/f.texi becomes f.info)
|
# ... or it is derived from the source name (dir/f.texi becomes f.info)
|
||||||
test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info
|
test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info
|
||||||
fi
|
fi
|
||||||
|
# If the file does not exist, the user really needs makeinfo;
|
||||||
|
# let's fail without touching anything.
|
||||||
|
test -f $file || exit 1
|
||||||
touch $file
|
touch $file
|
||||||
;;
|
;;
|
||||||
|
|
||||||
|
@ -314,13 +324,13 @@ WARNING: \`$1' is $msg. You should only need it if
|
||||||
fi
|
fi
|
||||||
firstarg="$1"
|
firstarg="$1"
|
||||||
if shift; then
|
if shift; then
|
||||||
case "$firstarg" in
|
case $firstarg in
|
||||||
*o*)
|
*o*)
|
||||||
firstarg=`echo "$firstarg" | sed s/o//`
|
firstarg=`echo "$firstarg" | sed s/o//`
|
||||||
tar "$firstarg" "$@" && exit 0
|
tar "$firstarg" "$@" && exit 0
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
case "$firstarg" in
|
case $firstarg in
|
||||||
*h*)
|
*h*)
|
||||||
firstarg=`echo "$firstarg" | sed s/h//`
|
firstarg=`echo "$firstarg" | sed s/h//`
|
||||||
tar "$firstarg" "$@" && exit 0
|
tar "$firstarg" "$@" && exit 0
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,7 +1,7 @@
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
// **** WAVPACK **** //
|
// **** WAVPACK **** //
|
||||||
// Hybrid Lossless Wavefile Compressor //
|
// Hybrid Lossless Wavefile Compressor //
|
||||||
// Copyright (c) 1998 - 2005 Conifer Software. //
|
// Copyright (c) 1998 - 2006 Conifer Software. //
|
||||||
// All Rights Reserved. //
|
// All Rights Reserved. //
|
||||||
// Distributed under the BSD Software License (see license.txt) //
|
// Distributed under the BSD Software License (see license.txt) //
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -12,9 +12,9 @@
|
||||||
// decoding old (versions 1, 2 & 3) WavPack files.
|
// decoding old (versions 1, 2 & 3) WavPack files.
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
ushort FormatTag, NumChannels;
|
unsigned short FormatTag, NumChannels;
|
||||||
uint32_t SampleRate, BytesPerSecond;
|
uint32_t SampleRate, BytesPerSecond;
|
||||||
ushort BlockAlign, BitsPerSample;
|
unsigned short BlockAlign, BitsPerSample;
|
||||||
} WaveHeader3;
|
} WaveHeader3;
|
||||||
|
|
||||||
#define WaveHeader3Format "SSLLSS"
|
#define WaveHeader3Format "SSLLSS"
|
||||||
|
@ -23,8 +23,8 @@ typedef struct {
|
||||||
char ckID [4];
|
char ckID [4];
|
||||||
int32_t ckSize;
|
int32_t ckSize;
|
||||||
short version;
|
short version;
|
||||||
short bits; // added for version 2.00
|
short bits; // added for version 2.00
|
||||||
short flags, shift; // added for version 3.00
|
short flags, shift; // added for version 3.00
|
||||||
int32_t total_samples, crc, crc2;
|
int32_t total_samples, crc, crc2;
|
||||||
char extension [4], extra_bc, extras [3];
|
char extension [4], extra_bc, extras [3];
|
||||||
} WavpackHeader3;
|
} WavpackHeader3;
|
||||||
|
@ -33,35 +33,35 @@ typedef struct {
|
||||||
|
|
||||||
// these flags added for version 3
|
// these flags added for version 3
|
||||||
|
|
||||||
#undef MONO_FLAG // these definitions changed for WavPack 4.0
|
#undef MONO_FLAG // these definitions changed for WavPack 4.0
|
||||||
#undef CROSS_DECORR
|
#undef CROSS_DECORR
|
||||||
#undef JOINT_STEREO
|
#undef JOINT_STEREO
|
||||||
|
|
||||||
#define MONO_FLAG 1 // not stereo
|
#define MONO_FLAG 1 // not stereo
|
||||||
#define FAST_FLAG 2 // non-adaptive predictor and stereo mode
|
#define FAST_FLAG 2 // non-adaptive predictor and stereo mode
|
||||||
#define RAW_FLAG 4 // raw mode (no .wav header)
|
#define RAW_FLAG 4 // raw mode (no .wav header)
|
||||||
#define CALC_NOISE 8 // calc noise in lossy mode (no longer stored)
|
#define CALC_NOISE 8 // calc noise in lossy mode (no longer stored)
|
||||||
#define HIGH_FLAG 0x10 // high quality mode (all modes)
|
#define HIGH_FLAG 0x10 // high quality mode (all modes)
|
||||||
#define BYTES_3 0x20 // files have 3-byte samples
|
#define BYTES_3 0x20 // files have 3-byte samples
|
||||||
#define OVER_20 0x40 // samples are over 20 bits
|
#define OVER_20 0x40 // samples are over 20 bits
|
||||||
#define WVC_FLAG 0x80 // create/use .wvc (no longer stored)
|
#define WVC_FLAG 0x80 // create/use .wvc (no longer stored)
|
||||||
#define LOSSY_SHAPE 0x100 // noise shape (lossy mode only)
|
#define LOSSY_SHAPE 0x100 // noise shape (lossy mode only)
|
||||||
#define VERY_FAST_FLAG 0x200 // double fast (no longer stored)
|
#define VERY_FAST_FLAG 0x200 // double fast (no longer stored)
|
||||||
#define NEW_HIGH_FLAG 0x400 // new high quality mode (lossless only)
|
#define NEW_HIGH_FLAG 0x400 // new high quality mode (lossless only)
|
||||||
#define CANCEL_EXTREME 0x800 // cancel EXTREME_DECORR
|
#define CANCEL_EXTREME 0x800 // cancel EXTREME_DECORR
|
||||||
#define CROSS_DECORR 0x1000 // decorrelate chans (with EXTREME_DECORR flag)
|
#define CROSS_DECORR 0x1000 // decorrelate chans (with EXTREME_DECORR flag)
|
||||||
#define NEW_DECORR_FLAG 0x2000 // new high-mode decorrelator
|
#define NEW_DECORR_FLAG 0x2000 // new high-mode decorrelator
|
||||||
#define JOINT_STEREO 0x4000 // joint stereo (lossy and high lossless)
|
#define JOINT_STEREO 0x4000 // joint stereo (lossy and high lossless)
|
||||||
#define EXTREME_DECORR 0x8000 // extra decorrelation (+ enables other flags)
|
#define EXTREME_DECORR 0x8000 // extra decorrelation (+ enables other flags)
|
||||||
|
|
||||||
#define STORED_FLAGS 0xfd77 // these are only flags that affect unpacking
|
#define STORED_FLAGS 0xfd77 // these are only flags that affect unpacking
|
||||||
#define NOT_STORED_FLAGS (~STORED_FLAGS & 0xffff)
|
#define NOT_STORED_FLAGS (~STORED_FLAGS & 0xffff)
|
||||||
|
|
||||||
// BitStream stuff (bits.c)
|
// BitStream stuff (bits.c)
|
||||||
|
|
||||||
typedef struct bs3 {
|
typedef struct bs3 {
|
||||||
void (*wrap)(struct bs3 *bs);
|
void (*wrap)(struct bs3 *bs);
|
||||||
uchar *buf, *end, *ptr;
|
unsigned char *buf, *end, *ptr;
|
||||||
uint32_t bufsiz, fpos, sr;
|
uint32_t bufsiz, fpos, sr;
|
||||||
WavpackStreamReader *reader;
|
WavpackStreamReader *reader;
|
||||||
int error, bc;
|
int error, bc;
|
||||||
|
@ -77,29 +77,29 @@ typedef struct {
|
||||||
uint32_t sample_index;
|
uint32_t sample_index;
|
||||||
int num_terms;
|
int num_terms;
|
||||||
|
|
||||||
#ifdef SEEKING
|
#ifndef NO_SEEKING
|
||||||
struct index_point {
|
struct index_point {
|
||||||
char saved;
|
char saved;
|
||||||
uint32_t sample_index;
|
uint32_t sample_index;
|
||||||
} index_points [256];
|
} index_points [256];
|
||||||
|
|
||||||
uchar *unpack_data;
|
unsigned char *unpack_data;
|
||||||
uint32_t unpack_size;
|
uint32_t unpack_size;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
int32_t sum_level, left_level, right_level, diff_level;
|
int32_t sum_level, left_level, right_level, diff_level;
|
||||||
int last_extra_bits, extra_bits_count, m;
|
int last_extra_bits, extra_bits_count, m;
|
||||||
int32_t error [2], crc;
|
int32_t error [2], crc;
|
||||||
int32_t sample [2] [2];
|
int32_t sample [2] [2];
|
||||||
int weight [2] [1];
|
int weight [2] [1];
|
||||||
} dc;
|
} dc;
|
||||||
|
|
||||||
struct decorr_pass decorr_passes [MAX_NTERMS3];
|
struct decorr_pass decorr_passes [MAX_NTERMS3];
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
uint index [2], k_value [2], ave_k [2];
|
unsigned int index [2], k_value [2], ave_k [2];
|
||||||
uint32_t zeros_acc, ave_level [K_DEPTH] [2];
|
uint32_t zeros_acc, ave_level [K_DEPTH] [2];
|
||||||
} w1;
|
} w1;
|
||||||
|
|
||||||
struct { int last_dbits [2], last_delta_sign [2], bit_limit; } w2;
|
struct { int last_dbits [2], last_delta_sign [2], bit_limit; } w2;
|
||||||
|
@ -107,7 +107,7 @@ typedef struct {
|
||||||
struct { int ave_dbits [2], bit_limit; } w3;
|
struct { int ave_dbits [2], bit_limit; } w3;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
uint32_t fast_level [2], slow_level [2];
|
uint32_t fast_level [2], slow_level [2];
|
||||||
int bits_acc [2], bitrate;
|
int bits_acc [2], bitrate;
|
||||||
} w4;
|
} w4;
|
||||||
} WavpackStream3;
|
} WavpackStream3;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
// **** WAVPACK **** //
|
// **** WAVPACK **** //
|
||||||
// Hybrid Lossless Wavefile Compressor //
|
// Hybrid Lossless Wavefile Compressor //
|
||||||
// Copyright (c) 1998 - 2005 Conifer Software. //
|
// Copyright (c) 1998 - 2006 Conifer Software. //
|
||||||
// All Rights Reserved. //
|
// All Rights Reserved. //
|
||||||
// Distributed under the BSD Software License (see license.txt) //
|
// Distributed under the BSD Software License (see license.txt) //
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -16,17 +16,25 @@
|
||||||
#include <io.h>
|
#include <io.h>
|
||||||
#include <conio.h>
|
#include <conio.h>
|
||||||
#include <shlobj.h>
|
#include <shlobj.h>
|
||||||
#elif defined(__GNUC__)
|
#elif defined(__GNUC__) || defined(__sun)
|
||||||
#include <glob.h>
|
#include <glob.h>
|
||||||
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "wavpack.h"
|
#include "wavpack.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#define fileno _fileno
|
||||||
|
#define stat64 __stat64
|
||||||
|
#define fstat64 _fstat64
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
|
|
||||||
|
@ -37,24 +45,24 @@ int copy_timestamp (const char *src_filename, const char *dst_filename)
|
||||||
int res = TRUE;
|
int res = TRUE;
|
||||||
|
|
||||||
if (*src_filename == '-' || *dst_filename == '-')
|
if (*src_filename == '-' || *dst_filename == '-')
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
src = CreateFile (src_filename, GENERIC_READ, FILE_SHARE_READ, NULL,
|
src = CreateFile (src_filename, GENERIC_READ, FILE_SHARE_READ, NULL,
|
||||||
OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
|
OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
|
||||||
|
|
||||||
dst = CreateFile (dst_filename, GENERIC_WRITE, FILE_SHARE_WRITE, NULL,
|
dst = CreateFile (dst_filename, GENERIC_WRITE, FILE_SHARE_WRITE, NULL,
|
||||||
OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
|
OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
|
||||||
|
|
||||||
if (src == INVALID_HANDLE_VALUE || dst == INVALID_HANDLE_VALUE ||
|
if (src == INVALID_HANDLE_VALUE || dst == INVALID_HANDLE_VALUE ||
|
||||||
!GetFileTime (src, NULL, NULL, &last_modified) ||
|
!GetFileTime (src, NULL, NULL, &last_modified) ||
|
||||||
!SetFileTime (dst, NULL, NULL, &last_modified))
|
!SetFileTime (dst, NULL, NULL, &last_modified))
|
||||||
res = FALSE;
|
res = FALSE;
|
||||||
|
|
||||||
if (src != INVALID_HANDLE_VALUE)
|
if (src != INVALID_HANDLE_VALUE)
|
||||||
CloseHandle (src);
|
CloseHandle (src);
|
||||||
|
|
||||||
if (dst != INVALID_HANDLE_VALUE)
|
if (dst != INVALID_HANDLE_VALUE)
|
||||||
CloseHandle (dst);
|
CloseHandle (dst);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -106,18 +114,18 @@ char *filespec_ext (char *filespec)
|
||||||
|
|
||||||
while (--cp >= filespec) {
|
while (--cp >= filespec) {
|
||||||
|
|
||||||
if (langid == 0x411 && is_second_byte (filespec, cp))
|
if (langid == 0x411 && is_second_byte (filespec, cp))
|
||||||
--cp;
|
--cp;
|
||||||
|
|
||||||
if (*cp == '\\' || *cp == ':')
|
if (*cp == '\\' || *cp == ':')
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (*cp == '.') {
|
if (*cp == '.') {
|
||||||
if (strlen (cp) > 1 && strlen (cp) <= 4)
|
if (strlen (cp) > 1 && strlen (cp) <= 4)
|
||||||
return cp;
|
return cp;
|
||||||
else
|
else
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -131,15 +139,15 @@ char *filespec_ext (char *filespec)
|
||||||
|
|
||||||
while (--cp >= filespec) {
|
while (--cp >= filespec) {
|
||||||
|
|
||||||
if (*cp == '/' || *cp == ':')
|
if (*cp == '/' || *cp == ':')
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (*cp == '.') {
|
if (*cp == '.') {
|
||||||
if (strlen (cp) > 1 && strlen (cp) <= 4)
|
if (strlen (cp) > 1 && strlen (cp) <= 4)
|
||||||
return cp;
|
return cp;
|
||||||
else
|
else
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -156,7 +164,7 @@ char *filespec_ext (char *filespec)
|
||||||
// returned. //
|
// returned. //
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#if defined(__GNUC__) && !defined(WIN32)
|
#if (defined(__GNUC__) || defined(__sun)) && !defined(WIN32)
|
||||||
|
|
||||||
char *filespec_path (char *filespec)
|
char *filespec_path (char *filespec)
|
||||||
{
|
{
|
||||||
|
@ -165,24 +173,24 @@ char *filespec_path (char *filespec)
|
||||||
struct stat fstats;
|
struct stat fstats;
|
||||||
|
|
||||||
if (cp == filespec || filespec_wild (filespec))
|
if (cp == filespec || filespec_wild (filespec))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (*--cp == '/' || *cp == ':')
|
if (*--cp == '/' || *cp == ':')
|
||||||
return filespec;
|
return filespec;
|
||||||
|
|
||||||
if (*cp == '.' && cp == filespec)
|
if (*cp == '.' && cp == filespec)
|
||||||
return strcat (filespec, "/");
|
return strcat (filespec, "/");
|
||||||
|
|
||||||
if (glob (filespec, GLOB_MARK|GLOB_NOSORT, NULL, &globs) == 0 &&
|
if (glob (filespec, GLOB_MARK|GLOB_NOSORT, NULL, &globs) == 0 &&
|
||||||
globs.gl_pathc > 0)
|
globs.gl_pathc > 0)
|
||||||
{
|
{
|
||||||
/* test if the file is a directory */
|
/* test if the file is a directory */
|
||||||
if (stat(globs.gl_pathv[0], &fstats) == 0 && (fstats.st_mode & S_IFDIR)) {
|
if (stat(globs.gl_pathv[0], &fstats) == 0 && (fstats.st_mode & S_IFDIR)) {
|
||||||
filespec[0] = '\0';
|
filespec[0] = '\0';
|
||||||
strcat (filespec, globs.gl_pathv[0]);
|
strcat (filespec, globs.gl_pathv[0]);
|
||||||
globfree(&globs);
|
globfree(&globs);
|
||||||
return filespec;
|
return filespec;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
globfree(&globs);
|
globfree(&globs);
|
||||||
|
|
||||||
|
@ -196,29 +204,29 @@ char *filespec_path (char *filespec)
|
||||||
char *cp = filespec + strlen (filespec);
|
char *cp = filespec + strlen (filespec);
|
||||||
LANGID langid = GetSystemDefaultLangID ();
|
LANGID langid = GetSystemDefaultLangID ();
|
||||||
struct _finddata_t finddata;
|
struct _finddata_t finddata;
|
||||||
int32_t file;
|
intptr_t file;
|
||||||
|
|
||||||
if (cp == filespec || filespec_wild (filespec))
|
if (cp == filespec || filespec_wild (filespec))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
--cp;
|
--cp;
|
||||||
|
|
||||||
if (langid == 0x411 && is_second_byte (filespec, cp))
|
if (langid == 0x411 && is_second_byte (filespec, cp))
|
||||||
--cp;
|
--cp;
|
||||||
|
|
||||||
if (*cp == '\\' || *cp == ':')
|
if (*cp == '\\' || *cp == ':')
|
||||||
return filespec;
|
return filespec;
|
||||||
|
|
||||||
if (*cp == '.' && cp == filespec)
|
if (*cp == '.' && cp == filespec)
|
||||||
return strcat (filespec, "\\");
|
return strcat (filespec, "\\");
|
||||||
|
|
||||||
if ((file = _findfirst (filespec, &finddata)) != -1L &&
|
if ((file = _findfirst (filespec, &finddata)) != (intptr_t) -1 &&
|
||||||
(finddata.attrib & _A_SUBDIR)) {
|
(finddata.attrib & _A_SUBDIR)) {
|
||||||
_findclose (file);
|
_findclose (file);
|
||||||
return strcat (filespec, "\\");
|
return strcat (filespec, "\\");
|
||||||
}
|
}
|
||||||
if (file != -1L)
|
if (file != -1L)
|
||||||
_findclose(file);
|
_findclose(file);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -248,17 +256,17 @@ char *filespec_name (char *filespec)
|
||||||
LANGID langid = GetSystemDefaultLangID ();
|
LANGID langid = GetSystemDefaultLangID ();
|
||||||
|
|
||||||
while (--cp >= filespec) {
|
while (--cp >= filespec) {
|
||||||
if (langid == 0x411 && is_second_byte (filespec, cp))
|
if (langid == 0x411 && is_second_byte (filespec, cp))
|
||||||
--cp;
|
--cp;
|
||||||
|
|
||||||
if (*cp == '\\' || *cp == ':')
|
if (*cp == '\\' || *cp == ':')
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strlen (cp + 1))
|
if (strlen (cp + 1))
|
||||||
return cp + 1;
|
return cp + 1;
|
||||||
else
|
else
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
@ -268,13 +276,13 @@ char *filespec_name (char *filespec)
|
||||||
char *cp = filespec + strlen (filespec);
|
char *cp = filespec + strlen (filespec);
|
||||||
|
|
||||||
while (--cp >= filespec)
|
while (--cp >= filespec)
|
||||||
if (*cp == '/' || *cp == ':')
|
if (*cp == '/' || *cp == ':')
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (strlen (cp + 1))
|
if (strlen (cp + 1))
|
||||||
return cp + 1;
|
return cp + 1;
|
||||||
else
|
else
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -289,13 +297,13 @@ char *filespec_name (char *filespec)
|
||||||
|
|
||||||
static int is_second_byte (char *filespec, char *pos)
|
static int is_second_byte (char *filespec, char *pos)
|
||||||
{
|
{
|
||||||
uchar *cp = pos;
|
unsigned char *cp = pos;
|
||||||
|
|
||||||
while (cp > filespec && ((cp [-1] >= 0x81 && cp [-1] <= 0x9f) ||
|
while (cp > filespec && ((cp [-1] >= 0x81 && cp [-1] <= 0x9f) ||
|
||||||
(cp [-1] >= 0xe0 && cp [-1] <= 0xfc)))
|
(cp [-1] >= 0xe0 && cp [-1] <= 0xfc)))
|
||||||
cp--;
|
cp--;
|
||||||
|
|
||||||
return ((int) pos - (int) cp) & 1;
|
return (int)((unsigned char *)pos - cp) & 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -317,36 +325,42 @@ char yna (void)
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
#if defined(WIN32)
|
#if defined(WIN32)
|
||||||
key = getch ();
|
key = _getch ();
|
||||||
#else
|
#else
|
||||||
key = fgetc(stdin);
|
key = fgetc(stdin);
|
||||||
#endif
|
#endif
|
||||||
if (key == 3) {
|
if (key == 3) {
|
||||||
fprintf (stderr, "^C\n");
|
fprintf (stderr, "^C\n");
|
||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
else if (key == '\r' || key == '\n') {
|
else if (key == '\r' || key == '\n') {
|
||||||
if (choice) {
|
if (choice) {
|
||||||
fprintf (stderr, "\r\n");
|
fprintf (stderr, "\r\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
fprintf (stderr, "%c", 7);
|
fprintf (stderr, "%c", 7);
|
||||||
}
|
}
|
||||||
else if (key == 'Y' || key == 'y') {
|
else if (key == 'Y' || key == 'y') {
|
||||||
fprintf (stderr, "%c\b", key);
|
#ifdef WIN32
|
||||||
choice = 'y';
|
fprintf (stderr, "%c\b", key);
|
||||||
}
|
#endif
|
||||||
else if (key == 'N' || key == 'n') {
|
choice = 'y';
|
||||||
fprintf (stderr, "%c\b", key);
|
}
|
||||||
choice = 'n';
|
else if (key == 'N' || key == 'n') {
|
||||||
}
|
#ifdef WIN32
|
||||||
else if (key == 'A' || key == 'a') {
|
fprintf (stderr, "%c\b", key);
|
||||||
fprintf (stderr, "%c\b", key);
|
#endif
|
||||||
choice = 'a';
|
choice = 'n';
|
||||||
}
|
}
|
||||||
else
|
else if (key == 'A' || key == 'a') {
|
||||||
fprintf (stderr, "%c", 7);
|
#ifdef WIN32
|
||||||
|
fprintf (stderr, "%c\b", key);
|
||||||
|
#endif
|
||||||
|
choice = 'a';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
fprintf (stderr, "%c", 7);
|
||||||
}
|
}
|
||||||
|
|
||||||
waiting_input = 0;
|
waiting_input = 0;
|
||||||
|
@ -361,7 +375,7 @@ char yna (void)
|
||||||
// with printf strings and args. //
|
// with printf strings and args. //
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
int debug_logging_mode = FALSE;
|
extern int debug_logging_mode;
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
|
|
||||||
|
@ -373,46 +387,46 @@ int get_app_path (char *app_path)
|
||||||
FARPROC ProcAdd;
|
FARPROC ProcAdd;
|
||||||
|
|
||||||
if (tried) {
|
if (tried) {
|
||||||
if (result)
|
if (result)
|
||||||
strcpy (app_path, file_path);
|
strcpy (app_path, file_path);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
tried = TRUE;
|
tried = TRUE;
|
||||||
hinstLib = LoadLibrary ("shell32.dll");
|
hinstLib = LoadLibrary ("shell32.dll");
|
||||||
|
|
||||||
if (hinstLib) {
|
if (hinstLib) {
|
||||||
ProcAdd = GetProcAddress (hinstLib, "SHGetFolderPathA");
|
ProcAdd = GetProcAddress (hinstLib, "SHGetFolderPathA");
|
||||||
|
|
||||||
if (ProcAdd && SUCCEEDED ((ProcAdd) (NULL, CSIDL_APPDATA | 0x8000, NULL, 0, file_path)))
|
if (ProcAdd && SUCCEEDED ((ProcAdd) (NULL, CSIDL_APPDATA | 0x8000, NULL, 0, file_path)))
|
||||||
result = TRUE;
|
result = TRUE;
|
||||||
|
|
||||||
if (!result) {
|
if (!result) {
|
||||||
ProcAdd = GetProcAddress (hinstLib, "SHGetSpecialFolderPathA");
|
ProcAdd = GetProcAddress (hinstLib, "SHGetSpecialFolderPathA");
|
||||||
|
|
||||||
if (ProcAdd && SUCCEEDED ((ProcAdd) (NULL, file_path, CSIDL_APPDATA, TRUE)))
|
if (ProcAdd && SUCCEEDED ((ProcAdd) (NULL, file_path, CSIDL_APPDATA, TRUE)))
|
||||||
result = TRUE;
|
result = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
FreeLibrary (hinstLib);
|
FreeLibrary (hinstLib);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!result) {
|
if (!result) {
|
||||||
hinstLib = LoadLibrary ("shfolder.dll");
|
hinstLib = LoadLibrary ("shfolder.dll");
|
||||||
|
|
||||||
if (hinstLib) {
|
if (hinstLib) {
|
||||||
ProcAdd = GetProcAddress (hinstLib, "SHGetFolderPathA");
|
ProcAdd = GetProcAddress (hinstLib, "SHGetFolderPathA");
|
||||||
|
|
||||||
if (ProcAdd && SUCCEEDED ((ProcAdd) (NULL, CSIDL_APPDATA | 0x8000, NULL, 0, file_path)))
|
if (ProcAdd && SUCCEEDED ((ProcAdd) (NULL, CSIDL_APPDATA | 0x8000, NULL, 0, file_path)))
|
||||||
result = TRUE;
|
result = TRUE;
|
||||||
|
|
||||||
FreeLibrary (hinstLib);
|
FreeLibrary (hinstLib);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result)
|
if (result)
|
||||||
strcpy (app_path, file_path);
|
strcpy (app_path, file_path);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -430,32 +444,32 @@ void error_line (char *error, ...)
|
||||||
finish_line ();
|
finish_line ();
|
||||||
|
|
||||||
if (debug_logging_mode) {
|
if (debug_logging_mode) {
|
||||||
char file_path [MAX_PATH];
|
char file_path [MAX_PATH];
|
||||||
FILE *error_log = NULL;
|
FILE *error_log = NULL;
|
||||||
|
|
||||||
if (get_app_path (file_path)) {
|
if (get_app_path (file_path)) {
|
||||||
strcat (file_path, "\\WavPack\\wavpack.log");
|
strcat (file_path, "\\WavPack\\wavpack.log");
|
||||||
error_log = fopen (file_path, "a+");
|
error_log = fopen (file_path, "a+");
|
||||||
|
|
||||||
if (!error_log) {
|
if (!error_log) {
|
||||||
get_app_path (file_path);
|
get_app_path (file_path);
|
||||||
strcat (file_path, "\\WavPack");
|
strcat (file_path, "\\WavPack");
|
||||||
|
|
||||||
if (CreateDirectory (file_path, NULL)) {
|
if (CreateDirectory (file_path, NULL)) {
|
||||||
strcat (file_path, "\\wavpack.log");
|
strcat (file_path, "\\wavpack.log");
|
||||||
error_log = fopen (file_path, "a+");
|
error_log = fopen (file_path, "a+");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!error_log)
|
if (!error_log)
|
||||||
error_log = fopen ("c:\\wavpack.log", "a+");
|
error_log = fopen ("c:\\wavpack.log", "a+");
|
||||||
|
|
||||||
if (error_log) {
|
if (error_log) {
|
||||||
fputs (error_msg + 1, error_log);
|
fputs (error_msg + 1, error_log);
|
||||||
fputc ('\n', error_log);
|
fputc ('\n', error_log);
|
||||||
fclose (error_log);
|
fclose (error_log);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -482,7 +496,7 @@ void debug_line (char *error, ...)
|
||||||
va_list argptr;
|
va_list argptr;
|
||||||
|
|
||||||
if (!debug_logging_mode)
|
if (!debug_logging_mode)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
error_msg [0] = '\r';
|
error_msg [0] = '\r';
|
||||||
va_start (argptr, error);
|
va_start (argptr, error);
|
||||||
|
@ -492,13 +506,13 @@ void debug_line (char *error, ...)
|
||||||
finish_line ();
|
finish_line ();
|
||||||
|
|
||||||
if (debug_logging_mode) {
|
if (debug_logging_mode) {
|
||||||
FILE *error_log = fopen ("c:\\wavpack.log", "a+");
|
FILE *error_log = fopen ("c:\\wavpack.log", "a+");
|
||||||
|
|
||||||
if (error_log) {
|
if (error_log) {
|
||||||
fputs (error_msg + 1, error_log);
|
fputs (error_msg + 1, error_log);
|
||||||
fputc ('\n', error_log);
|
fputc ('\n', error_log);
|
||||||
fclose (error_log);
|
fclose (error_log);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -511,19 +525,19 @@ static int break_flag;
|
||||||
BOOL WINAPI ctrl_handler (DWORD ctrl)
|
BOOL WINAPI ctrl_handler (DWORD ctrl)
|
||||||
{
|
{
|
||||||
if (ctrl == CTRL_C_EVENT) {
|
if (ctrl == CTRL_C_EVENT) {
|
||||||
break_flag = TRUE;
|
break_flag = TRUE;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctrl == CTRL_BREAK_EVENT) {
|
if (ctrl == CTRL_BREAK_EVENT) {
|
||||||
|
|
||||||
if (waiting_input) {
|
if (waiting_input) {
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
break_flag = TRUE;
|
break_flag = TRUE;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -563,13 +577,13 @@ void finish_line (void)
|
||||||
CONSOLE_SCREEN_BUFFER_INFO coninfo;
|
CONSOLE_SCREEN_BUFFER_INFO coninfo;
|
||||||
|
|
||||||
if (hConIn && GetConsoleScreenBufferInfo (hConIn, &coninfo)) {
|
if (hConIn && GetConsoleScreenBufferInfo (hConIn, &coninfo)) {
|
||||||
unsigned char spaces = coninfo.dwSize.X - coninfo.dwCursorPosition.X;
|
unsigned char spaces = coninfo.dwSize.X - coninfo.dwCursorPosition.X;
|
||||||
|
|
||||||
while (spaces--)
|
while (spaces--)
|
||||||
fputc (' ', stderr);
|
fputc (' ', stderr);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
fputc ('\n', stderr);
|
fputc ('\n', stderr);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -610,14 +624,14 @@ int DoReadFile (FILE *hFile, void *lpBuffer, uint32_t nNumberOfBytesToRead, uint
|
||||||
*lpNumberOfBytesRead = 0;
|
*lpNumberOfBytesRead = 0;
|
||||||
|
|
||||||
while (nNumberOfBytesToRead) {
|
while (nNumberOfBytesToRead) {
|
||||||
bcount = fread ((uchar *) lpBuffer + *lpNumberOfBytesRead, 1, nNumberOfBytesToRead, hFile);
|
bcount = (uint32_t) fread ((unsigned char *) lpBuffer + *lpNumberOfBytesRead, 1, nNumberOfBytesToRead, hFile);
|
||||||
|
|
||||||
if (bcount) {
|
if (bcount) {
|
||||||
*lpNumberOfBytesRead += bcount;
|
*lpNumberOfBytesRead += bcount;
|
||||||
nNumberOfBytesToRead -= bcount;
|
nNumberOfBytesToRead -= bcount;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return !ferror (hFile);
|
return !ferror (hFile);
|
||||||
|
@ -630,29 +644,45 @@ int DoWriteFile (FILE *hFile, void *lpBuffer, uint32_t nNumberOfBytesToWrite, ui
|
||||||
*lpNumberOfBytesWritten = 0;
|
*lpNumberOfBytesWritten = 0;
|
||||||
|
|
||||||
while (nNumberOfBytesToWrite) {
|
while (nNumberOfBytesToWrite) {
|
||||||
bcount = fwrite ((uchar *) lpBuffer + *lpNumberOfBytesWritten, 1, nNumberOfBytesToWrite, hFile);
|
bcount = (uint32_t) fwrite ((unsigned char *) lpBuffer + *lpNumberOfBytesWritten, 1, nNumberOfBytesToWrite, hFile);
|
||||||
|
|
||||||
if (bcount) {
|
if (bcount) {
|
||||||
*lpNumberOfBytesWritten += bcount;
|
*lpNumberOfBytesWritten += bcount;
|
||||||
nNumberOfBytesToWrite -= bcount;
|
nNumberOfBytesToWrite -= bcount;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return !ferror (hFile);
|
return !ferror (hFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t DoGetFileSize (FILE *hFile)
|
#ifdef WIN32
|
||||||
|
|
||||||
|
int64_t DoGetFileSize (FILE *hFile)
|
||||||
|
{
|
||||||
|
struct stat64 statbuf;
|
||||||
|
|
||||||
|
if (!hFile || fstat64 (fileno (hFile), &statbuf) || !(statbuf.st_mode & S_IFREG))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return statbuf.st_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
int64_t DoGetFileSize (FILE *hFile)
|
||||||
{
|
{
|
||||||
struct stat statbuf;
|
struct stat statbuf;
|
||||||
|
|
||||||
if (!hFile || fstat (fileno (hFile), &statbuf) || !(statbuf.st_mode & S_IFREG))
|
if (!hFile || fstat (fileno (hFile), &statbuf) || !(statbuf.st_mode & S_IFREG))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return statbuf.st_size;
|
return (int64_t) statbuf.st_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
uint32_t DoGetFilePosition (FILE *hFile)
|
uint32_t DoGetFilePosition (FILE *hFile)
|
||||||
{
|
{
|
||||||
return ftell (hFile);
|
return ftell (hFile);
|
||||||
|
@ -684,11 +714,11 @@ int DoCloseHandle (FILE *hFile)
|
||||||
int DoTruncateFile (FILE *hFile)
|
int DoTruncateFile (FILE *hFile)
|
||||||
{
|
{
|
||||||
if (hFile) {
|
if (hFile) {
|
||||||
fflush (hFile);
|
fflush (hFile);
|
||||||
#if defined(WIN32)
|
#if defined(WIN32)
|
||||||
return !chsize (fileno (hFile), 0);
|
return !_chsize (_fileno (hFile), 0);
|
||||||
#else
|
#else
|
||||||
return !ftruncate(fileno (hFile), 0);
|
return !ftruncate(fileno (hFile), 0);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,7 +1,7 @@
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
// **** WAVPACK **** //
|
// **** WAVPACK **** //
|
||||||
// Hybrid Lossless Wavefile Compressor //
|
// Hybrid Lossless Wavefile Compressor //
|
||||||
// Copyright (c) 1998 - 2005 Conifer Software. //
|
// Copyright (c) 1998 - 2006 Conifer Software. //
|
||||||
// All Rights Reserved. //
|
// All Rights Reserved. //
|
||||||
// Distributed under the BSD Software License (see license.txt) //
|
// Distributed under the BSD Software License (see license.txt) //
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -11,17 +11,11 @@
|
||||||
#ifndef WAVPACK_H
|
#ifndef WAVPACK_H
|
||||||
#define WAVPACK_H
|
#define WAVPACK_H
|
||||||
|
|
||||||
#if defined(WIN32)
|
// This header file contains all the definitions required to use the
|
||||||
#define FASTCALL __fastcall
|
// functions in "wputils.c" to read and write WavPack files and streams.
|
||||||
#else
|
|
||||||
#define FASTCALL
|
|
||||||
#define SetConsoleTitle(x)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
// This header file contains all the definitions required by WavPack.
|
|
||||||
|
|
||||||
#if defined(_WIN32) && !defined(__MINGW32__)
|
#if defined(_WIN32) && !defined(__MINGW32__)
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
typedef unsigned __int64 uint64_t;
|
typedef unsigned __int64 uint64_t;
|
||||||
|
@ -37,70 +31,10 @@ typedef float float32_t;
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef unsigned char uchar;
|
|
||||||
|
|
||||||
#if !defined(__GNUC__) || defined(WIN32)
|
|
||||||
typedef unsigned short ushort;
|
|
||||||
typedef unsigned int uint;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef PATH_MAX
|
|
||||||
#ifdef MAX_PATH
|
|
||||||
#define PATH_MAX MAX_PATH
|
|
||||||
#elif defined (MAXPATHLEN)
|
|
||||||
#define PATH_MAX MAXPATHLEN
|
|
||||||
#else
|
|
||||||
#define PATH_MAX 1024
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// This structure is used to access the individual fields of 32-bit ieee
|
|
||||||
// floating point numbers. This will not be compatible with compilers that
|
|
||||||
// allocate bit fields from the most significant bits, although I'm not sure
|
|
||||||
// how common that is.
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
unsigned mantissa : 23;
|
|
||||||
unsigned exponent : 8;
|
|
||||||
unsigned sign : 1;
|
|
||||||
} f32;
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#define FALSE 0
|
|
||||||
#define TRUE 1
|
|
||||||
|
|
||||||
#if defined(WIN32)
|
|
||||||
#undef VERSION_OS
|
|
||||||
#define VERSION_OS "Win32"
|
|
||||||
#endif
|
|
||||||
#define VERSION_STR "4.32"
|
|
||||||
#define DATE_STR "2006-04-05"
|
|
||||||
|
|
||||||
// ID3v1 and APEv2 TAG formats (may occur at the end of WavPack files)
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uchar tag_id [3], title [30], artist [30], album [30];
|
|
||||||
uchar year [4], comment [30], genre;
|
|
||||||
} ID3_Tag;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char ID [8];
|
|
||||||
int32_t version, length, item_count, flags;
|
|
||||||
char res [8];
|
|
||||||
} APE_Tag_Hdr;
|
|
||||||
|
|
||||||
#define APE_Tag_Hdr_Format "8LLLL"
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int32_t tag_file_pos;
|
|
||||||
ID3_Tag id3_tag;
|
|
||||||
APE_Tag_Hdr ape_tag_hdr;
|
|
||||||
char *ape_tag_data;
|
|
||||||
} M_Tag;
|
|
||||||
|
|
||||||
// RIFF / wav header formats (these occur at the beginning of both wav files
|
// 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)
|
// and pre-4.0 WavPack files that are not in the "raw" mode). Generally, an
|
||||||
|
// application using the library to read or write WavPack files will not be
|
||||||
|
// concerned with any of these.
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char ckID [4];
|
char ckID [4];
|
||||||
|
@ -116,114 +50,105 @@ typedef struct {
|
||||||
#define ChunkHeaderFormat "4L"
|
#define ChunkHeaderFormat "4L"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
ushort FormatTag, NumChannels;
|
unsigned short FormatTag, NumChannels;
|
||||||
uint32_t SampleRate, BytesPerSecond;
|
uint32_t SampleRate, BytesPerSecond;
|
||||||
ushort BlockAlign, BitsPerSample;
|
unsigned short BlockAlign, BitsPerSample;
|
||||||
ushort cbSize, ValidBitsPerSample;
|
unsigned short cbSize, ValidBitsPerSample;
|
||||||
int32_t ChannelMask;
|
int32_t ChannelMask;
|
||||||
ushort SubFormat;
|
unsigned short SubFormat;
|
||||||
char GUID [14];
|
char GUID [14];
|
||||||
} WaveHeader;
|
} WaveHeader;
|
||||||
|
|
||||||
#define WaveHeaderFormat "SSLLSSSSLS"
|
#define WaveHeaderFormat "SSLLSSSSLS"
|
||||||
|
|
||||||
////////////////////////////// WavPack Header /////////////////////////////////
|
// This is the ONLY structure that occurs in WavPack files (as of version
|
||||||
|
// 4.0), and is the preamble to every block in both the .wv and .wvc
|
||||||
// Note that this is the ONLY structure that is written to (or read from)
|
// files (in little-endian format). Normally, this structure has no use
|
||||||
// WavPack 4.0 files, and is the preamble to every block in both the .wv
|
// to an application using the library to read or write WavPack files,
|
||||||
// and .wvc files.
|
// but if an application needs to manually parse WavPack files then this
|
||||||
|
// would be used (with appropriate endian correction).
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char ckID [4];
|
char ckID [4];
|
||||||
uint32_t ckSize;
|
uint32_t ckSize;
|
||||||
short version;
|
short version;
|
||||||
uchar track_no, index_no;
|
unsigned char track_no, index_no;
|
||||||
uint32_t total_samples, block_index, block_samples, flags, crc;
|
uint32_t total_samples, block_index, block_samples, flags, crc;
|
||||||
} WavpackHeader;
|
} WavpackHeader;
|
||||||
|
|
||||||
#define WavpackHeaderFormat "4LS2LLLLL"
|
#define WavpackHeaderFormat "4LS2LLLLL"
|
||||||
|
|
||||||
// or-values for "flags"
|
// or-values for WavpackHeader.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 BYTES_STORED 3 // 1-4 bytes/sample
|
#define INT32_DATA 0x100 // special extended int handling
|
||||||
#define MONO_FLAG 4 // not stereo
|
#define HYBRID_BITRATE 0x200 // bitrate noise (hybrid mode only)
|
||||||
#define HYBRID_FLAG 8 // hybrid mode
|
#define HYBRID_BALANCE 0x400 // balance noise (hybrid stereo mode only)
|
||||||
#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 INITIAL_BLOCK 0x800 // initial block of multichannel segment
|
||||||
#define HYBRID_BITRATE 0x200 // bitrate noise (hybrid mode only)
|
#define FINAL_BLOCK 0x1000 // final block of multichannel segment
|
||||||
#define HYBRID_BALANCE 0x400 // balance noise (hybrid stereo mode only)
|
|
||||||
|
|
||||||
#define INITIAL_BLOCK 0x800 // initial block of multichannel segment
|
#define SHIFT_LSB 13
|
||||||
#define FINAL_BLOCK 0x1000 // final block of multichannel segment
|
#define SHIFT_MASK (0x1fL << SHIFT_LSB)
|
||||||
|
|
||||||
#define SHIFT_LSB 13
|
#define MAG_LSB 18
|
||||||
#define SHIFT_MASK (0x1fL << SHIFT_LSB)
|
#define MAG_MASK (0x1fL << MAG_LSB)
|
||||||
|
|
||||||
#define MAG_LSB 18
|
#define SRATE_LSB 23
|
||||||
#define MAG_MASK (0x1fL << MAG_LSB)
|
#define SRATE_MASK (0xfL << SRATE_LSB)
|
||||||
|
|
||||||
#define SRATE_LSB 23
|
#define FALSE_STEREO 0x40000000 // block is stereo, but data is mono
|
||||||
#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 IGNORED_FLAGS 0x18000000 // reserved, but ignore if encountered
|
#define UNKNOWN_FLAGS 0x80000000 // also reserved, but refuse decode if
|
||||||
#define NEW_SHAPING 0x20000000 // use IIR filter for negative shaping
|
// encountered
|
||||||
#define UNKNOWN_FLAGS 0x80000000 // also reserved, but refuse decode if
|
|
||||||
// encountered
|
|
||||||
|
|
||||||
#define MONO_DATA (MONO_FLAG | FALSE_STEREO)
|
#define MONO_DATA (MONO_FLAG | FALSE_STEREO)
|
||||||
|
|
||||||
#define MIN_STREAM_VERS 0x402 // lowest stream version we'll decode
|
#define MIN_STREAM_VERS 0x402 // lowest stream version we'll decode
|
||||||
#define MAX_STREAM_VERS 0x410 // highest stream version we'll decode
|
#define MAX_STREAM_VERS 0x410 // highest stream version we'll decode or encode
|
||||||
#define CUR_STREAM_VERS 0x404 // stream version we are writing now
|
#define CUR_STREAM_VERS 0x407 // stream version we are writing now
|
||||||
|
|
||||||
|
// These are the mask bit definitions for the metadata chunk id byte (see format.txt)
|
||||||
|
|
||||||
//////////////////////////// WavPack Metadata /////////////////////////////////
|
#define ID_UNIQUE 0x3f
|
||||||
|
#define ID_OPTIONAL_DATA 0x20
|
||||||
|
#define ID_ODD_SIZE 0x40
|
||||||
|
#define ID_LARGE 0x80
|
||||||
|
|
||||||
// This is an internal representation of metadata.
|
#define ID_DUMMY 0x0
|
||||||
|
#define ID_ENCODER_INFO 0x1
|
||||||
|
#define ID_DECORR_TERMS 0x2
|
||||||
|
#define ID_DECORR_WEIGHTS 0x3
|
||||||
|
#define ID_DECORR_SAMPLES 0x4
|
||||||
|
#define ID_ENTROPY_VARS 0x5
|
||||||
|
#define ID_HYBRID_PROFILE 0x6
|
||||||
|
#define ID_SHAPING_WEIGHTS 0x7
|
||||||
|
#define ID_FLOAT_INFO 0x8
|
||||||
|
#define ID_INT32_INFO 0x9
|
||||||
|
#define ID_WV_BITSTREAM 0xa
|
||||||
|
#define ID_WVC_BITSTREAM 0xb
|
||||||
|
#define ID_WVX_BITSTREAM 0xc
|
||||||
|
#define ID_CHANNEL_INFO 0xd
|
||||||
|
|
||||||
typedef struct {
|
#define ID_RIFF_HEADER (ID_OPTIONAL_DATA | 0x1)
|
||||||
int32_t byte_length;
|
#define ID_RIFF_TRAILER (ID_OPTIONAL_DATA | 0x2)
|
||||||
void *data;
|
#define ID_REPLAY_GAIN (ID_OPTIONAL_DATA | 0x3) // never used (APEv2)
|
||||||
uchar id;
|
#define ID_CUESHEET (ID_OPTIONAL_DATA | 0x4) // never used (APEv2)
|
||||||
} WavpackMetadata;
|
#define ID_CONFIG_BLOCK (ID_OPTIONAL_DATA | 0x5)
|
||||||
|
#define ID_MD5_CHECKSUM (ID_OPTIONAL_DATA | 0x6)
|
||||||
#define ID_UNIQUE 0x3f
|
#define ID_SAMPLE_RATE (ID_OPTIONAL_DATA | 0x7)
|
||||||
#define ID_OPTIONAL_DATA 0x20
|
|
||||||
#define ID_ODD_SIZE 0x40
|
|
||||||
#define ID_LARGE 0x80
|
|
||||||
|
|
||||||
#define ID_DUMMY 0x0
|
|
||||||
#define ID_ENCODER_INFO 0x1
|
|
||||||
#define ID_DECORR_TERMS 0x2
|
|
||||||
#define ID_DECORR_WEIGHTS 0x3
|
|
||||||
#define ID_DECORR_SAMPLES 0x4
|
|
||||||
#define ID_ENTROPY_VARS 0x5
|
|
||||||
#define ID_HYBRID_PROFILE 0x6
|
|
||||||
#define ID_SHAPING_WEIGHTS 0x7
|
|
||||||
#define ID_FLOAT_INFO 0x8
|
|
||||||
#define ID_INT32_INFO 0x9
|
|
||||||
#define ID_WV_BITSTREAM 0xa
|
|
||||||
#define ID_WVC_BITSTREAM 0xb
|
|
||||||
#define ID_WVX_BITSTREAM 0xc
|
|
||||||
#define ID_CHANNEL_INFO 0xd
|
|
||||||
|
|
||||||
#define ID_RIFF_HEADER (ID_OPTIONAL_DATA | 0x1)
|
|
||||||
#define ID_RIFF_TRAILER (ID_OPTIONAL_DATA | 0x2)
|
|
||||||
#define ID_REPLAY_GAIN (ID_OPTIONAL_DATA | 0x3)
|
|
||||||
#define ID_CUESHEET (ID_OPTIONAL_DATA | 0x4)
|
|
||||||
#define ID_CONFIG_BLOCK (ID_OPTIONAL_DATA | 0x5)
|
|
||||||
#define ID_MD5_CHECKSUM (ID_OPTIONAL_DATA | 0x6)
|
|
||||||
#define ID_SAMPLE_RATE (ID_OPTIONAL_DATA | 0x7)
|
|
||||||
|
|
||||||
///////////////////////// WavPack Configuration ///////////////////////////////
|
///////////////////////// WavPack Configuration ///////////////////////////////
|
||||||
|
|
||||||
// This internal structure is used during encode to provide configuration to
|
// This external structure is used during encode to provide configuration to
|
||||||
// the encoding engine and during decoding to provide fle information back 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.
|
// the higher level functions. Not all fields are used in both modes.
|
||||||
|
|
||||||
|
@ -232,124 +157,33 @@ typedef struct {
|
||||||
int bits_per_sample, bytes_per_sample;
|
int bits_per_sample, bytes_per_sample;
|
||||||
int qmode, flags, xmode, num_channels, float_norm_exp;
|
int qmode, flags, xmode, num_channels, float_norm_exp;
|
||||||
int32_t block_samples, extra_flags, sample_rate, channel_mask;
|
int32_t block_samples, extra_flags, sample_rate, channel_mask;
|
||||||
uchar md5_checksum [16], md5_read;
|
unsigned char md5_checksum [16], md5_read;
|
||||||
int num_tag_strings;
|
int num_tag_strings;
|
||||||
char **tag_strings;
|
char **tag_strings;
|
||||||
} WavpackConfig;
|
} WavpackConfig;
|
||||||
|
|
||||||
#define CONFIG_BYTES_STORED 3 // 1-4 bytes/sample
|
#define CONFIG_HYBRID_FLAG 8 // hybrid mode
|
||||||
#define CONFIG_MONO_FLAG 4 // not stereo
|
#define CONFIG_JOINT_STEREO 0x10 // joint stereo
|
||||||
#define CONFIG_HYBRID_FLAG 8 // hybrid mode
|
#define CONFIG_HYBRID_SHAPE 0x40 // noise shape (hybrid mode only)
|
||||||
#define CONFIG_JOINT_STEREO 0x10 // joint stereo
|
#define CONFIG_FAST_FLAG 0x200 // fast mode
|
||||||
#define CONFIG_CROSS_DECORR 0x20 // no-delay cross decorrelation
|
#define CONFIG_HIGH_FLAG 0x800 // high quality mode
|
||||||
#define CONFIG_HYBRID_SHAPE 0x40 // noise shape (hybrid mode only)
|
#define CONFIG_VERY_HIGH_FLAG 0x1000 // very high
|
||||||
#define CONFIG_FLOAT_DATA 0x80 // ieee 32-bit floating point data
|
#define CONFIG_BITRATE_KBPS 0x2000 // bitrate is kbps, not bits / sample
|
||||||
|
#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_EXTRA_MODE 0x2000000 // extra processing mode
|
||||||
|
#define CONFIG_SKIP_WVX 0x4000000 // no wvx stream w/ floats & big ints
|
||||||
|
#define CONFIG_MD5_CHECKSUM 0x8000000 // 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 CONFIG_ADOBE_MODE 0x100 // "adobe" mode for 32-bit floats
|
////////////// Callbacks used for reading & writing WavPack streams //////////
|
||||||
#define CONFIG_FAST_FLAG 0x200 // fast mode
|
|
||||||
#define CONFIG_VERY_FAST_FLAG 0x400 // double fast
|
|
||||||
#define CONFIG_HIGH_FLAG 0x800 // high quality mode
|
|
||||||
#define CONFIG_VERY_HIGH_FLAG 0x1000 // double high (not used yet)
|
|
||||||
#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_COPY_TIME 0x20000 // copy file-time from source
|
|
||||||
#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_QUALITY_MODE 0x200000 // psychoacoustic quality mode
|
|
||||||
#define CONFIG_RAW_FLAG 0x400000 // raw mode (not implemented yet)
|
|
||||||
#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_QUIET_MODE 0x10000000 // don't report progress %
|
|
||||||
#define CONFIG_IGNORE_LENGTH 0x20000000 // ignore length in wav header
|
|
||||||
#define CONFIG_NEW_RIFF_HEADER 0x40000000 // generate new RIFF wav header
|
|
||||||
|
|
||||||
#define EXTRA_SCAN_ONLY 1
|
|
||||||
#define EXTRA_STEREO_MODES 2
|
|
||||||
#define EXTRA_TRY_DELTAS 8
|
|
||||||
#define EXTRA_ADJUST_DELTAS 16
|
|
||||||
#define EXTRA_SORT_FIRST 32
|
|
||||||
#define EXTRA_BRANCHES 0x1c0
|
|
||||||
#define EXTRA_SKIP_8TO16 512
|
|
||||||
#define EXTRA_TERMS 0x3c00
|
|
||||||
#define EXTRA_DUMP_TERMS 16384
|
|
||||||
#define EXTRA_SORT_LAST 32768
|
|
||||||
|
|
||||||
//////////////////////////////// WavPack Stream ///////////////////////////////
|
|
||||||
|
|
||||||
// This internal structure contains everything required to handle a WavPack
|
|
||||||
// "stream", which is defined as a stereo or mono stream of audio samples. For
|
|
||||||
// multichannel audio several of these would be required. Each stream contains
|
|
||||||
// pointers to hold a complete allocated block of WavPack data, although it's
|
|
||||||
// possible to decode WavPack blocks without buffering an entire block.
|
|
||||||
|
|
||||||
typedef struct bs {
|
|
||||||
uchar *buf, *end, *ptr;
|
|
||||||
void (*wrap)(struct bs *bs);
|
|
||||||
int error, bc;
|
|
||||||
uint32_t sr;
|
|
||||||
} Bitstream;
|
|
||||||
|
|
||||||
#define MAX_STREAMS 8
|
|
||||||
#define MAX_NTERMS 16
|
|
||||||
#define MAX_TERM 8
|
|
||||||
|
|
||||||
struct decorr_pass {
|
|
||||||
int term, delta, weight_A, weight_B;
|
|
||||||
int32_t samples_A [MAX_TERM], samples_B [MAX_TERM];
|
|
||||||
int32_t aweight_A, aweight_B;
|
|
||||||
int32_t sum_A, sum_B;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
WavpackHeader wphdr;
|
|
||||||
|
|
||||||
uchar *blockbuff, *blockend;
|
|
||||||
uchar *block2buff, *block2end;
|
|
||||||
int32_t *sample_buffer;
|
|
||||||
|
|
||||||
int bits, num_terms, mute_error, false_stereo, shift;
|
|
||||||
uint32_t sample_index, crc, crc_x, crc_wvx;
|
|
||||||
Bitstream wvbits, wvcbits, wvxbits;
|
|
||||||
float delta_decay;
|
|
||||||
|
|
||||||
uchar int32_sent_bits, int32_zeros, int32_ones, int32_dups;
|
|
||||||
uchar float_flags, float_shift, float_max_exp, float_norm_exp;
|
|
||||||
|
|
||||||
struct {
|
|
||||||
int32_t shaping_acc [2], shaping_delta [2], error [2];
|
|
||||||
double noise_sum, noise_ave, noise_max;
|
|
||||||
} dc;
|
|
||||||
|
|
||||||
struct decorr_pass decorr_passes [MAX_NTERMS];
|
|
||||||
|
|
||||||
struct {
|
|
||||||
uint32_t bitrate_delta [2], bitrate_acc [2];
|
|
||||||
uint32_t median [3] [2], slow_level [2], error_limit [2];
|
|
||||||
uint32_t pend_data, holding_one, zeros_acc;
|
|
||||||
int holding_zero, pend_count;
|
|
||||||
} w;
|
|
||||||
} WavpackStream;
|
|
||||||
|
|
||||||
// flags for float_flags:
|
|
||||||
|
|
||||||
#define FLOAT_SHIFT_ONES 1 // bits left-shifted into float = '1'
|
|
||||||
#define FLOAT_SHIFT_SAME 2 // bits left-shifted into float are the same
|
|
||||||
#define FLOAT_SHIFT_SENT 4 // bits shifted into float are sent literally
|
|
||||||
#define FLOAT_ZEROS_SENT 8 // "zeros" are not all real zeros
|
|
||||||
#define FLOAT_NEG_ZEROS 0x10 // contains negative zeros
|
|
||||||
#define FLOAT_EXCEPTIONS 0x20 // contains exceptions (inf, nan, etc.)
|
|
||||||
|
|
||||||
/////////////////////////////// WavPack Context ///////////////////////////////
|
|
||||||
|
|
||||||
// This internal structure holds everything required to encode or decode WavPack
|
|
||||||
// files. It is recommended that direct access to this structure be minimized
|
|
||||||
// and the provided utilities used instead.
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int32_t (*read_bytes)(void *id, void *data, int32_t bcount);
|
int32_t (*read_bytes)(void *id, void *data, int32_t bcount);
|
||||||
|
@ -366,278 +200,46 @@ typedef struct {
|
||||||
|
|
||||||
typedef int (*WavpackBlockOutput)(void *id, void *data, int32_t bcount);
|
typedef int (*WavpackBlockOutput)(void *id, void *data, int32_t bcount);
|
||||||
|
|
||||||
typedef struct {
|
//////////////////////////// function prototypes /////////////////////////////
|
||||||
WavpackConfig config;
|
|
||||||
|
|
||||||
WavpackMetadata *metadata;
|
// Note: See wputils.c sourcecode for descriptions for using these functions.
|
||||||
uint32_t metabytes;
|
|
||||||
int metacount;
|
|
||||||
|
|
||||||
uchar *wrapper_data;
|
typedef void WavpackContext;
|
||||||
uint32_t wrapper_bytes;
|
|
||||||
|
|
||||||
WavpackBlockOutput blockout;
|
#ifdef __cplusplus
|
||||||
void *wv_out, *wvc_out;
|
extern "C" {
|
||||||
|
|
||||||
WavpackStreamReader *reader;
|
|
||||||
void *wv_in, *wvc_in;
|
|
||||||
|
|
||||||
uint32_t filelen, file2len, filepos, file2pos, total_samples, crc_errors, first_flags;
|
|
||||||
int wvc_flag, open_flags, norm_offset, reduced_channels, lossy_blocks, close_files;
|
|
||||||
int block_samples, max_samples, acc_samples, riff_header_added, riff_header_created;
|
|
||||||
M_Tag m_tag;
|
|
||||||
|
|
||||||
int current_stream, num_streams, stream_version;
|
|
||||||
WavpackStream *streams [8];
|
|
||||||
void *stream3;
|
|
||||||
|
|
||||||
char error_message [80];
|
|
||||||
} WavpackContext;
|
|
||||||
|
|
||||||
//////////////////////// function prototypes and macros //////////////////////
|
|
||||||
|
|
||||||
#define CLEAR(destin) memset (&destin, 0, sizeof (destin));
|
|
||||||
|
|
||||||
// these macros implement the weight application and update operations
|
|
||||||
// that are at the heart of the decorrelation loops
|
|
||||||
|
|
||||||
#define apply_weight_i(weight, sample) ((weight * sample + 512) >> 10)
|
|
||||||
|
|
||||||
#define apply_weight_f(weight, sample) (((((sample & 0xffff) * weight) >> 9) + \
|
|
||||||
(((sample & ~0xffff) >> 9) * weight) + 1) >> 1)
|
|
||||||
|
|
||||||
#if 1 // PERFCOND
|
|
||||||
#define apply_weight(weight, sample) (sample != (short) sample ? \
|
|
||||||
apply_weight_f (weight, sample) : apply_weight_i (weight, sample))
|
|
||||||
#else
|
|
||||||
#define apply_weight(weight, sample) ((int32_t)((weight * (int64_t) sample + 512) >> 10))
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if 1 // PERFCOND
|
|
||||||
#define update_weight(weight, delta, source, result) \
|
|
||||||
if (source && result) weight -= ((((source ^ result) >> 30) & 2) - 1) * delta;
|
|
||||||
#else
|
|
||||||
#define update_weight(weight, delta, source, result) \
|
|
||||||
if (source && result) (source ^ result) < 0 ? (weight -= delta) : (weight += delta);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define update_weight_d1(weight, delta, source, result) \
|
|
||||||
if (source && result) weight -= (((source ^ result) >> 30) & 2) - 1;
|
|
||||||
|
|
||||||
#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 && ((source ^ result) < 0 ? (weight -= delta) < -1024 : (weight += delta) > 1024)) \
|
|
||||||
weight = weight < 0 ? -1024 : 1024;
|
|
||||||
|
|
||||||
#define update_weight_clip_d1(weight, delta, source, result) \
|
|
||||||
if (source && result && abs (weight -= (((source ^ result) >> 30) & 2) - 1) > 1024) \
|
|
||||||
weight = weight < 0 ? -1024 : 1024;
|
|
||||||
|
|
||||||
#define update_weight_clip_d2(weight, delta, source, result) \
|
|
||||||
if (source && result && abs (weight -= (((source ^ result) >> 29) & 4) - 2) > 1024) \
|
|
||||||
weight = weight < 0 ? -1024 : 1024;
|
|
||||||
|
|
||||||
// bits.c
|
|
||||||
|
|
||||||
void bs_open_read (Bitstream *bs, uchar *buffer_start, uchar *buffer_end);
|
|
||||||
void bs_open_write (Bitstream *bs, uchar *buffer_start, uchar *buffer_end);
|
|
||||||
uint32_t bs_close_read (Bitstream *bs);
|
|
||||||
uint32_t bs_close_write (Bitstream *bs);
|
|
||||||
|
|
||||||
int DoReadFile (FILE *hFile, void *lpBuffer, uint32_t nNumberOfBytesToRead, uint32_t *lpNumberOfBytesRead);
|
|
||||||
int DoWriteFile (FILE *hFile, void *lpBuffer, uint32_t nNumberOfBytesToWrite, uint32_t *lpNumberOfBytesWritten);
|
|
||||||
uint32_t DoGetFileSize (FILE *hFile), DoGetFilePosition (FILE *hFile);
|
|
||||||
int DoSetFilePositionRelative (FILE *hFile, int32_t pos, int mode);
|
|
||||||
int DoSetFilePositionAbsolute (FILE *hFile, uint32_t pos);
|
|
||||||
int DoUngetc (int c, FILE *hFile), DoDeleteFile (char *filename);
|
|
||||||
int DoCloseHandle (FILE *hFile), DoTruncateFile (FILE *hFile);
|
|
||||||
|
|
||||||
#define bs_is_open(bs) ((bs)->ptr != NULL)
|
|
||||||
|
|
||||||
#define getbit(bs) ( \
|
|
||||||
(((bs)->bc) ? \
|
|
||||||
((bs)->bc--, (bs)->sr & 1) : \
|
|
||||||
(((++((bs)->ptr) != (bs)->end) ? (void) 0 : (bs)->wrap (bs)), (bs)->bc = 7, ((bs)->sr = *((bs)->ptr)) & 1) \
|
|
||||||
) ? \
|
|
||||||
((bs)->sr >>= 1, 1) : \
|
|
||||||
((bs)->sr >>= 1, 0) \
|
|
||||||
)
|
|
||||||
|
|
||||||
#define getbits(value, nbits, bs) { \
|
|
||||||
while ((nbits) > (bs)->bc) { \
|
|
||||||
if (++((bs)->ptr) == (bs)->end) (bs)->wrap (bs); \
|
|
||||||
(bs)->sr |= (int32_t)*((bs)->ptr) << (bs)->bc; \
|
|
||||||
(bs)->bc += 8; \
|
|
||||||
} \
|
|
||||||
*(value) = (bs)->sr; \
|
|
||||||
if ((bs)->bc > 32) { \
|
|
||||||
(bs)->bc -= (nbits); \
|
|
||||||
(bs)->sr = *((bs)->ptr) >> (8 - (bs)->bc); \
|
|
||||||
} \
|
|
||||||
else { \
|
|
||||||
(bs)->bc -= (nbits); \
|
|
||||||
(bs)->sr >>= (nbits); \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define putbit(bit, bs) { if (bit) (bs)->sr |= (1 << (bs)->bc); \
|
|
||||||
if (++((bs)->bc) == 8) { \
|
|
||||||
*((bs)->ptr) = (bs)->sr; \
|
|
||||||
(bs)->sr = (bs)->bc = 0; \
|
|
||||||
if (++((bs)->ptr) == (bs)->end) (bs)->wrap (bs); \
|
|
||||||
}}
|
|
||||||
|
|
||||||
#define putbit_0(bs) { \
|
|
||||||
if (++((bs)->bc) == 8) { \
|
|
||||||
*((bs)->ptr) = (bs)->sr; \
|
|
||||||
(bs)->sr = (bs)->bc = 0; \
|
|
||||||
if (++((bs)->ptr) == (bs)->end) (bs)->wrap (bs); \
|
|
||||||
}}
|
|
||||||
|
|
||||||
#define putbit_1(bs) { (bs)->sr |= (1 << (bs)->bc); \
|
|
||||||
if (++((bs)->bc) == 8) { \
|
|
||||||
*((bs)->ptr) = (bs)->sr; \
|
|
||||||
(bs)->sr = (bs)->bc = 0; \
|
|
||||||
if (++((bs)->ptr) == (bs)->end) (bs)->wrap (bs); \
|
|
||||||
}}
|
|
||||||
|
|
||||||
#define putbits(value, nbits, bs) { \
|
|
||||||
(bs)->sr |= (int32_t)(value) << (bs)->bc; \
|
|
||||||
if (((bs)->bc += (nbits)) >= 8) \
|
|
||||||
do { \
|
|
||||||
*((bs)->ptr) = (bs)->sr; \
|
|
||||||
(bs)->sr >>= 8; \
|
|
||||||
if (((bs)->bc -= 8) > 24) (bs)->sr |= ((value) >> ((nbits) - (bs)->bc)); \
|
|
||||||
if (++((bs)->ptr) == (bs)->end) (bs)->wrap (bs); \
|
|
||||||
} while ((bs)->bc >= 8); \
|
|
||||||
}
|
|
||||||
|
|
||||||
void little_endian_to_native (void *data, char *format);
|
|
||||||
void native_to_little_endian (void *data, char *format);
|
|
||||||
|
|
||||||
// pack.c
|
|
||||||
|
|
||||||
void pack_init (WavpackContext *wpc);
|
|
||||||
int pack_block (WavpackContext *wpc, int32_t *buffer);
|
|
||||||
double pack_noise (WavpackContext *wpc, double *peak);
|
|
||||||
|
|
||||||
// unpack.c
|
|
||||||
|
|
||||||
int unpack_init (WavpackContext *wpc);
|
|
||||||
int init_wv_bitstream (WavpackStream *wps, WavpackMetadata *wpmd);
|
|
||||||
int init_wvc_bitstream (WavpackStream *wps, WavpackMetadata *wpmd);
|
|
||||||
int init_wvx_bitstream (WavpackStream *wps, WavpackMetadata *wpmd);
|
|
||||||
int read_decorr_terms (WavpackStream *wps, WavpackMetadata *wpmd);
|
|
||||||
int read_decorr_weights (WavpackStream *wps, WavpackMetadata *wpmd);
|
|
||||||
int read_decorr_samples (WavpackStream *wps, WavpackMetadata *wpmd);
|
|
||||||
int read_shaping_info (WavpackStream *wps, WavpackMetadata *wpmd);
|
|
||||||
int read_float_info (WavpackStream *wps, WavpackMetadata *wpmd);
|
|
||||||
int read_int32_info (WavpackStream *wps, WavpackMetadata *wpmd);
|
|
||||||
int read_channel_info (WavpackContext *wpc, WavpackMetadata *wpmd);
|
|
||||||
int read_config_info (WavpackContext *wpc, WavpackMetadata *wpmd);
|
|
||||||
int read_sample_rate (WavpackContext *wpc, WavpackMetadata *wpmd);
|
|
||||||
int read_wrapper_data (WavpackContext *wpc, WavpackMetadata *wpmd);
|
|
||||||
int32_t unpack_samples (WavpackContext *wpc, int32_t *buffer, uint32_t sample_count);
|
|
||||||
int check_crc_error (WavpackContext *wpc);
|
|
||||||
|
|
||||||
// unpack3.c
|
|
||||||
|
|
||||||
WavpackContext *open_file3 (WavpackContext *wpc, char *error);
|
|
||||||
int32_t unpack_samples3 (WavpackContext *wpc, int32_t *buffer, uint32_t sample_count);
|
|
||||||
int seek_sample3 (WavpackContext *wpc, uint32_t desired_index);
|
|
||||||
uint32_t get_sample_index3 (WavpackContext *wpc);
|
|
||||||
void free_stream3 (WavpackContext *wpc);
|
|
||||||
int get_version3 (WavpackContext *wpc);
|
|
||||||
|
|
||||||
// utils.c
|
|
||||||
|
|
||||||
int copy_timestamp (const char *src_filename, const char *dst_filename);
|
|
||||||
char *filespec_ext (char *filespec), *filespec_path (char *filespec);
|
|
||||||
char *filespec_name (char *filespec), *filespec_wild (char *filespec);
|
|
||||||
void error_line (char *error, ...);
|
|
||||||
void setup_break (void), finish_line (void);
|
|
||||||
int check_break (void);
|
|
||||||
char yna (void);
|
|
||||||
|
|
||||||
#define FN_FIT(fn) ((strlen (fn) > 30) ? filespec_name (fn) : fn)
|
|
||||||
|
|
||||||
// metadata.c stuff
|
|
||||||
|
|
||||||
int read_metadata_buff (WavpackMetadata *wpmd, uchar *blockbuff, uchar **buffptr);
|
|
||||||
int write_metadata_block (WavpackContext *wpc);
|
|
||||||
int copy_metadata (WavpackMetadata *wpmd, uchar *buffer_start, uchar *buffer_end);
|
|
||||||
int add_to_metadata (WavpackContext *wpc, void *data, uint32_t bcount, uchar id);
|
|
||||||
int process_metadata (WavpackContext *wpc, WavpackMetadata *wpmd);
|
|
||||||
void free_metadata (WavpackMetadata *wpmd);
|
|
||||||
|
|
||||||
// words.c stuff
|
|
||||||
|
|
||||||
void init_words (WavpackStream *wps);
|
|
||||||
void word_set_bitrate (WavpackStream *wps);
|
|
||||||
void write_entropy_vars (WavpackStream *wps, WavpackMetadata *wpmd);
|
|
||||||
void write_hybrid_profile (WavpackStream *wps, WavpackMetadata *wpmd);
|
|
||||||
int read_entropy_vars (WavpackStream *wps, WavpackMetadata *wpmd);
|
|
||||||
int read_hybrid_profile (WavpackStream *wps, WavpackMetadata *wpmd);
|
|
||||||
int32_t FASTCALL send_word (WavpackStream *wps, int32_t value, int chan);
|
|
||||||
void FASTCALL send_word_lossless (WavpackStream *wps, int32_t value, int chan);
|
|
||||||
int32_t FASTCALL get_word (WavpackStream *wps, int chan, int32_t *correction);
|
|
||||||
int32_t FASTCALL get_word_lossless (WavpackStream *wps, int chan);
|
|
||||||
void flush_word (WavpackStream *wps);
|
|
||||||
int32_t nosend_word (WavpackStream *wps, int32_t value, int chan);
|
|
||||||
void scan_word (WavpackStream *wps, int32_t *samples, uint32_t num_samples, int dir);
|
|
||||||
|
|
||||||
int log2s (int32_t value);
|
|
||||||
int32_t exp2s (int log);
|
|
||||||
uint32_t log2buffer (int32_t *samples, uint32_t num_samples, int limit);
|
|
||||||
|
|
||||||
signed char store_weight (int weight);
|
|
||||||
int restore_weight (signed char weight);
|
|
||||||
|
|
||||||
#define WORD_EOF (1L << 31)
|
|
||||||
|
|
||||||
// float.c
|
|
||||||
|
|
||||||
void write_float_info (WavpackStream *wps, WavpackMetadata *wpmd);
|
|
||||||
int scan_float_data (WavpackStream *wps, f32 *values, int32_t num_values);
|
|
||||||
void send_float_data (WavpackStream *wps, f32 *values, int32_t num_values);
|
|
||||||
int read_float_info (WavpackStream *wps, WavpackMetadata *wpmd);
|
|
||||||
void float_values (WavpackStream *wps, int32_t *values, int32_t num_values);
|
|
||||||
void float_normalize (int32_t *values, int32_t num_values, int delta_exp);
|
|
||||||
|
|
||||||
// analyze?.c
|
|
||||||
|
|
||||||
void analyze_stereo (WavpackContext *wpc, int32_t *samples);
|
|
||||||
void analyze_mono (WavpackContext *wpc, int32_t *samples);
|
|
||||||
|
|
||||||
// wputils.c
|
|
||||||
|
|
||||||
WavpackContext *WavpackOpenFileInputEx (WavpackStreamReader *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);
|
WavpackContext *WavpackOpenFileInput (const char *infilename, char *error, int flags, int norm_offset);
|
||||||
|
|
||||||
#define OPEN_WVC 0x1 // open/read "correction" file
|
#define OPEN_WVC 0x1 // open/read "correction" file
|
||||||
#define OPEN_TAGS 0x2 // read ID3v1 / APEv2 tags (seekable file)
|
#define OPEN_TAGS 0x2 // read ID3v1 / APEv2 tags (seekable file)
|
||||||
#define OPEN_WRAPPER 0x4 // make audio wrapper available (i.e. RIFF)
|
#define OPEN_WRAPPER 0x4 // make audio wrapper available (i.e. RIFF)
|
||||||
#define OPEN_2CH_MAX 0x8 // open multichannel as stereo (no downmix)
|
#define OPEN_2CH_MAX 0x8 // open multichannel as stereo (no downmix)
|
||||||
#define OPEN_NORMALIZE 0x10 // normalize floating point data to +/- 1.0
|
#define OPEN_NORMALIZE 0x10 // normalize floating point data to +/- 1.0
|
||||||
#define OPEN_STREAMING 0x20 // "streaming" mode blindly unpacks blocks
|
#define OPEN_STREAMING 0x20 // "streaming" mode blindly unpacks blocks
|
||||||
// w/o regard to header file position info
|
// w/o regard to header file position info
|
||||||
#define OPEN_EDIT_TAGS 0x40 // allow editing of tags
|
#define OPEN_EDIT_TAGS 0x40 // allow editing of tags
|
||||||
|
|
||||||
int WavpackGetMode (WavpackContext *wpc);
|
int WavpackGetMode (WavpackContext *wpc);
|
||||||
|
|
||||||
#define MODE_WVC 0x1
|
#define MODE_WVC 0x1
|
||||||
#define MODE_LOSSLESS 0x2
|
#define MODE_LOSSLESS 0x2
|
||||||
#define MODE_HYBRID 0x4
|
#define MODE_HYBRID 0x4
|
||||||
#define MODE_FLOAT 0x8
|
#define MODE_FLOAT 0x8
|
||||||
#define MODE_VALID_TAG 0x10
|
#define MODE_VALID_TAG 0x10
|
||||||
#define MODE_HIGH 0x20
|
#define MODE_HIGH 0x20
|
||||||
#define MODE_FAST 0x40
|
#define MODE_FAST 0x40
|
||||||
#define MODE_EXTRA 0x80
|
#define MODE_EXTRA 0x80 // extra mode used, see MODE_XMODE for possible level
|
||||||
#define MODE_APETAG 0x100
|
#define MODE_APETAG 0x100
|
||||||
#define MODE_SFX 0x200
|
#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
|
||||||
|
|
||||||
|
char *WavpackGetErrorMessage (WavpackContext *wpc);
|
||||||
int WavpackGetVersion (WavpackContext *wpc);
|
int WavpackGetVersion (WavpackContext *wpc);
|
||||||
uint32_t WavpackUnpackSamples (WavpackContext *wpc, int32_t *buffer, uint32_t samples);
|
uint32_t WavpackUnpackSamples (WavpackContext *wpc, int32_t *buffer, uint32_t samples);
|
||||||
uint32_t WavpackGetNumSamples (WavpackContext *wpc);
|
uint32_t WavpackGetNumSamples (WavpackContext *wpc);
|
||||||
|
@ -650,11 +252,14 @@ uint32_t WavpackGetSampleRate (WavpackContext *wpc);
|
||||||
int WavpackGetBitsPerSample (WavpackContext *wpc);
|
int WavpackGetBitsPerSample (WavpackContext *wpc);
|
||||||
int WavpackGetBytesPerSample (WavpackContext *wpc);
|
int WavpackGetBytesPerSample (WavpackContext *wpc);
|
||||||
int WavpackGetNumChannels (WavpackContext *wpc);
|
int WavpackGetNumChannels (WavpackContext *wpc);
|
||||||
|
int WavpackGetChannelMask (WavpackContext *wpc);
|
||||||
int WavpackGetReducedChannels (WavpackContext *wpc);
|
int WavpackGetReducedChannels (WavpackContext *wpc);
|
||||||
int WavpackGetMD5Sum (WavpackContext *wpc, uchar data [16]);
|
int WavpackGetFloatNormExp (WavpackContext *wpc);
|
||||||
|
int WavpackGetMD5Sum (WavpackContext *wpc, unsigned char data [16]);
|
||||||
uint32_t WavpackGetWrapperBytes (WavpackContext *wpc);
|
uint32_t WavpackGetWrapperBytes (WavpackContext *wpc);
|
||||||
uchar *WavpackGetWrapperData (WavpackContext *wpc);
|
unsigned char *WavpackGetWrapperData (WavpackContext *wpc);
|
||||||
void WavpackFreeWrapper (WavpackContext *wpc);
|
void WavpackFreeWrapper (WavpackContext *wpc);
|
||||||
|
void WavpackSeekTrailingWrapper (WavpackContext *wpc);
|
||||||
double WavpackGetProgress (WavpackContext *wpc);
|
double WavpackGetProgress (WavpackContext *wpc);
|
||||||
uint32_t WavpackGetFileSize (WavpackContext *wpc);
|
uint32_t WavpackGetFileSize (WavpackContext *wpc);
|
||||||
double WavpackGetRatio (WavpackContext *wpc);
|
double WavpackGetRatio (WavpackContext *wpc);
|
||||||
|
@ -663,18 +268,35 @@ double WavpackGetInstantBitrate (WavpackContext *wpc);
|
||||||
int WavpackGetNumTagItems (WavpackContext *wpc);
|
int WavpackGetNumTagItems (WavpackContext *wpc);
|
||||||
int WavpackGetTagItem (WavpackContext *wpc, const char *item, char *value, int size);
|
int WavpackGetTagItem (WavpackContext *wpc, const char *item, char *value, int size);
|
||||||
int WavpackGetTagItemIndexed (WavpackContext *wpc, int index, char *item, int size);
|
int WavpackGetTagItemIndexed (WavpackContext *wpc, int index, char *item, int size);
|
||||||
|
int WavpackGetNumBinaryTagItems (WavpackContext *wpc);
|
||||||
|
int WavpackGetBinaryTagItem (WavpackContext *wpc, const char *item, char *value, int size);
|
||||||
|
int WavpackGetBinaryTagItemIndexed (WavpackContext *wpc, int index, char *item, int size);
|
||||||
int WavpackAppendTagItem (WavpackContext *wpc, const char *item, const char *value, int vsize);
|
int WavpackAppendTagItem (WavpackContext *wpc, const char *item, const char *value, int vsize);
|
||||||
|
int WavpackAppendBinaryTagItem (WavpackContext *wpc, const char *item, const char *value, int vsize);
|
||||||
int WavpackDeleteTagItem (WavpackContext *wpc, const char *item);
|
int WavpackDeleteTagItem (WavpackContext *wpc, const char *item);
|
||||||
int WavpackWriteTag (WavpackContext *wpc);
|
int WavpackWriteTag (WavpackContext *wpc);
|
||||||
|
|
||||||
WavpackContext *WavpackOpenFileOutput (WavpackBlockOutput blockout, void *wv_id, void *wvc_id);
|
WavpackContext *WavpackOpenFileOutput (WavpackBlockOutput blockout, void *wv_id, void *wvc_id);
|
||||||
int WavpackSetConfiguration (WavpackContext *wpc, WavpackConfig *config, uint32_t total_samples);
|
int WavpackSetConfiguration (WavpackContext *wpc, WavpackConfig *config, uint32_t total_samples);
|
||||||
int WavpackAddWrapper (WavpackContext *wpc, void *data, uint32_t bcount);
|
int WavpackAddWrapper (WavpackContext *wpc, void *data, uint32_t bcount);
|
||||||
int WavpackStoreMD5Sum (WavpackContext *wpc, uchar data [16]);
|
int WavpackStoreMD5Sum (WavpackContext *wpc, unsigned char data [16]);
|
||||||
int WavpackPackInit (WavpackContext *wpc);
|
int WavpackPackInit (WavpackContext *wpc);
|
||||||
int WavpackPackSamples (WavpackContext *wpc, int32_t *sample_buffer, uint32_t sample_count);
|
int WavpackPackSamples (WavpackContext *wpc, int32_t *sample_buffer, uint32_t sample_count);
|
||||||
int WavpackFlushSamples (WavpackContext *wpc);
|
int WavpackFlushSamples (WavpackContext *wpc);
|
||||||
void WavpackUpdateNumSamples (WavpackContext *wpc, void *first_block);
|
void WavpackUpdateNumSamples (WavpackContext *wpc, void *first_block);
|
||||||
void *WavpackGetWrapperLocation (void *first_block, uint32_t *size);
|
void *WavpackGetWrapperLocation (void *first_block, uint32_t *size);
|
||||||
|
double WavpackGetEncodedNoise (WavpackContext *wpc, double *peak);
|
||||||
|
|
||||||
|
void WavpackFloatNormalize (int32_t *values, int32_t num_values, int delta_exp);
|
||||||
|
|
||||||
|
void WavpackLittleEndianToNative (void *data, char *format);
|
||||||
|
void WavpackNativeToLittleEndian (void *data, char *format);
|
||||||
|
|
||||||
|
uint32_t WavpackGetLibraryVersion (void);
|
||||||
|
const char *WavpackGetLibraryVersionString (void);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,172 +0,0 @@
|
||||||
////////////////////////////////////////////////////////////////////////////
|
|
||||||
// **** WAVPACK **** //
|
|
||||||
// Hybrid Lossless Wavefile Compressor //
|
|
||||||
// Copyright (c) 1998 - 2005 Conifer Software. //
|
|
||||||
// All Rights Reserved. //
|
|
||||||
// Distributed under the BSD Software License (see license.txt) //
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// wputils.h
|
|
||||||
|
|
||||||
#ifndef WPUTILS_H
|
|
||||||
#define WPUTILS_H
|
|
||||||
|
|
||||||
// This header file contains all the definitions required to use the
|
|
||||||
// functions in "wputils.c" to read and write WavPack files and streams.
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
#if defined(_WIN32) && !defined(__MINGW32__)
|
|
||||||
#include <stdlib.h>
|
|
||||||
typedef unsigned __int64 uint64_t;
|
|
||||||
typedef unsigned __int32 uint32_t;
|
|
||||||
typedef unsigned __int16 uint16_t;
|
|
||||||
typedef unsigned __int8 uint8_t;
|
|
||||||
typedef __int64 int64_t;
|
|
||||||
typedef __int32 int32_t;
|
|
||||||
typedef __int16 int16_t;
|
|
||||||
typedef __int8 int8_t;
|
|
||||||
typedef float float32_t;
|
|
||||||
#else
|
|
||||||
#include <inttypes.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef unsigned char uchar;
|
|
||||||
|
|
||||||
#if !defined(__GNUC__) || defined(WIN32)
|
|
||||||
typedef unsigned short ushort;
|
|
||||||
typedef unsigned int uint;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
///////////////////////// WavPack Configuration ///////////////////////////////
|
|
||||||
|
|
||||||
// This external 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;
|
|
||||||
uchar md5_checksum [16], md5_read;
|
|
||||||
int num_tag_strings;
|
|
||||||
char **tag_strings;
|
|
||||||
} WavpackConfig;
|
|
||||||
|
|
||||||
#define CONFIG_HYBRID_FLAG 8 // hybrid mode
|
|
||||||
#define CONFIG_JOINT_STEREO 0x10 // joint stereo
|
|
||||||
#define CONFIG_HYBRID_SHAPE 0x40 // noise shape (hybrid mode only)
|
|
||||||
#define CONFIG_FAST_FLAG 0x200 // fast mode
|
|
||||||
#define CONFIG_HIGH_FLAG 0x800 // high quality mode
|
|
||||||
#define CONFIG_BITRATE_KBPS 0x2000 // bitrate is kbps, not bits / sample
|
|
||||||
#define CONFIG_SHAPE_OVERRIDE 0x8000 // shaping mode specified
|
|
||||||
#define CONFIG_JOINT_OVERRIDE 0x10000 // joint-stereo mode specified
|
|
||||||
#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_EXTRA_MODE 0x2000000 // extra processing mode
|
|
||||||
#define CONFIG_SKIP_WVX 0x4000000 // no wvx stream w/ floats & big ints
|
|
||||||
#define CONFIG_MD5_CHECKSUM 0x8000000 // store MD5 signature
|
|
||||||
|
|
||||||
////////////// Callbacks used for reading & writing WavPack streams //////////
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
typedef int (*WavpackBlockOutput)(void *id, void *data, int32_t bcount);
|
|
||||||
|
|
||||||
//////////////////////// function prototypes and macros //////////////////////
|
|
||||||
|
|
||||||
typedef void WavpackContext;
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
#define OPEN_WVC 0x1 // open/read "correction" file
|
|
||||||
#define OPEN_TAGS 0x2 // read ID3v1 / APEv2 tags (seekable file)
|
|
||||||
#define OPEN_WRAPPER 0x4 // make audio wrapper available (i.e. RIFF)
|
|
||||||
#define OPEN_2CH_MAX 0x8 // open multichannel as stereo (no downmix)
|
|
||||||
#define OPEN_NORMALIZE 0x10 // normalize floating point data to +/- 1.0
|
|
||||||
#define OPEN_STREAMING 0x20 // "streaming" mode blindly unpacks blocks
|
|
||||||
// w/o regard to header file position info
|
|
||||||
#define OPEN_EDIT_TAGS 0x40 // allow editing of tags
|
|
||||||
|
|
||||||
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
|
|
||||||
#define MODE_APETAG 0x100
|
|
||||||
#define MODE_SFX 0x200
|
|
||||||
|
|
||||||
int WavpackGetVersion (WavpackContext *wpc);
|
|
||||||
uint32_t WavpackUnpackSamples (WavpackContext *wpc, int32_t *buffer, uint32_t samples);
|
|
||||||
uint32_t WavpackGetNumSamples (WavpackContext *wpc);
|
|
||||||
uint32_t WavpackGetSampleIndex (WavpackContext *wpc);
|
|
||||||
int WavpackGetNumErrors (WavpackContext *wpc);
|
|
||||||
int WavpackLossyBlocks (WavpackContext *wpc);
|
|
||||||
int WavpackSeekSample (WavpackContext *wpc, uint32_t sample);
|
|
||||||
WavpackContext *WavpackCloseFile (WavpackContext *wpc);
|
|
||||||
uint32_t WavpackGetSampleRate (WavpackContext *wpc);
|
|
||||||
int WavpackGetBitsPerSample (WavpackContext *wpc);
|
|
||||||
int WavpackGetBytesPerSample (WavpackContext *wpc);
|
|
||||||
int WavpackGetNumChannels (WavpackContext *wpc);
|
|
||||||
int WavpackGetReducedChannels (WavpackContext *wpc);
|
|
||||||
int WavpackGetFloatNormExp (WavpackContext *wpc);
|
|
||||||
int WavpackGetMD5Sum (WavpackContext *wpc, uchar data [16]);
|
|
||||||
uint32_t WavpackGetWrapperBytes (WavpackContext *wpc);
|
|
||||||
uchar *WavpackGetWrapperData (WavpackContext *wpc);
|
|
||||||
void WavpackFreeWrapper (WavpackContext *wpc);
|
|
||||||
double WavpackGetProgress (WavpackContext *wpc);
|
|
||||||
uint32_t WavpackGetFileSize (WavpackContext *wpc);
|
|
||||||
double WavpackGetRatio (WavpackContext *wpc);
|
|
||||||
double WavpackGetAverageBitrate (WavpackContext *wpc, int count_wvc);
|
|
||||||
double WavpackGetInstantBitrate (WavpackContext *wpc);
|
|
||||||
int WavpackGetNumTagItems (WavpackContext *wpc);
|
|
||||||
int WavpackGetTagItem (WavpackContext *wpc, const char *item, char *value, int size);
|
|
||||||
int WavpackGetTagItemIndexed (WavpackContext *wpc, int index, char *item, int size);
|
|
||||||
int WavpackAppendTagItem (WavpackContext *wpc, const char *item, const char *value, int vsize);
|
|
||||||
int WavpackDeleteTagItem (WavpackContext *wpc, const char *item);
|
|
||||||
int WavpackWriteTag (WavpackContext *wpc);
|
|
||||||
|
|
||||||
|
|
||||||
WavpackContext *WavpackOpenFileOutput (WavpackBlockOutput blockout, void *wv_id, void *wvc_id);
|
|
||||||
int WavpackSetConfiguration (WavpackContext *wpc, WavpackConfig *config, uint32_t total_samples);
|
|
||||||
int WavpackAddWrapper (WavpackContext *wpc, void *data, uint32_t bcount);
|
|
||||||
int WavpackStoreMD5Sum (WavpackContext *wpc, uchar data [16]);
|
|
||||||
int WavpackPackInit (WavpackContext *wpc);
|
|
||||||
int WavpackPackSamples (WavpackContext *wpc, int32_t *sample_buffer, uint32_t sample_count);
|
|
||||||
int WavpackFlushSamples (WavpackContext *wpc);
|
|
||||||
void WavpackUpdateNumSamples (WavpackContext *wpc, void *first_block);
|
|
||||||
void *WavpackGetWrapperLocation (void *first_block, uint32_t *size);
|
|
||||||
|
|
||||||
// this function is not actually in wputils.c, but is generally useful
|
|
||||||
|
|
||||||
void float_normalize (int32_t *values, int32_t num_values, int delta_exp);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
File diff suppressed because it is too large
Load Diff
|
@ -7,11 +7,15 @@
|
||||||
objects = {
|
objects = {
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
|
83DD1DD017FA038A00249519 /* utils.h in Headers */ = {isa = PBXBuildFile; fileRef = 83DD1DCD17FA038A00249519 /* utils.h */; };
|
||||||
|
83DD1DD117FA038A00249519 /* wavpack_local.h in Headers */ = {isa = PBXBuildFile; fileRef = 83DD1DCE17FA038A00249519 /* wavpack_local.h */; };
|
||||||
|
83DD1DD217FA038A00249519 /* wavpack_version.h in Headers */ = {isa = PBXBuildFile; fileRef = 83DD1DCF17FA038A00249519 /* wavpack_version.h */; };
|
||||||
|
83DD1DD417FA03F900249519 /* tags.c in Sources */ = {isa = PBXBuildFile; fileRef = 83DD1DD317FA03F900249519 /* tags.c */; };
|
||||||
|
83DD1DD517FA04E100249519 /* wavpack.c in Sources */ = {isa = PBXBuildFile; fileRef = 8E7574C109F31BD50080F1EE /* wavpack.c */; };
|
||||||
8DC2EF530486A6940098B216 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C1666FE841158C02AAC07 /* InfoPlist.strings */; };
|
8DC2EF530486A6940098B216 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C1666FE841158C02AAC07 /* InfoPlist.strings */; };
|
||||||
8E7574B309F31BB90080F1EE /* md5.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E7574AF09F31BB90080F1EE /* md5.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
8E7574B309F31BB90080F1EE /* md5.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E7574AF09F31BB90080F1EE /* md5.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||||
8E7574B409F31BB90080F1EE /* unpack3.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E7574B009F31BB90080F1EE /* unpack3.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
8E7574B409F31BB90080F1EE /* unpack3.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E7574B009F31BB90080F1EE /* unpack3.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||||
8E7574B509F31BB90080F1EE /* wavpack.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E7574B109F31BB90080F1EE /* wavpack.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
8E7574B509F31BB90080F1EE /* wavpack.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E7574B109F31BB90080F1EE /* wavpack.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||||
8E7574B609F31BB90080F1EE /* wputils.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E7574B209F31BB90080F1EE /* wputils.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
|
||||||
8E7574C509F31BD50080F1EE /* bits.c in Sources */ = {isa = PBXBuildFile; fileRef = 8E7574B709F31BD50080F1EE /* bits.c */; };
|
8E7574C509F31BD50080F1EE /* bits.c in Sources */ = {isa = PBXBuildFile; fileRef = 8E7574B709F31BD50080F1EE /* bits.c */; };
|
||||||
8E7574C609F31BD50080F1EE /* extra1.c in Sources */ = {isa = PBXBuildFile; fileRef = 8E7574B809F31BD50080F1EE /* extra1.c */; };
|
8E7574C609F31BD50080F1EE /* extra1.c in Sources */ = {isa = PBXBuildFile; fileRef = 8E7574B809F31BD50080F1EE /* extra1.c */; };
|
||||||
8E7574C709F31BD50080F1EE /* extra2.c in Sources */ = {isa = PBXBuildFile; fileRef = 8E7574B909F31BD50080F1EE /* extra2.c */; };
|
8E7574C709F31BD50080F1EE /* extra2.c in Sources */ = {isa = PBXBuildFile; fileRef = 8E7574B909F31BD50080F1EE /* extra2.c */; };
|
||||||
|
@ -29,12 +33,15 @@
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
089C1667FE841158C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
089C1667FE841158C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||||
|
83DD1DCD17FA038A00249519 /* utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = utils.h; path = Files/utils.h; sourceTree = "<group>"; };
|
||||||
|
83DD1DCE17FA038A00249519 /* wavpack_local.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = wavpack_local.h; path = Files/wavpack_local.h; sourceTree = "<group>"; };
|
||||||
|
83DD1DCF17FA038A00249519 /* wavpack_version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = wavpack_version.h; path = Files/wavpack_version.h; sourceTree = "<group>"; };
|
||||||
|
83DD1DD317FA03F900249519 /* tags.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = tags.c; path = Files/tags.c; sourceTree = "<group>"; };
|
||||||
8DC2EF5A0486A6940098B216 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
|
8DC2EF5A0486A6940098B216 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
|
||||||
8DC2EF5B0486A6940098B216 /* WavPack.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = WavPack.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
8DC2EF5B0486A6940098B216 /* WavPack.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = WavPack.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
8E7574AF09F31BB90080F1EE /* md5.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = md5.h; path = Files/md5.h; sourceTree = "<group>"; };
|
8E7574AF09F31BB90080F1EE /* md5.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = md5.h; path = Files/md5.h; sourceTree = "<group>"; };
|
||||||
8E7574B009F31BB90080F1EE /* unpack3.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = unpack3.h; path = Files/unpack3.h; sourceTree = "<group>"; };
|
8E7574B009F31BB90080F1EE /* unpack3.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = unpack3.h; path = Files/unpack3.h; sourceTree = "<group>"; };
|
||||||
8E7574B109F31BB90080F1EE /* wavpack.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = wavpack.h; path = Files/wavpack.h; sourceTree = "<group>"; };
|
8E7574B109F31BB90080F1EE /* wavpack.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = wavpack.h; path = Files/wavpack.h; sourceTree = "<group>"; };
|
||||||
8E7574B209F31BB90080F1EE /* wputils.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = wputils.h; path = Files/wputils.h; sourceTree = "<group>"; };
|
|
||||||
8E7574B709F31BD50080F1EE /* bits.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = bits.c; path = Files/bits.c; sourceTree = "<group>"; };
|
8E7574B709F31BD50080F1EE /* bits.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = bits.c; path = Files/bits.c; sourceTree = "<group>"; };
|
||||||
8E7574B809F31BD50080F1EE /* extra1.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = extra1.c; path = Files/extra1.c; sourceTree = "<group>"; };
|
8E7574B809F31BD50080F1EE /* extra1.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = extra1.c; path = Files/extra1.c; sourceTree = "<group>"; };
|
||||||
8E7574B909F31BD50080F1EE /* extra2.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = extra2.c; path = Files/extra2.c; sourceTree = "<group>"; };
|
8E7574B909F31BD50080F1EE /* extra2.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = extra2.c; path = Files/extra2.c; sourceTree = "<group>"; };
|
||||||
|
@ -120,6 +127,7 @@
|
||||||
8E7574A809F31B940080F1EE /* Source */ = {
|
8E7574A809F31B940080F1EE /* Source */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
83DD1DD317FA03F900249519 /* tags.c */,
|
||||||
8E7574B709F31BD50080F1EE /* bits.c */,
|
8E7574B709F31BD50080F1EE /* bits.c */,
|
||||||
8E7574B809F31BD50080F1EE /* extra1.c */,
|
8E7574B809F31BD50080F1EE /* extra1.c */,
|
||||||
8E7574B909F31BD50080F1EE /* extra2.c */,
|
8E7574B909F31BD50080F1EE /* extra2.c */,
|
||||||
|
@ -141,10 +149,12 @@
|
||||||
8E7574A909F31B9A0080F1EE /* Headers */ = {
|
8E7574A909F31B9A0080F1EE /* Headers */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
83DD1DCD17FA038A00249519 /* utils.h */,
|
||||||
|
83DD1DCE17FA038A00249519 /* wavpack_local.h */,
|
||||||
|
83DD1DCF17FA038A00249519 /* wavpack_version.h */,
|
||||||
8E7574AF09F31BB90080F1EE /* md5.h */,
|
8E7574AF09F31BB90080F1EE /* md5.h */,
|
||||||
8E7574B009F31BB90080F1EE /* unpack3.h */,
|
8E7574B009F31BB90080F1EE /* unpack3.h */,
|
||||||
8E7574B109F31BB90080F1EE /* wavpack.h */,
|
8E7574B109F31BB90080F1EE /* wavpack.h */,
|
||||||
8E7574B209F31BB90080F1EE /* wputils.h */,
|
|
||||||
);
|
);
|
||||||
name = Headers;
|
name = Headers;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -157,9 +167,11 @@
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
8E7574B309F31BB90080F1EE /* md5.h in Headers */,
|
8E7574B309F31BB90080F1EE /* md5.h in Headers */,
|
||||||
|
83DD1DD117FA038A00249519 /* wavpack_local.h in Headers */,
|
||||||
8E7574B409F31BB90080F1EE /* unpack3.h in Headers */,
|
8E7574B409F31BB90080F1EE /* unpack3.h in Headers */,
|
||||||
|
83DD1DD217FA038A00249519 /* wavpack_version.h in Headers */,
|
||||||
|
83DD1DD017FA038A00249519 /* utils.h in Headers */,
|
||||||
8E7574B509F31BB90080F1EE /* wavpack.h in Headers */,
|
8E7574B509F31BB90080F1EE /* wavpack.h in Headers */,
|
||||||
8E7574B609F31BB90080F1EE /* wputils.h in Headers */,
|
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
@ -225,6 +237,8 @@
|
||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
83DD1DD517FA04E100249519 /* wavpack.c in Sources */,
|
||||||
|
83DD1DD417FA03F900249519 /* tags.c in Sources */,
|
||||||
8E7574C509F31BD50080F1EE /* bits.c in Sources */,
|
8E7574C509F31BD50080F1EE /* bits.c in Sources */,
|
||||||
8E7574C609F31BD50080F1EE /* extra1.c in Sources */,
|
8E7574C609F31BD50080F1EE /* extra1.c in Sources */,
|
||||||
8E7574C709F31BD50080F1EE /* extra2.c in Sources */,
|
8E7574C709F31BD50080F1EE /* extra2.c in Sources */,
|
||||||
|
|
Loading…
Reference in New Issue