Updated WavPack to version 4.60.1
parent
63b8f55dcf
commit
43704d16ce
|
@ -1,85 +1,103 @@
|
|||
////////////////////////////////////////////////////////////////////////////
|
||||
// **** WAVPACK **** //
|
||||
// Hybrid Lossless Wavefile Compressor //
|
||||
// Copyright (c) 1998 - 2005 Conifer Software. //
|
||||
// Copyright (c) 1998 - 2006 Conifer Software. //
|
||||
// All Rights Reserved. //
|
||||
// Distributed under the BSD Software License (see license.txt) //
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
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
|
||||
platforms. For example code using the library you might want to check some
|
||||
of the plugin sources in the Windows source release.
|
||||
platforms.
|
||||
|
||||
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
|
||||
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:
|
||||
|
||||
1. This code is designed to be much easier to port to other platforms than
|
||||
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"
|
||||
module. The code is even written to be endian-independent and a compile
|
||||
option is provided to eliminate the DOS-specific directory searches.
|
||||
1. There are two documentation files contained in the distribution:
|
||||
|
||||
doc/library_use.txt contains a detailed description of the API provided
|
||||
by WavPack library appropriate for read and writing
|
||||
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
|
||||
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
|
||||
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
|
||||
3. For WavPack file decoding, a library interface in "wputils.c" provides all
|
||||
the functionality required for both the winamp plugin and the "wvunpack"
|
||||
command-line program (including the transparent decoding of "correction"
|
||||
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
|
||||
to open the "correction" file. It is no longer necessary to manipulate the
|
||||
WavPack structures directly; everything is handled with function calls. In
|
||||
fact, a new header file called "wputils.h" can be used that hides all the
|
||||
WavPack internals from the application.
|
||||
to open the "correction" file. The header file "include/wavpack.h"
|
||||
includes everything needed while hiding all the 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"
|
||||
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
|
||||
accepts completed WavPack blocks. For version 4.2 limited functionality
|
||||
has been added to append APEv2 tags to WavPack files during creation.
|
||||
accepts completed WavPack blocks. It is also possible to append APEv2 tags
|
||||
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
|
||||
the library for the desired application and must be the same for the
|
||||
compilation of ALL files:
|
||||
5. The following #define's can be optionally used to eliminate some functionality
|
||||
to create smaller binaries. It is important that they must be specified
|
||||
the same for the compilation of ALL files:
|
||||
|
||||
UNPACK to unpack audio samples from WavPack files
|
||||
PACK to create WavPack files from raw audio data
|
||||
NO_UNPACK no unpacking of audio samples from WavPack files
|
||||
(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
|
||||
SEEKING to allow seeking to a specific sample index (unpack only)
|
||||
USE_FSTREAMS to open WavPack files by name using fstreams (via fopen)
|
||||
TAGS to read specified fields from ID3v1 and APEv2 tags and
|
||||
(also don't include pack.c, extra1.c and extra2.c)
|
||||
NO_SEEKING to not allow seeking to a specific sample index (unpack only)
|
||||
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
|
||||
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
|
||||
|
||||
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
|
||||
INFO_ONLY: wputils.c unpack.c words.c bits.c metadata.c float.c
|
||||
For applications requiring very low latency, there is a special version of
|
||||
the library that supports a variation on the regular WavPack block format
|
||||
to facilitate this.
|
||||
|
||||
PACK: wputils.c pack.c extra1.c extra2.c
|
||||
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
|
||||
7. Questions or comments should be directed to david@wavpack.com
|
||||
|
|
|
@ -1,259 +1,274 @@
|
|||
////////////////////////////////////////////////////////////////////////////
|
||||
// **** WAVPACK **** //
|
||||
// Hybrid Lossless Wavefile Compressor //
|
||||
// Copyright (c) 1998 - 2005 Conifer Software. //
|
||||
// All Rights Reserved. //
|
||||
// Distributed under the BSD Software License (see license.txt) //
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// bits.c
|
||||
|
||||
// This module provides utilities to support the BitStream structure which is
|
||||
// used to read and write all WavPack audio data streams. It also contains a
|
||||
// wrapper for the stream I/O functions and a set of functions dealing with
|
||||
// endian-ness, both for enhancing portability. Finally, a debug wrapper for
|
||||
// the malloc() system is provided.
|
||||
|
||||
#include "wavpack.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#if defined(WIN32)
|
||||
#include <io.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
////////////////////////// Bitstream functions ////////////////////////////////
|
||||
|
||||
#if defined(UNPACK) || defined(INFO_ONLY)
|
||||
|
||||
// Open the specified BitStream and associate with the specified buffer.
|
||||
|
||||
static void bs_read (Bitstream *bs);
|
||||
|
||||
void bs_open_read (Bitstream *bs, uchar *buffer_start, uchar *buffer_end)
|
||||
{
|
||||
bs->error = bs->sr = bs->bc = 0;
|
||||
bs->ptr = (bs->buf = buffer_start) - 1;
|
||||
bs->end = buffer_end;
|
||||
bs->wrap = bs_read;
|
||||
}
|
||||
|
||||
// This function is only called from the getbit() and getbits() macros when
|
||||
// the BitStream has been exhausted and more data is required. Sinve these
|
||||
// bistreams no longer access files, this function simple sets an error and
|
||||
// resets the buffer.
|
||||
|
||||
static void bs_read (Bitstream *bs)
|
||||
{
|
||||
bs->ptr = bs->buf - 1;
|
||||
bs->error = 1;
|
||||
}
|
||||
|
||||
// This function is called to close the bitstream. It returns the number of
|
||||
// full bytes actually read as bits.
|
||||
|
||||
uint32_t bs_close_read (Bitstream *bs)
|
||||
{
|
||||
uint32_t bytes_read;
|
||||
|
||||
if (bs->bc < 8)
|
||||
bs->ptr++;
|
||||
|
||||
if ((bs->buf - bs->ptr) & 1)
|
||||
bs->ptr++;
|
||||
|
||||
bytes_read = bs->ptr - bs->buf;
|
||||
CLEAR (*bs);
|
||||
return bytes_read;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef PACK
|
||||
|
||||
// Open the specified BitStream using the specified buffer pointers. It is
|
||||
// assumed that enough buffer space has been allocated for all data that will
|
||||
// be written, otherwise an error will be generated.
|
||||
|
||||
static void bs_write (Bitstream *bs);
|
||||
|
||||
void bs_open_write (Bitstream *bs, uchar *buffer_start, uchar *buffer_end)
|
||||
{
|
||||
bs->error = bs->sr = bs->bc = 0;
|
||||
bs->ptr = bs->buf = buffer_start;
|
||||
bs->end = buffer_end;
|
||||
bs->wrap = bs_write;
|
||||
}
|
||||
|
||||
// This function is only called from the putbit() and putbits() macros when
|
||||
// the buffer is full, which is now flagged as an error.
|
||||
|
||||
static void bs_write (Bitstream *bs)
|
||||
{
|
||||
bs->ptr = bs->buf;
|
||||
bs->error = 1;
|
||||
}
|
||||
|
||||
// This function forces a flushing write of the specified BitStream, and
|
||||
// returns the total number of bytes written into the buffer.
|
||||
|
||||
uint32_t bs_close_write (Bitstream *bs)
|
||||
{
|
||||
uint32_t bytes_written;
|
||||
|
||||
if (bs->error)
|
||||
return (uint32_t) -1;
|
||||
|
||||
while (bs->bc || ((bs->ptr - bs->buf) & 1)) putbit_1 (bs);
|
||||
bytes_written = bs->ptr - bs->buf;
|
||||
CLEAR (*bs);
|
||||
return bytes_written;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/////////////////////// Endian Correction Routines ////////////////////////////
|
||||
|
||||
void little_endian_to_native (void *data, char *format)
|
||||
{
|
||||
uchar *cp = (uchar *) data;
|
||||
int32_t temp;
|
||||
|
||||
while (*format) {
|
||||
switch (*format) {
|
||||
case 'L':
|
||||
temp = cp [0] + ((int32_t) cp [1] << 8) + ((int32_t) cp [2] << 16) + ((int32_t) cp [3] << 24);
|
||||
* (int32_t *) cp = temp;
|
||||
cp += 4;
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
temp = cp [0] + (cp [1] << 8);
|
||||
* (short *) cp = (short) temp;
|
||||
cp += 2;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (isdigit (*format))
|
||||
cp += *format - '0';
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
format++;
|
||||
}
|
||||
}
|
||||
|
||||
void native_to_little_endian (void *data, char *format)
|
||||
{
|
||||
uchar *cp = (uchar *) data;
|
||||
int32_t temp;
|
||||
|
||||
while (*format) {
|
||||
switch (*format) {
|
||||
case 'L':
|
||||
temp = * (int32_t *) cp;
|
||||
*cp++ = (uchar) temp;
|
||||
*cp++ = (uchar) (temp >> 8);
|
||||
*cp++ = (uchar) (temp >> 16);
|
||||
*cp++ = (uchar) (temp >> 24);
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
temp = * (short *) cp;
|
||||
*cp++ = (uchar) temp;
|
||||
*cp++ = (uchar) (temp >> 8);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (isdigit (*format))
|
||||
cp += *format - '0';
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
format++;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////// Debug Wrapper for Malloc ///////////////////////////
|
||||
|
||||
#ifdef DEBUG_ALLOC
|
||||
|
||||
void *vptrs [512];
|
||||
|
||||
static void *add_ptr (void *ptr)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 512; ++i)
|
||||
if (!vptrs [i]) {
|
||||
vptrs [i] = ptr;
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == 512)
|
||||
error_line ("too many mallocs!");
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static void *del_ptr (void *ptr)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 512; ++i)
|
||||
if (vptrs [i] == ptr) {
|
||||
vptrs [i] = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == 512)
|
||||
error_line ("free invalid ptr!");
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void *malloc_db (uint32_t size)
|
||||
{
|
||||
if (size)
|
||||
return add_ptr (malloc (size));
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void free_db (void *ptr)
|
||||
{
|
||||
if (ptr)
|
||||
free (del_ptr (ptr));
|
||||
}
|
||||
|
||||
void *realloc_db (void *ptr, uint32_t size)
|
||||
{
|
||||
if (ptr && size)
|
||||
return add_ptr (realloc (del_ptr (ptr), size));
|
||||
else if (size)
|
||||
return malloc_db (size);
|
||||
else
|
||||
free_db (ptr);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int32_t dump_alloc (void)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (j = i = 0; i < 512; ++i)
|
||||
if (vptrs [i])
|
||||
j++;
|
||||
|
||||
return j;
|
||||
}
|
||||
|
||||
#endif
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// **** WAVPACK **** //
|
||||
// Hybrid Lossless Wavefile Compressor //
|
||||
// Copyright (c) 1998 - 2006 Conifer Software. //
|
||||
// All Rights Reserved. //
|
||||
// Distributed under the BSD Software License (see license.txt) //
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// bits.c
|
||||
|
||||
// This module provides utilities to support the BitStream structure which is
|
||||
// used to read and write all WavPack audio data streams. It also contains a
|
||||
// wrapper for the stream I/O functions and a set of functions dealing with
|
||||
// endian-ness, both for enhancing portability. Finally, a debug wrapper for
|
||||
// the malloc() system is provided.
|
||||
|
||||
#include "wavpack_local.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#if defined(WIN32)
|
||||
#include <io.h>
|
||||
#else
|
||||
#if defined(__OS2__)
|
||||
#include <io.h>
|
||||
#endif
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
////////////////////////// Bitstream functions ////////////////////////////////
|
||||
|
||||
#if !defined(NO_UNPACK) || defined(INFO_ONLY)
|
||||
|
||||
// Open the specified BitStream and associate with the specified buffer.
|
||||
|
||||
static void bs_read (Bitstream *bs);
|
||||
|
||||
void bs_open_read (Bitstream *bs, void *buffer_start, void *buffer_end)
|
||||
{
|
||||
bs->error = bs->sr = bs->bc = 0;
|
||||
bs->ptr = (bs->buf = buffer_start) - 1;
|
||||
bs->end = buffer_end;
|
||||
bs->wrap = bs_read;
|
||||
}
|
||||
|
||||
// This function is only called from the getbit() and getbits() macros when
|
||||
// the BitStream has been exhausted and more data is required. Sinve these
|
||||
// bistreams no longer access files, this function simple sets an error and
|
||||
// resets the buffer.
|
||||
|
||||
static void bs_read (Bitstream *bs)
|
||||
{
|
||||
bs->ptr = bs->buf - 1;
|
||||
bs->error = 1;
|
||||
}
|
||||
|
||||
// This function is called to close the bitstream. It returns the number of
|
||||
// full bytes actually read as bits.
|
||||
|
||||
uint32_t bs_close_read (Bitstream *bs)
|
||||
{
|
||||
uint32_t bytes_read;
|
||||
|
||||
if (bs->bc < sizeof (*(bs->ptr)) * 8)
|
||||
bs->ptr++;
|
||||
|
||||
bytes_read = (uint32_t)(bs->ptr - bs->buf) * sizeof (*(bs->ptr));
|
||||
|
||||
if (!(bytes_read & 1))
|
||||
++bytes_read;
|
||||
|
||||
CLEAR (*bs);
|
||||
return bytes_read;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef NO_PACK
|
||||
|
||||
// Open the specified BitStream using the specified buffer pointers. It is
|
||||
// assumed that enough buffer space has been allocated for all data that will
|
||||
// be written, otherwise an error will be generated.
|
||||
|
||||
static void bs_write (Bitstream *bs);
|
||||
|
||||
void bs_open_write (Bitstream *bs, void *buffer_start, void *buffer_end)
|
||||
{
|
||||
bs->error = bs->sr = bs->bc = 0;
|
||||
bs->ptr = bs->buf = buffer_start;
|
||||
bs->end = buffer_end;
|
||||
bs->wrap = bs_write;
|
||||
}
|
||||
|
||||
// This function is only called from the putbit() and putbits() macros when
|
||||
// the buffer is full, which is now flagged as an error.
|
||||
|
||||
static void bs_write (Bitstream *bs)
|
||||
{
|
||||
bs->ptr = bs->buf;
|
||||
bs->error = 1;
|
||||
}
|
||||
|
||||
// This function forces a flushing write of the specified BitStream, and
|
||||
// returns the total number of bytes written into the buffer.
|
||||
|
||||
uint32_t bs_close_write (Bitstream *bs)
|
||||
{
|
||||
uint32_t bytes_written;
|
||||
|
||||
if (bs->error)
|
||||
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;
|
||||
};
|
||||
|
||||
CLEAR (*bs);
|
||||
return bytes_written;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/////////////////////// Endian Correction Routines ////////////////////////////
|
||||
|
||||
void little_endian_to_native (void *data, char *format)
|
||||
{
|
||||
unsigned char *cp = (unsigned char *) data;
|
||||
int32_t temp;
|
||||
|
||||
while (*format) {
|
||||
switch (*format) {
|
||||
case 'L':
|
||||
temp = cp [0] + ((int32_t) cp [1] << 8) + ((int32_t) cp [2] << 16) + ((int32_t) cp [3] << 24);
|
||||
* (int32_t *) cp = temp;
|
||||
cp += 4;
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
temp = cp [0] + (cp [1] << 8);
|
||||
* (short *) cp = (short) temp;
|
||||
cp += 2;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (isdigit (*format))
|
||||
cp += *format - '0';
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
format++;
|
||||
}
|
||||
}
|
||||
|
||||
void native_to_little_endian (void *data, char *format)
|
||||
{
|
||||
unsigned char *cp = (unsigned char *) data;
|
||||
int32_t temp;
|
||||
|
||||
while (*format) {
|
||||
switch (*format) {
|
||||
case 'L':
|
||||
temp = * (int32_t *) cp;
|
||||
*cp++ = (unsigned char) temp;
|
||||
*cp++ = (unsigned char) (temp >> 8);
|
||||
*cp++ = (unsigned char) (temp >> 16);
|
||||
*cp++ = (unsigned char) (temp >> 24);
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
temp = * (short *) cp;
|
||||
*cp++ = (unsigned char) temp;
|
||||
*cp++ = (unsigned char) (temp >> 8);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (isdigit (*format))
|
||||
cp += *format - '0';
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
format++;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////// Debug Wrapper for Malloc ///////////////////////////
|
||||
|
||||
#ifdef DEBUG_ALLOC
|
||||
|
||||
void *vptrs [512];
|
||||
|
||||
static void *add_ptr (void *ptr)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 512; ++i)
|
||||
if (!vptrs [i]) {
|
||||
vptrs [i] = ptr;
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == 512)
|
||||
error_line ("too many mallocs!");
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static void *del_ptr (void *ptr)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 512; ++i)
|
||||
if (vptrs [i] == ptr) {
|
||||
vptrs [i] = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == 512)
|
||||
error_line ("free invalid ptr!");
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void *malloc_db (uint32_t size)
|
||||
{
|
||||
if (size)
|
||||
return add_ptr (malloc (size));
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void free_db (void *ptr)
|
||||
{
|
||||
if (ptr)
|
||||
free (del_ptr (ptr));
|
||||
}
|
||||
|
||||
void *realloc_db (void *ptr, uint32_t size)
|
||||
{
|
||||
if (ptr && size)
|
||||
return add_ptr (realloc (del_ptr (ptr), size));
|
||||
else if (size)
|
||||
return malloc_db (size);
|
||||
else
|
||||
free_db (ptr);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int32_t dump_alloc (void)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (j = i = 0; i < 512; ++i)
|
||||
if (vptrs [i])
|
||||
j++;
|
||||
|
||||
return j;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#! /bin/sh
|
||||
# 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.
|
||||
# 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
|
||||
# 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
|
||||
# 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)
|
||||
AM_INIT_AUTOMAKE(wavpack, 4.32, bryant@wavpack.com)
|
||||
AC_CONFIG_SRCDIR([pack.c])
|
||||
AC_INIT(wavpack, 4.60.1, bryant@wavpack.com)
|
||||
AM_INIT_AUTOMAKE(wavpack, 4.60.1, bryant@wavpack.com)
|
||||
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
|
||||
VERSION_OS=$(uname -s)
|
||||
|
@ -13,18 +37,28 @@ AC_C_BIGENDIAN(AC_DEFINE([HIGHFIRST], [1], [big-endian machine]))
|
|||
|
||||
# Checks for programs.
|
||||
AC_PROG_CC
|
||||
AC_LIBTOOL_WIN32_DLL
|
||||
AC_PROG_LIBTOOL
|
||||
AC_PROG_INSTALL
|
||||
AM_PROG_CC_C_O
|
||||
|
||||
AC_HEADER_STDC
|
||||
|
||||
# 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
|
||||
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
|
||||
AC_MSG_ERROR([[Sorry, you can't deactivate iconv.]])
|
||||
else
|
||||
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"
|
||||
fi
|
||||
|
||||
|
@ -35,13 +69,12 @@ else
|
|||
iconv_t cd = iconv_open ("","");
|
||||
iconv (cd, NULL, NULL, NULL, NULL);],[
|
||||
AC_MSG_RESULT(yes)
|
||||
WITH_ICONV=1
|
||||
ICONV=""],[
|
||||
WITH_ICONV=1],[
|
||||
AC_MSG_RESULT(no)
|
||||
AC_MSG_CHECKING(for iconv in -liconv)
|
||||
|
||||
_ldflags="${LDFLAGS}"
|
||||
_libs="${LIBS}"
|
||||
old_ldflags="${LDFLAGS}"
|
||||
old_libs="${LIBS}"
|
||||
LDFLAGS="${LDFLAGS} ${ICONV_LIBS}"
|
||||
LIBS="${LIBS} -liconv"
|
||||
|
||||
|
@ -52,11 +85,51 @@ iconv (cd, NULL, NULL, NULL, NULL);],[
|
|||
AC_MSG_RESULT(yes)
|
||||
WITH_ICONV=1
|
||||
ICONV_LIBS="${ICONV_LIBS} -liconv"
|
||||
ICONV="${ICONV_LIBS}"],[
|
||||
AC_MSG_ERROR([[Can't find iconv libraries.]])])]),
|
||||
AC_MSG_ERROR([[Can't find iconv headers.]]))
|
||||
ICONV="-liconv"],[
|
||||
AC_MSG_ERROR([[Can't find iconv libraries.]])])
|
||||
LDFLAGS=$old_ldflags
|
||||
LIBS=$old_libs
|
||||
]),
|
||||
AC_MSG_ERROR([[Can't find iconv headers.]]))
|
||||
fi
|
||||
AC_SUBST(ICONV)
|
||||
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
|
||||
# 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
|
||||
# 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
|
||||
# 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
|
||||
# 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
|
||||
## we want. Yay! Note: for some reason libtool 1.4 doesn't like
|
||||
## 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=$?
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
|
@ -201,34 +215,39 @@ aix)
|
|||
# current directory. Also, the AIX compiler puts `$object:' at the
|
||||
# start of each line; $object doesn't have directory information.
|
||||
# Version 6 uses the directory in both cases.
|
||||
stripped=`echo "$object" | sed 's/\(.*\)\..*$/\1/'`
|
||||
tmpdepfile="$stripped.u"
|
||||
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.u
|
||||
tmpdepfile2=$base.u
|
||||
tmpdepfile3=$dir.libs/$base.u
|
||||
"$@" -Wc,-M
|
||||
else
|
||||
tmpdepfile1=$dir$base.u
|
||||
tmpdepfile2=$dir$base.u
|
||||
tmpdepfile3=$dir$base.u
|
||||
"$@" -M
|
||||
fi
|
||||
stat=$?
|
||||
|
||||
if test -f "$tmpdepfile"; then :
|
||||
else
|
||||
stripped=`echo "$stripped" | sed 's,^.*/,,'`
|
||||
tmpdepfile="$stripped.u"
|
||||
fi
|
||||
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
rm -f "$tmpdepfile"
|
||||
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||
exit $stat
|
||||
fi
|
||||
|
||||
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||
do
|
||||
test -f "$tmpdepfile" && break
|
||||
done
|
||||
if test -f "$tmpdepfile"; then
|
||||
outname="$stripped.o"
|
||||
# Each line is of the form `foo.o: dependent.h'.
|
||||
# Do two passes, one to just change these to
|
||||
# `$object: dependent.h' and one to simply `dependent.h:'.
|
||||
sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile"
|
||||
sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile"
|
||||
sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
|
||||
# That's a tab and a space in the [].
|
||||
sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
|
||||
else
|
||||
# The sourcefile does not contain any dependencies, so just
|
||||
# store a dummy comment line, to avoid errors with the Makefile
|
||||
|
@ -276,6 +295,46 @@ icc)
|
|||
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)
|
||||
# The Tru64 compiler uses -MD to generate dependencies as a side
|
||||
# effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'.
|
||||
|
@ -288,13 +347,13 @@ tru64)
|
|||
|
||||
if test "$libtool" = yes; then
|
||||
# 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.
|
||||
# With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d.
|
||||
#
|
||||
# With libtool 1.5 this exception was removed, and libtool now
|
||||
# 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
|
||||
# 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
|
||||
|
@ -467,7 +526,8 @@ cpp)
|
|||
done
|
||||
|
||||
"$@" -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"
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
|
|
File diff suppressed because it is too large
Load Diff
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,371 +1,371 @@
|
|||
////////////////////////////////////////////////////////////////////////////
|
||||
// **** WAVPACK **** //
|
||||
// Hybrid Lossless Wavefile Compressor //
|
||||
// Copyright (c) 1998 - 2005 Conifer Software. //
|
||||
// All Rights Reserved. //
|
||||
// Distributed under the BSD Software License (see license.txt) //
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// float.c
|
||||
|
||||
#include "wavpack.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef DEBUG_ALLOC
|
||||
#define malloc malloc_db
|
||||
#define realloc realloc_db
|
||||
#define free free_db
|
||||
void *malloc_db (uint32_t size);
|
||||
void *realloc_db (void *ptr, uint32_t size);
|
||||
void free_db (void *ptr);
|
||||
int32_t dump_alloc (void);
|
||||
#endif
|
||||
|
||||
#ifdef PACK
|
||||
|
||||
void write_float_info (WavpackStream *wps, WavpackMetadata *wpmd)
|
||||
{
|
||||
char *byteptr;
|
||||
|
||||
byteptr = wpmd->data = malloc (4);
|
||||
wpmd->id = ID_FLOAT_INFO;
|
||||
*byteptr++ = wps->float_flags;
|
||||
*byteptr++ = wps->float_shift;
|
||||
*byteptr++ = wps->float_max_exp;
|
||||
*byteptr++ = wps->float_norm_exp;
|
||||
wpmd->byte_length = byteptr - (char *) wpmd->data;
|
||||
}
|
||||
|
||||
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 false_zeros = 0, neg_zeros = 0;
|
||||
uint32_t ordata = 0, crc = 0xffffffff;
|
||||
int max_exp = 0, shift_count;
|
||||
int32_t count, value;
|
||||
f32 *dp;
|
||||
|
||||
wps->float_shift = wps->float_flags = 0;
|
||||
|
||||
for (dp = values, count = num_values; count--; dp++) {
|
||||
crc = crc * 27 + dp->mantissa * 9 + dp->exponent * 3 + dp->sign;
|
||||
|
||||
if (dp->exponent > max_exp && dp->exponent < 255)
|
||||
max_exp = dp->exponent;
|
||||
}
|
||||
|
||||
wps->crc_x = crc;
|
||||
|
||||
for (dp = values, count = num_values; count--; dp++) {
|
||||
if (dp->exponent == 255) {
|
||||
wps->float_flags |= FLOAT_EXCEPTIONS;
|
||||
value = 0x1000000;
|
||||
shift_count = 0;
|
||||
}
|
||||
else if (dp->exponent) {
|
||||
shift_count = max_exp - dp->exponent;
|
||||
value = 0x800000 + dp->mantissa;
|
||||
}
|
||||
else {
|
||||
shift_count = max_exp ? max_exp - 1 : 0;
|
||||
value = dp->mantissa;
|
||||
|
||||
// if (dp->mantissa)
|
||||
// denormals++;
|
||||
}
|
||||
|
||||
if (shift_count < 25)
|
||||
value >>= shift_count;
|
||||
else
|
||||
value = 0;
|
||||
|
||||
if (!value) {
|
||||
if (dp->exponent || dp->mantissa)
|
||||
++false_zeros;
|
||||
else if (dp->sign)
|
||||
++neg_zeros;
|
||||
}
|
||||
else if (shift_count) {
|
||||
int32_t mask = (1 << shift_count) - 1;
|
||||
|
||||
if (!(dp->mantissa & mask))
|
||||
shifted_zeros++;
|
||||
else if ((dp->mantissa & mask) == mask)
|
||||
shifted_ones++;
|
||||
else
|
||||
shifted_both++;
|
||||
}
|
||||
|
||||
ordata |= value;
|
||||
* (int32_t *) dp = (dp->sign) ? -value : value;
|
||||
}
|
||||
|
||||
wps->float_max_exp = max_exp;
|
||||
|
||||
if (shifted_both)
|
||||
wps->float_flags |= FLOAT_SHIFT_SENT;
|
||||
else if (shifted_ones && !shifted_zeros)
|
||||
wps->float_flags |= FLOAT_SHIFT_ONES;
|
||||
else if (shifted_ones && shifted_zeros)
|
||||
wps->float_flags |= FLOAT_SHIFT_SAME;
|
||||
else if (ordata && !(ordata & 1)) {
|
||||
while (!(ordata & 1)) {
|
||||
wps->float_shift++;
|
||||
ordata >>= 1;
|
||||
}
|
||||
|
||||
for (dp = values, count = num_values; count--; dp++)
|
||||
* (int32_t *) dp >>= wps->float_shift;
|
||||
}
|
||||
|
||||
wps->wphdr.flags &= ~MAG_MASK;
|
||||
|
||||
while (ordata) {
|
||||
wps->wphdr.flags += 1 << MAG_LSB;
|
||||
ordata >>= 1;
|
||||
}
|
||||
|
||||
if (false_zeros || neg_zeros)
|
||||
wps->float_flags |= FLOAT_ZEROS_SENT;
|
||||
|
||||
if (neg_zeros)
|
||||
wps->float_flags |= FLOAT_NEG_ZEROS;
|
||||
|
||||
// error_line ("samples = %d, max exp = %d, pre-shift = %d, denormals = %d",
|
||||
// num_values, max_exp, wps->float_shift, denormals);
|
||||
// if (wps->float_flags & FLOAT_EXCEPTIONS)
|
||||
// error_line ("exceptions!");
|
||||
// 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);
|
||||
|
||||
return wps->float_flags & (FLOAT_EXCEPTIONS | FLOAT_ZEROS_SENT | FLOAT_SHIFT_SENT | FLOAT_SHIFT_SAME);
|
||||
}
|
||||
|
||||
void send_float_data (WavpackStream *wps, f32 *values, int32_t num_values)
|
||||
{
|
||||
int max_exp = wps->float_max_exp;
|
||||
int32_t count, value, shift_count;
|
||||
f32 *dp;
|
||||
|
||||
for (dp = values, count = num_values; count--; dp++) {
|
||||
if (dp->exponent == 255) {
|
||||
if (dp->mantissa) {
|
||||
putbit_1 (&wps->wvxbits);
|
||||
putbits (dp->mantissa, 23, &wps->wvxbits);
|
||||
}
|
||||
else {
|
||||
putbit_0 (&wps->wvxbits);
|
||||
}
|
||||
|
||||
value = 0x1000000;
|
||||
shift_count = 0;
|
||||
}
|
||||
else if (dp->exponent) {
|
||||
shift_count = max_exp - dp->exponent;
|
||||
value = 0x800000 + dp->mantissa;
|
||||
}
|
||||
else {
|
||||
shift_count = max_exp ? max_exp - 1 : 0;
|
||||
value = dp->mantissa;
|
||||
}
|
||||
|
||||
if (shift_count < 25)
|
||||
value >>= shift_count;
|
||||
else
|
||||
value = 0;
|
||||
|
||||
if (!value) {
|
||||
if (wps->float_flags & FLOAT_ZEROS_SENT) {
|
||||
if (dp->exponent || dp->mantissa) {
|
||||
putbit_1 (&wps->wvxbits);
|
||||
putbits (dp->mantissa, 23, &wps->wvxbits);
|
||||
|
||||
if (max_exp >= 25) {
|
||||
putbits (dp->exponent, 8, &wps->wvxbits);
|
||||
}
|
||||
|
||||
putbit (dp->sign, &wps->wvxbits);
|
||||
}
|
||||
else {
|
||||
putbit_0 (&wps->wvxbits);
|
||||
|
||||
if (wps->float_flags & FLOAT_NEG_ZEROS)
|
||||
putbit (dp->sign, &wps->wvxbits);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (shift_count) {
|
||||
if (wps->float_flags & FLOAT_SHIFT_SENT) {
|
||||
int32_t data = dp->mantissa & ((1 << shift_count) - 1);
|
||||
putbits (data, shift_count, &wps->wvxbits);
|
||||
}
|
||||
else if (wps->float_flags & FLOAT_SHIFT_SAME) {
|
||||
putbit (dp->mantissa & 1, &wps->wvxbits);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(UNPACK) || defined(INFO_ONLY)
|
||||
|
||||
int read_float_info (WavpackStream *wps, WavpackMetadata *wpmd)
|
||||
{
|
||||
int bytecnt = wpmd->byte_length;
|
||||
char *byteptr = wpmd->data;
|
||||
|
||||
if (bytecnt != 4)
|
||||
return FALSE;
|
||||
|
||||
wps->float_flags = *byteptr++;
|
||||
wps->float_shift = *byteptr++;
|
||||
wps->float_max_exp = *byteptr++;
|
||||
wps->float_norm_exp = *byteptr;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef UNPACK
|
||||
|
||||
static void float_values_nowvx (WavpackStream *wps, int32_t *values, int32_t num_values);
|
||||
|
||||
void float_values (WavpackStream *wps, int32_t *values, int32_t num_values)
|
||||
{
|
||||
uint32_t crc = wps->crc_x;
|
||||
|
||||
if (!bs_is_open (&wps->wvxbits)) {
|
||||
float_values_nowvx (wps, values, num_values);
|
||||
return;
|
||||
}
|
||||
|
||||
while (num_values--) {
|
||||
int shift_count = 0, exp = wps->float_max_exp;
|
||||
f32 outval = { 0, 0, 0 };
|
||||
uint32_t temp;
|
||||
|
||||
if (*values == 0) {
|
||||
if (wps->float_flags & FLOAT_ZEROS_SENT) {
|
||||
if (getbit (&wps->wvxbits)) {
|
||||
getbits (&temp, 23, &wps->wvxbits);
|
||||
outval.mantissa = temp;
|
||||
|
||||
if (exp >= 25) {
|
||||
getbits (&temp, 8, &wps->wvxbits);
|
||||
outval.exponent = temp;
|
||||
}
|
||||
|
||||
outval.sign = getbit (&wps->wvxbits);
|
||||
}
|
||||
else if (wps->float_flags & FLOAT_NEG_ZEROS)
|
||||
outval.sign = getbit (&wps->wvxbits);
|
||||
}
|
||||
}
|
||||
else {
|
||||
*values <<= wps->float_shift;
|
||||
|
||||
if (*values < 0) {
|
||||
*values = -*values;
|
||||
outval.sign = 1;
|
||||
}
|
||||
|
||||
if (*values == 0x1000000) {
|
||||
if (getbit (&wps->wvxbits)) {
|
||||
getbits (&temp, 23, &wps->wvxbits);
|
||||
outval.mantissa = temp;
|
||||
}
|
||||
|
||||
outval.exponent = 255;
|
||||
}
|
||||
else {
|
||||
if (exp)
|
||||
while (!(*values & 0x800000) && --exp) {
|
||||
shift_count++;
|
||||
*values <<= 1;
|
||||
}
|
||||
|
||||
if (shift_count) {
|
||||
if ((wps->float_flags & FLOAT_SHIFT_ONES) ||
|
||||
((wps->float_flags & FLOAT_SHIFT_SAME) && getbit (&wps->wvxbits)))
|
||||
*values |= ((1 << shift_count) - 1);
|
||||
else if (wps->float_flags & FLOAT_SHIFT_SENT) {
|
||||
getbits (&temp, shift_count, &wps->wvxbits);
|
||||
*values |= temp & ((1 << shift_count) - 1);
|
||||
}
|
||||
}
|
||||
|
||||
outval.mantissa = *values;
|
||||
outval.exponent = exp;
|
||||
}
|
||||
}
|
||||
|
||||
crc = crc * 27 + outval.mantissa * 9 + outval.exponent * 3 + outval.sign;
|
||||
* (f32 *) values++ = outval;
|
||||
}
|
||||
|
||||
wps->crc_x = crc;
|
||||
}
|
||||
|
||||
static void float_values_nowvx (WavpackStream *wps, int32_t *values, int32_t num_values)
|
||||
{
|
||||
while (num_values--) {
|
||||
int shift_count = 0, exp = wps->float_max_exp;
|
||||
f32 outval = { 0, 0, 0 };
|
||||
|
||||
if (*values) {
|
||||
*values <<= wps->float_shift;
|
||||
|
||||
if (*values < 0) {
|
||||
*values = -*values;
|
||||
outval.sign = 1;
|
||||
}
|
||||
|
||||
if (*values >= 0x1000000) {
|
||||
while (*values & 0xf000000) {
|
||||
*values >>= 1;
|
||||
++exp;
|
||||
}
|
||||
}
|
||||
else if (exp) {
|
||||
while (!(*values & 0x800000) && --exp) {
|
||||
shift_count++;
|
||||
*values <<= 1;
|
||||
}
|
||||
|
||||
if (shift_count && (wps->float_flags & FLOAT_SHIFT_ONES))
|
||||
*values |= ((1 << shift_count) - 1);
|
||||
}
|
||||
|
||||
outval.mantissa = *values;
|
||||
outval.exponent = exp;
|
||||
}
|
||||
|
||||
* (f32 *) values++ = outval;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void float_normalize (int32_t *values, int32_t num_values, int delta_exp)
|
||||
{
|
||||
f32 *fvalues = (f32 *) values, fzero = { 0, 0, 0 };
|
||||
int exp;
|
||||
|
||||
if (!delta_exp)
|
||||
return;
|
||||
|
||||
while (num_values--) {
|
||||
if ((exp = fvalues->exponent) == 0 || exp + delta_exp <= 0)
|
||||
*fvalues = fzero;
|
||||
else if (exp == 255 || (exp += delta_exp) >= 255) {
|
||||
fvalues->exponent = 255;
|
||||
fvalues->mantissa = 0;
|
||||
}
|
||||
else
|
||||
fvalues->exponent = exp;
|
||||
|
||||
fvalues++;
|
||||
}
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// **** WAVPACK **** //
|
||||
// Hybrid Lossless Wavefile Compressor //
|
||||
// Copyright (c) 1998 - 2006 Conifer Software. //
|
||||
// All Rights Reserved. //
|
||||
// Distributed under the BSD Software License (see license.txt) //
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// float.c
|
||||
|
||||
#include "wavpack_local.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef DEBUG_ALLOC
|
||||
#define malloc malloc_db
|
||||
#define realloc realloc_db
|
||||
#define free free_db
|
||||
void *malloc_db (uint32_t size);
|
||||
void *realloc_db (void *ptr, uint32_t size);
|
||||
void free_db (void *ptr);
|
||||
int32_t dump_alloc (void);
|
||||
#endif
|
||||
|
||||
#ifndef NO_PACK
|
||||
|
||||
void write_float_info (WavpackStream *wps, WavpackMetadata *wpmd)
|
||||
{
|
||||
char *byteptr;
|
||||
|
||||
byteptr = wpmd->data = malloc (4);
|
||||
wpmd->id = ID_FLOAT_INFO;
|
||||
*byteptr++ = wps->float_flags;
|
||||
*byteptr++ = wps->float_shift;
|
||||
*byteptr++ = wps->float_max_exp;
|
||||
*byteptr++ = wps->float_norm_exp;
|
||||
wpmd->byte_length = (int32_t)(byteptr - (char *) wpmd->data);
|
||||
}
|
||||
|
||||
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 false_zeros = 0, neg_zeros = 0;
|
||||
uint32_t ordata = 0, crc = 0xffffffff;
|
||||
int32_t count, value, shift_count;
|
||||
int max_exp = 0;
|
||||
f32 *dp;
|
||||
|
||||
wps->float_shift = wps->float_flags = 0;
|
||||
|
||||
for (dp = values, count = num_values; count--; dp++) {
|
||||
crc = crc * 27 + get_mantissa (*dp) * 9 + get_exponent (*dp) * 3 + get_sign (*dp);
|
||||
|
||||
if (get_exponent (*dp) > max_exp && get_exponent (*dp) < 255)
|
||||
max_exp = get_exponent (*dp);
|
||||
}
|
||||
|
||||
wps->crc_x = crc;
|
||||
|
||||
for (dp = values, count = num_values; count--; dp++) {
|
||||
if (get_exponent (*dp) == 255) {
|
||||
wps->float_flags |= FLOAT_EXCEPTIONS;
|
||||
value = 0x1000000;
|
||||
shift_count = 0;
|
||||
}
|
||||
else if (get_exponent (*dp)) {
|
||||
shift_count = max_exp - get_exponent (*dp);
|
||||
value = 0x800000 + get_mantissa (*dp);
|
||||
}
|
||||
else {
|
||||
shift_count = max_exp ? max_exp - 1 : 0;
|
||||
value = get_mantissa (*dp);
|
||||
|
||||
// if (get_mantissa (*dp))
|
||||
// denormals++;
|
||||
}
|
||||
|
||||
if (shift_count < 25)
|
||||
value >>= shift_count;
|
||||
else
|
||||
value = 0;
|
||||
|
||||
if (!value) {
|
||||
if (get_exponent (*dp) || get_mantissa (*dp))
|
||||
++false_zeros;
|
||||
else if (get_sign (*dp))
|
||||
++neg_zeros;
|
||||
}
|
||||
else if (shift_count) {
|
||||
int32_t mask = (1 << shift_count) - 1;
|
||||
|
||||
if (!(get_mantissa (*dp) & mask))
|
||||
shifted_zeros++;
|
||||
else if ((get_mantissa (*dp) & mask) == mask)
|
||||
shifted_ones++;
|
||||
else
|
||||
shifted_both++;
|
||||
}
|
||||
|
||||
ordata |= value;
|
||||
* (int32_t *) dp = (get_sign (*dp)) ? -value : value;
|
||||
}
|
||||
|
||||
wps->float_max_exp = max_exp;
|
||||
|
||||
if (shifted_both)
|
||||
wps->float_flags |= FLOAT_SHIFT_SENT;
|
||||
else if (shifted_ones && !shifted_zeros)
|
||||
wps->float_flags |= FLOAT_SHIFT_ONES;
|
||||
else if (shifted_ones && shifted_zeros)
|
||||
wps->float_flags |= FLOAT_SHIFT_SAME;
|
||||
else if (ordata && !(ordata & 1)) {
|
||||
while (!(ordata & 1)) {
|
||||
wps->float_shift++;
|
||||
ordata >>= 1;
|
||||
}
|
||||
|
||||
for (dp = values, count = num_values; count--; dp++)
|
||||
* (int32_t *) dp >>= wps->float_shift;
|
||||
}
|
||||
|
||||
wps->wphdr.flags &= ~MAG_MASK;
|
||||
|
||||
while (ordata) {
|
||||
wps->wphdr.flags += 1 << MAG_LSB;
|
||||
ordata >>= 1;
|
||||
}
|
||||
|
||||
if (false_zeros || neg_zeros)
|
||||
wps->float_flags |= FLOAT_ZEROS_SENT;
|
||||
|
||||
if (neg_zeros)
|
||||
wps->float_flags |= FLOAT_NEG_ZEROS;
|
||||
|
||||
// error_line ("samples = %d, max exp = %d, pre-shift = %d, denormals = %d",
|
||||
// num_values, max_exp, wps->float_shift, denormals);
|
||||
// if (wps->float_flags & FLOAT_EXCEPTIONS)
|
||||
// error_line ("exceptions!");
|
||||
// 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);
|
||||
|
||||
return wps->float_flags & (FLOAT_EXCEPTIONS | FLOAT_ZEROS_SENT | FLOAT_SHIFT_SENT | FLOAT_SHIFT_SAME);
|
||||
}
|
||||
|
||||
void send_float_data (WavpackStream *wps, f32 *values, int32_t num_values)
|
||||
{
|
||||
int max_exp = wps->float_max_exp;
|
||||
int32_t count, value, shift_count;
|
||||
f32 *dp;
|
||||
|
||||
for (dp = values, count = num_values; count--; dp++) {
|
||||
if (get_exponent (*dp) == 255) {
|
||||
if (get_mantissa (*dp)) {
|
||||
putbit_1 (&wps->wvxbits);
|
||||
putbits (get_mantissa (*dp), 23, &wps->wvxbits);
|
||||
}
|
||||
else {
|
||||
putbit_0 (&wps->wvxbits);
|
||||
}
|
||||
|
||||
value = 0x1000000;
|
||||
shift_count = 0;
|
||||
}
|
||||
else if (get_exponent (*dp)) {
|
||||
shift_count = max_exp - get_exponent (*dp);
|
||||
value = 0x800000 + get_mantissa (*dp);
|
||||
}
|
||||
else {
|
||||
shift_count = max_exp ? max_exp - 1 : 0;
|
||||
value = get_mantissa (*dp);
|
||||
}
|
||||
|
||||
if (shift_count < 25)
|
||||
value >>= shift_count;
|
||||
else
|
||||
value = 0;
|
||||
|
||||
if (!value) {
|
||||
if (wps->float_flags & FLOAT_ZEROS_SENT) {
|
||||
if (get_exponent (*dp) || get_mantissa (*dp)) {
|
||||
putbit_1 (&wps->wvxbits);
|
||||
putbits (get_mantissa (*dp), 23, &wps->wvxbits);
|
||||
|
||||
if (max_exp >= 25) {
|
||||
putbits (get_exponent (*dp), 8, &wps->wvxbits);
|
||||
}
|
||||
|
||||
putbit (get_sign (*dp), &wps->wvxbits);
|
||||
}
|
||||
else {
|
||||
putbit_0 (&wps->wvxbits);
|
||||
|
||||
if (wps->float_flags & FLOAT_NEG_ZEROS)
|
||||
putbit (get_sign (*dp), &wps->wvxbits);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (shift_count) {
|
||||
if (wps->float_flags & FLOAT_SHIFT_SENT) {
|
||||
int32_t data = get_mantissa (*dp) & ((1 << shift_count) - 1);
|
||||
putbits (data, shift_count, &wps->wvxbits);
|
||||
}
|
||||
else if (wps->float_flags & FLOAT_SHIFT_SAME) {
|
||||
putbit (get_mantissa (*dp) & 1, &wps->wvxbits);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined(NO_UNPACK) || defined(INFO_ONLY)
|
||||
|
||||
int read_float_info (WavpackStream *wps, WavpackMetadata *wpmd)
|
||||
{
|
||||
int bytecnt = wpmd->byte_length;
|
||||
char *byteptr = wpmd->data;
|
||||
|
||||
if (bytecnt != 4)
|
||||
return FALSE;
|
||||
|
||||
wps->float_flags = *byteptr++;
|
||||
wps->float_shift = *byteptr++;
|
||||
wps->float_max_exp = *byteptr++;
|
||||
wps->float_norm_exp = *byteptr;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef NO_UNPACK
|
||||
|
||||
static void float_values_nowvx (WavpackStream *wps, int32_t *values, int32_t num_values);
|
||||
|
||||
void float_values (WavpackStream *wps, int32_t *values, int32_t num_values)
|
||||
{
|
||||
uint32_t crc = wps->crc_x;
|
||||
|
||||
if (!bs_is_open (&wps->wvxbits)) {
|
||||
float_values_nowvx (wps, values, num_values);
|
||||
return;
|
||||
}
|
||||
|
||||
while (num_values--) {
|
||||
int shift_count = 0, exp = wps->float_max_exp;
|
||||
f32 outval = 0;
|
||||
uint32_t temp;
|
||||
|
||||
if (*values == 0) {
|
||||
if (wps->float_flags & FLOAT_ZEROS_SENT) {
|
||||
if (getbit (&wps->wvxbits)) {
|
||||
getbits (&temp, 23, &wps->wvxbits);
|
||||
set_mantissa (outval, temp);
|
||||
|
||||
if (exp >= 25) {
|
||||
getbits (&temp, 8, &wps->wvxbits);
|
||||
set_exponent (outval, temp);
|
||||
}
|
||||
|
||||
set_sign (outval, getbit (&wps->wvxbits));
|
||||
}
|
||||
else if (wps->float_flags & FLOAT_NEG_ZEROS)
|
||||
set_sign (outval, getbit (&wps->wvxbits));
|
||||
}
|
||||
}
|
||||
else {
|
||||
*values <<= wps->float_shift;
|
||||
|
||||
if (*values < 0) {
|
||||
*values = -*values;
|
||||
set_sign (outval, 1);
|
||||
}
|
||||
|
||||
if (*values == 0x1000000) {
|
||||
if (getbit (&wps->wvxbits)) {
|
||||
getbits (&temp, 23, &wps->wvxbits);
|
||||
set_mantissa (outval, temp);
|
||||
}
|
||||
|
||||
set_exponent (outval, 255);
|
||||
}
|
||||
else {
|
||||
if (exp)
|
||||
while (!(*values & 0x800000) && --exp) {
|
||||
shift_count++;
|
||||
*values <<= 1;
|
||||
}
|
||||
|
||||
if (shift_count) {
|
||||
if ((wps->float_flags & FLOAT_SHIFT_ONES) ||
|
||||
((wps->float_flags & FLOAT_SHIFT_SAME) && getbit (&wps->wvxbits)))
|
||||
*values |= ((1 << shift_count) - 1);
|
||||
else if (wps->float_flags & FLOAT_SHIFT_SENT) {
|
||||
getbits (&temp, shift_count, &wps->wvxbits);
|
||||
*values |= temp & ((1 << shift_count) - 1);
|
||||
}
|
||||
}
|
||||
|
||||
set_mantissa (outval, *values);
|
||||
set_exponent (outval, exp);
|
||||
}
|
||||
}
|
||||
|
||||
crc = crc * 27 + get_mantissa (outval) * 9 + get_exponent (outval) * 3 + get_sign (outval);
|
||||
* (f32 *) values++ = outval;
|
||||
}
|
||||
|
||||
wps->crc_x = crc;
|
||||
}
|
||||
|
||||
static void float_values_nowvx (WavpackStream *wps, int32_t *values, int32_t num_values)
|
||||
{
|
||||
while (num_values--) {
|
||||
int shift_count = 0, exp = wps->float_max_exp;
|
||||
f32 outval = 0;
|
||||
|
||||
if (*values) {
|
||||
*values <<= wps->float_shift;
|
||||
|
||||
if (*values < 0) {
|
||||
*values = -*values;
|
||||
set_sign (outval, 1);
|
||||
}
|
||||
|
||||
if (*values >= 0x1000000) {
|
||||
while (*values & 0xf000000) {
|
||||
*values >>= 1;
|
||||
++exp;
|
||||
}
|
||||
}
|
||||
else if (exp) {
|
||||
while (!(*values & 0x800000) && --exp) {
|
||||
shift_count++;
|
||||
*values <<= 1;
|
||||
}
|
||||
|
||||
if (shift_count && (wps->float_flags & FLOAT_SHIFT_ONES))
|
||||
*values |= ((1 << shift_count) - 1);
|
||||
}
|
||||
|
||||
set_mantissa (outval, *values);
|
||||
set_exponent (outval, exp);
|
||||
}
|
||||
|
||||
* (f32 *) values++ = outval;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void WavpackFloatNormalize (int32_t *values, int32_t num_values, int delta_exp)
|
||||
{
|
||||
f32 *fvalues = (f32 *) values;
|
||||
int exp;
|
||||
|
||||
if (!delta_exp)
|
||||
return;
|
||||
|
||||
while (num_values--) {
|
||||
if ((exp = get_exponent (*fvalues)) == 0 || exp + delta_exp <= 0)
|
||||
*fvalues = 0;
|
||||
else if (exp == 255 || (exp += delta_exp) >= 255) {
|
||||
set_exponent (*fvalues, 255);
|
||||
set_mantissa (*fvalues, 0);
|
||||
}
|
||||
else
|
||||
set_exponent (*fvalues, exp);
|
||||
|
||||
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.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
@ -1,263 +1,263 @@
|
|||
/*
|
||||
* This code implements the MD5 message-digest algorithm.
|
||||
* The algorithm is due to Ron Rivest. This code was
|
||||
* written by Colin Plumb in 1993, no copyright is claimed.
|
||||
* This code is in the public domain; do with it what you wish.
|
||||
*
|
||||
* Equivalent code is available from RSA Data Security, Inc.
|
||||
* This code has been tested against that, and is equivalent,
|
||||
* except that you don't need to include two pages of legalese
|
||||
* with every copy.
|
||||
*
|
||||
* To compute the message digest of a chunk of bytes, declare an
|
||||
* MD5Context structure, pass it to MD5Init, call MD5Update as
|
||||
* needed on buffers full of bytes, and then call MD5Final, which
|
||||
* will fill a supplied 16-byte array with the digest.
|
||||
*/
|
||||
|
||||
/* Brutally hacked by John Walker back from ANSI C to K&R (no
|
||||
prototypes) to maintain the tradition that Netfone will compile
|
||||
with Sun's original "cc". */
|
||||
|
||||
#include <memory.h> /* for memcpy() */
|
||||
#include "md5.h"
|
||||
|
||||
#ifdef sgi
|
||||
#define HIGHFIRST
|
||||
#endif
|
||||
|
||||
#ifdef sun
|
||||
#define HIGHFIRST
|
||||
#endif
|
||||
|
||||
#ifndef HIGHFIRST
|
||||
#define byteReverse(buf, len) /* Nothing */
|
||||
#else
|
||||
/*
|
||||
* Note: this code is harmless on little-endian machines.
|
||||
*/
|
||||
void byteReverse(buf, longs)
|
||||
unsigned char *buf; unsigned longs;
|
||||
{
|
||||
uint32 t;
|
||||
do {
|
||||
t = (uint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
|
||||
((unsigned) buf[1] << 8 | buf[0]);
|
||||
*(uint32 *) buf = t;
|
||||
buf += 4;
|
||||
} while (--longs);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
|
||||
* initialization constants.
|
||||
*/
|
||||
void MD5Init(ctx)
|
||||
struct MD5Context *ctx;
|
||||
{
|
||||
ctx->buf[0] = 0x67452301;
|
||||
ctx->buf[1] = 0xefcdab89;
|
||||
ctx->buf[2] = 0x98badcfe;
|
||||
ctx->buf[3] = 0x10325476;
|
||||
|
||||
ctx->bits[0] = 0;
|
||||
ctx->bits[1] = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Update context to reflect the concatenation of another buffer full
|
||||
* of bytes.
|
||||
*/
|
||||
void MD5Update(ctx, buf, len)
|
||||
struct MD5Context *ctx; unsigned char *buf; unsigned len;
|
||||
{
|
||||
uint32 t;
|
||||
|
||||
/* Update bitcount */
|
||||
|
||||
t = ctx->bits[0];
|
||||
if ((ctx->bits[0] = t + ((uint32) len << 3)) < t)
|
||||
ctx->bits[1]++; /* Carry from low to high */
|
||||
ctx->bits[1] += len >> 29;
|
||||
|
||||
t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
|
||||
|
||||
/* Handle any leading odd-sized chunks */
|
||||
|
||||
if (t) {
|
||||
unsigned char *p = (unsigned char *) ctx->in + t;
|
||||
|
||||
t = 64 - t;
|
||||
if (len < t) {
|
||||
memcpy(p, buf, len);
|
||||
return;
|
||||
}
|
||||
memcpy(p, buf, t);
|
||||
byteReverse(ctx->in, 16);
|
||||
MD5Transform(ctx->buf, (uint32 *) ctx->in);
|
||||
buf += t;
|
||||
len -= t;
|
||||
}
|
||||
/* Process data in 64-byte chunks */
|
||||
|
||||
while (len >= 64) {
|
||||
memcpy(ctx->in, buf, 64);
|
||||
byteReverse(ctx->in, 16);
|
||||
MD5Transform(ctx->buf, (uint32 *) ctx->in);
|
||||
buf += 64;
|
||||
len -= 64;
|
||||
}
|
||||
|
||||
/* Handle any remaining bytes of data. */
|
||||
|
||||
memcpy(ctx->in, buf, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Final wrapup - pad to 64-byte boundary with the bit pattern
|
||||
* 1 0* (64-bit count of bits processed, MSB-first)
|
||||
*/
|
||||
void MD5Final(digest, ctx)
|
||||
unsigned char digest[16]; struct MD5Context *ctx;
|
||||
{
|
||||
unsigned count;
|
||||
unsigned char *p;
|
||||
|
||||
/* Compute number of bytes mod 64 */
|
||||
count = (ctx->bits[0] >> 3) & 0x3F;
|
||||
|
||||
/* Set the first char of padding to 0x80. This is safe since there is
|
||||
always at least one byte free */
|
||||
p = ctx->in + count;
|
||||
*p++ = 0x80;
|
||||
|
||||
/* Bytes of padding needed to make 64 bytes */
|
||||
count = 64 - 1 - count;
|
||||
|
||||
/* Pad out to 56 mod 64 */
|
||||
if (count < 8) {
|
||||
/* Two lots of padding: Pad the first block to 64 bytes */
|
||||
memset(p, 0, count);
|
||||
byteReverse(ctx->in, 16);
|
||||
MD5Transform(ctx->buf, (uint32 *) ctx->in);
|
||||
|
||||
/* Now fill the next block with 56 bytes */
|
||||
memset(ctx->in, 0, 56);
|
||||
} else {
|
||||
/* Pad block to 56 bytes */
|
||||
memset(p, 0, count - 8);
|
||||
}
|
||||
byteReverse(ctx->in, 14);
|
||||
|
||||
/* Append length in bits and transform */
|
||||
((uint32 *) ctx->in)[14] = ctx->bits[0];
|
||||
((uint32 *) ctx->in)[15] = ctx->bits[1];
|
||||
|
||||
MD5Transform(ctx->buf, (uint32 *) ctx->in);
|
||||
byteReverse((unsigned char *) ctx->buf, 4);
|
||||
memcpy(digest, ctx->buf, 16);
|
||||
memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
|
||||
}
|
||||
|
||||
|
||||
/* The four core functions - F1 is optimized somewhat */
|
||||
|
||||
/* #define F1(x, y, z) (x & y | ~x & z) */
|
||||
#define F1(x, y, z) (z ^ (x & (y ^ z)))
|
||||
#define F2(x, y, z) F1(z, x, y)
|
||||
#define F3(x, y, z) (x ^ y ^ z)
|
||||
#define F4(x, y, z) (y ^ (x | ~z))
|
||||
|
||||
/* This is the central step in the MD5 algorithm. */
|
||||
#define MD5STEP(f, w, x, y, z, data, s) \
|
||||
( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
|
||||
|
||||
/*
|
||||
* The core of the MD5 algorithm, this alters an existing MD5 hash to
|
||||
* reflect the addition of 16 longwords of new data. MD5Update blocks
|
||||
* the data and converts bytes into longwords for this routine.
|
||||
*/
|
||||
void MD5Transform(buf, in)
|
||||
uint32 buf[4]; uint32 in[16];
|
||||
{
|
||||
register uint32 a, b, c, d;
|
||||
|
||||
a = buf[0];
|
||||
b = buf[1];
|
||||
c = buf[2];
|
||||
d = buf[3];
|
||||
|
||||
MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
|
||||
MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
|
||||
MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
|
||||
MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
|
||||
|
||||
MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
|
||||
MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
|
||||
MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
|
||||
MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
|
||||
|
||||
MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
|
||||
MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
|
||||
MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
|
||||
MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
|
||||
|
||||
MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
|
||||
MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
|
||||
MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
|
||||
MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
|
||||
|
||||
buf[0] += a;
|
||||
buf[1] += b;
|
||||
buf[2] += c;
|
||||
buf[3] += d;
|
||||
}
|
||||
/*
|
||||
* This code implements the MD5 message-digest algorithm.
|
||||
* The algorithm is due to Ron Rivest. This code was
|
||||
* written by Colin Plumb in 1993, no copyright is claimed.
|
||||
* This code is in the public domain; do with it what you wish.
|
||||
*
|
||||
* Equivalent code is available from RSA Data Security, Inc.
|
||||
* This code has been tested against that, and is equivalent,
|
||||
* except that you don't need to include two pages of legalese
|
||||
* with every copy.
|
||||
*
|
||||
* To compute the message digest of a chunk of bytes, declare an
|
||||
* MD5Context structure, pass it to MD5Init, call MD5Update as
|
||||
* needed on buffers full of bytes, and then call MD5Final, which
|
||||
* will fill a supplied 16-byte array with the digest.
|
||||
*/
|
||||
|
||||
/* Brutally hacked by John Walker back from ANSI C to K&R (no
|
||||
prototypes) to maintain the tradition that Netfone will compile
|
||||
with Sun's original "cc". */
|
||||
|
||||
#include <memory.h> /* for memcpy() */
|
||||
#include "md5.h"
|
||||
|
||||
#ifdef sgi
|
||||
#define HIGHFIRST
|
||||
#endif
|
||||
|
||||
#ifdef sun
|
||||
#define HIGHFIRST
|
||||
#endif
|
||||
|
||||
#ifndef HIGHFIRST
|
||||
#define byteReverse(buf, len) /* Nothing */
|
||||
#else
|
||||
/*
|
||||
* Note: this code is harmless on little-endian machines.
|
||||
*/
|
||||
void byteReverse(buf, longs)
|
||||
unsigned char *buf; unsigned longs;
|
||||
{
|
||||
uint32 t;
|
||||
do {
|
||||
t = (uint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
|
||||
((unsigned) buf[1] << 8 | buf[0]);
|
||||
*(uint32 *) buf = t;
|
||||
buf += 4;
|
||||
} while (--longs);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
|
||||
* initialization constants.
|
||||
*/
|
||||
void MD5Init(ctx)
|
||||
struct MD5Context *ctx;
|
||||
{
|
||||
ctx->buf[0] = 0x67452301;
|
||||
ctx->buf[1] = 0xefcdab89;
|
||||
ctx->buf[2] = 0x98badcfe;
|
||||
ctx->buf[3] = 0x10325476;
|
||||
|
||||
ctx->bits[0] = 0;
|
||||
ctx->bits[1] = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Update context to reflect the concatenation of another buffer full
|
||||
* of bytes.
|
||||
*/
|
||||
void MD5Update(ctx, buf, len)
|
||||
struct MD5Context *ctx; unsigned char *buf; unsigned len;
|
||||
{
|
||||
uint32 t;
|
||||
|
||||
/* Update bitcount */
|
||||
|
||||
t = ctx->bits[0];
|
||||
if ((ctx->bits[0] = t + ((uint32) len << 3)) < t)
|
||||
ctx->bits[1]++; /* Carry from low to high */
|
||||
ctx->bits[1] += len >> 29;
|
||||
|
||||
t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
|
||||
|
||||
/* Handle any leading odd-sized chunks */
|
||||
|
||||
if (t) {
|
||||
unsigned char *p = (unsigned char *) ctx->in + t;
|
||||
|
||||
t = 64 - t;
|
||||
if (len < t) {
|
||||
memcpy(p, buf, len);
|
||||
return;
|
||||
}
|
||||
memcpy(p, buf, t);
|
||||
byteReverse(ctx->in, 16);
|
||||
MD5Transform(ctx->buf, (uint32 *) ctx->in);
|
||||
buf += t;
|
||||
len -= t;
|
||||
}
|
||||
/* Process data in 64-byte chunks */
|
||||
|
||||
while (len >= 64) {
|
||||
memcpy(ctx->in, buf, 64);
|
||||
byteReverse(ctx->in, 16);
|
||||
MD5Transform(ctx->buf, (uint32 *) ctx->in);
|
||||
buf += 64;
|
||||
len -= 64;
|
||||
}
|
||||
|
||||
/* Handle any remaining bytes of data. */
|
||||
|
||||
memcpy(ctx->in, buf, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Final wrapup - pad to 64-byte boundary with the bit pattern
|
||||
* 1 0* (64-bit count of bits processed, MSB-first)
|
||||
*/
|
||||
void MD5Final(digest, ctx)
|
||||
unsigned char digest[16]; struct MD5Context *ctx;
|
||||
{
|
||||
unsigned count;
|
||||
unsigned char *p;
|
||||
|
||||
/* Compute number of bytes mod 64 */
|
||||
count = (ctx->bits[0] >> 3) & 0x3F;
|
||||
|
||||
/* Set the first char of padding to 0x80. This is safe since there is
|
||||
always at least one byte free */
|
||||
p = ctx->in + count;
|
||||
*p++ = 0x80;
|
||||
|
||||
/* Bytes of padding needed to make 64 bytes */
|
||||
count = 64 - 1 - count;
|
||||
|
||||
/* Pad out to 56 mod 64 */
|
||||
if (count < 8) {
|
||||
/* Two lots of padding: Pad the first block to 64 bytes */
|
||||
memset(p, 0, count);
|
||||
byteReverse(ctx->in, 16);
|
||||
MD5Transform(ctx->buf, (uint32 *) ctx->in);
|
||||
|
||||
/* Now fill the next block with 56 bytes */
|
||||
memset(ctx->in, 0, 56);
|
||||
} else {
|
||||
/* Pad block to 56 bytes */
|
||||
memset(p, 0, count - 8);
|
||||
}
|
||||
byteReverse(ctx->in, 14);
|
||||
|
||||
/* Append length in bits and transform */
|
||||
((uint32 *) ctx->in)[14] = ctx->bits[0];
|
||||
((uint32 *) ctx->in)[15] = ctx->bits[1];
|
||||
|
||||
MD5Transform(ctx->buf, (uint32 *) ctx->in);
|
||||
byteReverse((unsigned char *) ctx->buf, 4);
|
||||
memcpy(digest, ctx->buf, 16);
|
||||
memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */
|
||||
}
|
||||
|
||||
|
||||
/* The four core functions - F1 is optimized somewhat */
|
||||
|
||||
/* #define F1(x, y, z) (x & y | ~x & z) */
|
||||
#define F1(x, y, z) (z ^ (x & (y ^ z)))
|
||||
#define F2(x, y, z) F1(z, x, y)
|
||||
#define F3(x, y, z) (x ^ y ^ z)
|
||||
#define F4(x, y, z) (y ^ (x | ~z))
|
||||
|
||||
/* This is the central step in the MD5 algorithm. */
|
||||
#define MD5STEP(f, w, x, y, z, data, s) \
|
||||
( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
|
||||
|
||||
/*
|
||||
* The core of the MD5 algorithm, this alters an existing MD5 hash to
|
||||
* reflect the addition of 16 longwords of new data. MD5Update blocks
|
||||
* the data and converts bytes into longwords for this routine.
|
||||
*/
|
||||
void MD5Transform(buf, in)
|
||||
uint32 buf[4]; uint32 in[16];
|
||||
{
|
||||
register uint32 a, b, c, d;
|
||||
|
||||
a = buf[0];
|
||||
b = buf[1];
|
||||
c = buf[2];
|
||||
d = buf[3];
|
||||
|
||||
MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
|
||||
MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
|
||||
MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
|
||||
MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
|
||||
|
||||
MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
|
||||
MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
|
||||
MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
|
||||
MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
|
||||
|
||||
MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
|
||||
MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
|
||||
MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
|
||||
MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
|
||||
|
||||
MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
|
||||
MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
|
||||
MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
|
||||
MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
|
||||
|
||||
buf[0] += a;
|
||||
buf[1] += b;
|
||||
buf[2] += c;
|
||||
buf[3] += d;
|
||||
}
|
||||
|
|
|
@ -1,26 +1,26 @@
|
|||
#ifndef MD5_H
|
||||
#define MD5_H
|
||||
|
||||
#if defined (__alpha__) || defined (__x86_64__)
|
||||
typedef unsigned int uint32;
|
||||
#else
|
||||
typedef unsigned long uint32;
|
||||
#endif
|
||||
|
||||
struct MD5Context {
|
||||
uint32 buf[4];
|
||||
uint32 bits[2];
|
||||
unsigned char in[64];
|
||||
};
|
||||
|
||||
extern void MD5Init (struct MD5Context *ctx);
|
||||
extern void MD5Update (struct MD5Context *ctx, unsigned char *buf, unsigned len);
|
||||
extern void MD5Final (unsigned char digest[16], struct MD5Context *ctx);
|
||||
extern void MD5Transform (uint32 buf[4], uint32 in[16]);
|
||||
|
||||
/*
|
||||
* This is needed to make RSAREF happy on some MS-DOS compilers.
|
||||
*/
|
||||
typedef struct MD5Context MD5_CTX;
|
||||
|
||||
#endif /* !MD5_H */
|
||||
#ifndef MD5_H
|
||||
#define MD5_H
|
||||
|
||||
#if defined (__alpha__) || defined (__x86_64__)
|
||||
typedef unsigned int uint32;
|
||||
#else
|
||||
typedef unsigned long uint32;
|
||||
#endif
|
||||
|
||||
struct MD5Context {
|
||||
uint32 buf[4];
|
||||
uint32 bits[2];
|
||||
unsigned char in[64];
|
||||
};
|
||||
|
||||
extern void MD5Init (struct MD5Context *ctx);
|
||||
extern void MD5Update (struct MD5Context *ctx, unsigned char *buf, unsigned len);
|
||||
extern void MD5Final (unsigned char digest[16], struct MD5Context *ctx);
|
||||
extern void MD5Transform (uint32 buf[4], uint32 in[16]);
|
||||
|
||||
/*
|
||||
* This is needed to make RSAREF happy on some MS-DOS compilers.
|
||||
*/
|
||||
typedef struct MD5Context MD5_CTX;
|
||||
|
||||
#endif /* !MD5_H */
|
||||
|
|
|
@ -1,313 +1,313 @@
|
|||
////////////////////////////////////////////////////////////////////////////
|
||||
// **** WAVPACK **** //
|
||||
// Hybrid Lossless Wavefile Compressor //
|
||||
// Copyright (c) 1998 - 2005 Conifer Software. //
|
||||
// All Rights Reserved. //
|
||||
// Distributed under the BSD Software License (see license.txt) //
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// metadata.c
|
||||
|
||||
// This module handles the metadata structure introduced in WavPack 4.0
|
||||
|
||||
#include "wavpack.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef DEBUG_ALLOC
|
||||
#define malloc malloc_db
|
||||
#define realloc realloc_db
|
||||
#define free free_db
|
||||
void *malloc_db (uint32_t size);
|
||||
void *realloc_db (void *ptr, uint32_t size);
|
||||
void free_db (void *ptr);
|
||||
int32_t dump_alloc (void);
|
||||
#endif
|
||||
|
||||
#if defined(UNPACK) || defined(INFO_ONLY)
|
||||
|
||||
int read_metadata_buff (WavpackMetadata *wpmd, uchar *blockbuff, uchar **buffptr)
|
||||
{
|
||||
WavpackHeader *wphdr = (WavpackHeader *) blockbuff;
|
||||
uchar *buffend = blockbuff + wphdr->ckSize + 8;
|
||||
|
||||
if (buffend - *buffptr < 2)
|
||||
return FALSE;
|
||||
|
||||
wpmd->id = *(*buffptr)++;
|
||||
wpmd->byte_length = *(*buffptr)++ << 1;
|
||||
|
||||
if (wpmd->id & ID_LARGE) {
|
||||
wpmd->id &= ~ID_LARGE;
|
||||
|
||||
if (buffend - *buffptr < 2)
|
||||
return FALSE;
|
||||
|
||||
wpmd->byte_length += *(*buffptr)++ << 9;
|
||||
wpmd->byte_length += *(*buffptr)++ << 17;
|
||||
}
|
||||
|
||||
if (wpmd->id & ID_ODD_SIZE) {
|
||||
wpmd->id &= ~ID_ODD_SIZE;
|
||||
wpmd->byte_length--;
|
||||
}
|
||||
|
||||
if (wpmd->byte_length) {
|
||||
if (buffend - *buffptr < wpmd->byte_length + (wpmd->byte_length & 1)) {
|
||||
wpmd->data = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
wpmd->data = *buffptr;
|
||||
(*buffptr) += wpmd->byte_length + (wpmd->byte_length & 1);
|
||||
}
|
||||
else
|
||||
wpmd->data = NULL;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int process_metadata (WavpackContext *wpc, WavpackMetadata *wpmd)
|
||||
{
|
||||
WavpackStream *wps = wpc->streams [wpc->current_stream];
|
||||
|
||||
switch (wpmd->id) {
|
||||
case ID_DUMMY:
|
||||
return TRUE;
|
||||
|
||||
case ID_DECORR_TERMS:
|
||||
return read_decorr_terms (wps, wpmd);
|
||||
|
||||
case ID_DECORR_WEIGHTS:
|
||||
return read_decorr_weights (wps, wpmd);
|
||||
|
||||
case ID_DECORR_SAMPLES:
|
||||
return read_decorr_samples (wps, wpmd);
|
||||
|
||||
case ID_ENTROPY_VARS:
|
||||
return read_entropy_vars (wps, wpmd);
|
||||
|
||||
case ID_HYBRID_PROFILE:
|
||||
return read_hybrid_profile (wps, wpmd);
|
||||
|
||||
case ID_SHAPING_WEIGHTS:
|
||||
return read_shaping_info (wps, wpmd);
|
||||
|
||||
case ID_FLOAT_INFO:
|
||||
return read_float_info (wps, wpmd);
|
||||
|
||||
case ID_INT32_INFO:
|
||||
return read_int32_info (wps, wpmd);
|
||||
|
||||
case ID_CHANNEL_INFO:
|
||||
return read_channel_info (wpc, wpmd);
|
||||
|
||||
case ID_CONFIG_BLOCK:
|
||||
return read_config_info (wpc, wpmd);
|
||||
|
||||
case ID_SAMPLE_RATE:
|
||||
return read_sample_rate (wpc, wpmd);
|
||||
|
||||
case ID_WV_BITSTREAM:
|
||||
return init_wv_bitstream (wps, wpmd);
|
||||
|
||||
case ID_WVC_BITSTREAM:
|
||||
return init_wvc_bitstream (wps, wpmd);
|
||||
|
||||
case ID_WVX_BITSTREAM:
|
||||
return init_wvx_bitstream (wps, wpmd);
|
||||
|
||||
case ID_RIFF_HEADER: case ID_RIFF_TRAILER:
|
||||
return read_wrapper_data (wpc, wpmd);
|
||||
|
||||
case ID_MD5_CHECKSUM:
|
||||
if (wpmd->byte_length == 16) {
|
||||
memcpy (wpc->config.md5_checksum, wpmd->data, 16);
|
||||
wpc->config.flags |= CONFIG_MD5_CHECKSUM;
|
||||
wpc->config.md5_read = 1;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
||||
default:
|
||||
return (wpmd->id & ID_OPTIONAL_DATA) ? TRUE : FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef PACK
|
||||
|
||||
int copy_metadata (WavpackMetadata *wpmd, uchar *buffer_start, uchar *buffer_end)
|
||||
{
|
||||
uint32_t mdsize = wpmd->byte_length + (wpmd->byte_length & 1);
|
||||
WavpackHeader *wphdr = (WavpackHeader *) buffer_start;
|
||||
|
||||
if (wpmd->byte_length & 1)
|
||||
((char *) wpmd->data) [wpmd->byte_length] = 0;
|
||||
|
||||
mdsize += (wpmd->byte_length > 510) ? 4 : 2;
|
||||
buffer_start += wphdr->ckSize + 8;
|
||||
|
||||
if (buffer_start + mdsize >= buffer_end)
|
||||
return FALSE;
|
||||
|
||||
buffer_start [0] = wpmd->id | (wpmd->byte_length & 1 ? ID_ODD_SIZE : 0);
|
||||
buffer_start [1] = (wpmd->byte_length + 1) >> 1;
|
||||
|
||||
if (wpmd->byte_length > 510) {
|
||||
buffer_start [0] |= ID_LARGE;
|
||||
buffer_start [2] = (wpmd->byte_length + 1) >> 9;
|
||||
buffer_start [3] = (wpmd->byte_length + 1) >> 17;
|
||||
}
|
||||
|
||||
if (wpmd->data && wpmd->byte_length) {
|
||||
if (wpmd->byte_length > 510) {
|
||||
buffer_start [0] |= ID_LARGE;
|
||||
buffer_start [2] = (wpmd->byte_length + 1) >> 9;
|
||||
buffer_start [3] = (wpmd->byte_length + 1) >> 17;
|
||||
memcpy (buffer_start + 4, wpmd->data, mdsize - 4);
|
||||
}
|
||||
else
|
||||
memcpy (buffer_start + 2, wpmd->data, mdsize - 2);
|
||||
}
|
||||
|
||||
wphdr->ckSize += mdsize;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int add_to_metadata (WavpackContext *wpc, void *data, uint32_t bcount, uchar id)
|
||||
{
|
||||
WavpackMetadata *mdp;
|
||||
uchar *src = data;
|
||||
|
||||
while (bcount) {
|
||||
if (wpc->metacount) {
|
||||
uint32_t bc = bcount;
|
||||
|
||||
mdp = wpc->metadata + wpc->metacount - 1;
|
||||
|
||||
if (mdp->id == id) {
|
||||
if (wpc->metabytes + bcount > 1000000)
|
||||
bc = 1000000 - wpc->metabytes;
|
||||
|
||||
mdp->data = realloc (mdp->data, mdp->byte_length + bc);
|
||||
memcpy ((char *) mdp->data + mdp->byte_length, src, bc);
|
||||
mdp->byte_length += bc;
|
||||
wpc->metabytes += bc;
|
||||
bcount -= bc;
|
||||
src += bc;
|
||||
|
||||
if (wpc->metabytes >= 1000000 && !write_metadata_block (wpc))
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (bcount) {
|
||||
wpc->metadata = realloc (wpc->metadata, (wpc->metacount + 1) * sizeof (WavpackMetadata));
|
||||
mdp = wpc->metadata + wpc->metacount++;
|
||||
mdp->byte_length = 0;
|
||||
mdp->data = NULL;
|
||||
mdp->id = id;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static char *write_metadata (WavpackMetadata *wpmd, char *outdata)
|
||||
{
|
||||
uchar id = wpmd->id, wordlen [3];
|
||||
|
||||
wordlen [0] = (wpmd->byte_length + 1) >> 1;
|
||||
wordlen [1] = (wpmd->byte_length + 1) >> 9;
|
||||
wordlen [2] = (wpmd->byte_length + 1) >> 17;
|
||||
|
||||
if (wpmd->byte_length & 1) {
|
||||
// ((char *) wpmd->data) [wpmd->byte_length] = 0;
|
||||
id |= ID_ODD_SIZE;
|
||||
}
|
||||
|
||||
if (wordlen [1] || wordlen [2])
|
||||
id |= ID_LARGE;
|
||||
|
||||
*outdata++ = id;
|
||||
*outdata++ = wordlen [0];
|
||||
|
||||
if (id & ID_LARGE) {
|
||||
*outdata++ = wordlen [1];
|
||||
*outdata++ = wordlen [2];
|
||||
}
|
||||
|
||||
if (wpmd->data && wpmd->byte_length) {
|
||||
memcpy (outdata, wpmd->data, wpmd->byte_length);
|
||||
outdata += wpmd->byte_length;
|
||||
|
||||
if (wpmd->byte_length & 1)
|
||||
*outdata++ = 0;
|
||||
}
|
||||
|
||||
return outdata;
|
||||
}
|
||||
|
||||
int write_metadata_block (WavpackContext *wpc)
|
||||
{
|
||||
char *block_buff, *block_ptr;
|
||||
WavpackHeader *wphdr;
|
||||
|
||||
if (wpc->metacount) {
|
||||
int metacount = wpc->metacount, block_size = sizeof (WavpackHeader);
|
||||
WavpackMetadata *wpmdp = wpc->metadata;
|
||||
|
||||
while (metacount--) {
|
||||
block_size += wpmdp->byte_length + (wpmdp->byte_length & 1);
|
||||
block_size += (wpmdp->byte_length > 510) ? 4 : 2;
|
||||
wpmdp++;
|
||||
}
|
||||
|
||||
wphdr = (WavpackHeader *) (block_buff = malloc (block_size));
|
||||
|
||||
CLEAR (*wphdr);
|
||||
memcpy (wphdr->ckID, "wvpk", 4);
|
||||
wphdr->total_samples = wpc->total_samples;
|
||||
wphdr->version = wpc->stream_version;
|
||||
wphdr->ckSize = block_size - 8;
|
||||
wphdr->block_samples = 0;
|
||||
|
||||
block_ptr = (char *)(wphdr + 1);
|
||||
|
||||
wpmdp = wpc->metadata;
|
||||
|
||||
while (wpc->metacount) {
|
||||
block_ptr = write_metadata (wpmdp, block_ptr);
|
||||
wpc->metabytes -= wpmdp->byte_length;
|
||||
free_metadata (wpmdp++);
|
||||
wpc->metacount--;
|
||||
}
|
||||
|
||||
free (wpc->metadata);
|
||||
wpc->metadata = NULL;
|
||||
native_to_little_endian ((WavpackHeader *) block_buff, WavpackHeaderFormat);
|
||||
|
||||
if (!wpc->blockout (wpc->wv_out, block_buff, block_size)) {
|
||||
free (block_buff);
|
||||
strcpy (wpc->error_message, "can't write WavPack data, disk probably full!");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
free (block_buff);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void free_metadata (WavpackMetadata *wpmd)
|
||||
{
|
||||
if (wpmd->data) {
|
||||
free (wpmd->data);
|
||||
wpmd->data = NULL;
|
||||
}
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// **** WAVPACK **** //
|
||||
// Hybrid Lossless Wavefile Compressor //
|
||||
// Copyright (c) 1998 - 2006 Conifer Software. //
|
||||
// All Rights Reserved. //
|
||||
// Distributed under the BSD Software License (see license.txt) //
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// metadata.c
|
||||
|
||||
// This module handles the metadata structure introduced in WavPack 4.0
|
||||
|
||||
#include "wavpack_local.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef DEBUG_ALLOC
|
||||
#define malloc malloc_db
|
||||
#define realloc realloc_db
|
||||
#define free free_db
|
||||
void *malloc_db (uint32_t size);
|
||||
void *realloc_db (void *ptr, uint32_t size);
|
||||
void free_db (void *ptr);
|
||||
int32_t dump_alloc (void);
|
||||
#endif
|
||||
|
||||
#if !defined(NO_UNPACK) || defined(INFO_ONLY)
|
||||
|
||||
int read_metadata_buff (WavpackMetadata *wpmd, unsigned char *blockbuff, unsigned char **buffptr)
|
||||
{
|
||||
WavpackHeader *wphdr = (WavpackHeader *) blockbuff;
|
||||
unsigned char *buffend = blockbuff + wphdr->ckSize + 8;
|
||||
|
||||
if (buffend - *buffptr < 2)
|
||||
return FALSE;
|
||||
|
||||
wpmd->id = *(*buffptr)++;
|
||||
wpmd->byte_length = *(*buffptr)++ << 1;
|
||||
|
||||
if (wpmd->id & ID_LARGE) {
|
||||
wpmd->id &= ~ID_LARGE;
|
||||
|
||||
if (buffend - *buffptr < 2)
|
||||
return FALSE;
|
||||
|
||||
wpmd->byte_length += *(*buffptr)++ << 9;
|
||||
wpmd->byte_length += *(*buffptr)++ << 17;
|
||||
}
|
||||
|
||||
if (wpmd->id & ID_ODD_SIZE) {
|
||||
wpmd->id &= ~ID_ODD_SIZE;
|
||||
wpmd->byte_length--;
|
||||
}
|
||||
|
||||
if (wpmd->byte_length) {
|
||||
if (buffend - *buffptr < wpmd->byte_length + (wpmd->byte_length & 1)) {
|
||||
wpmd->data = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
wpmd->data = *buffptr;
|
||||
(*buffptr) += wpmd->byte_length + (wpmd->byte_length & 1);
|
||||
}
|
||||
else
|
||||
wpmd->data = NULL;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int process_metadata (WavpackContext *wpc, WavpackMetadata *wpmd)
|
||||
{
|
||||
WavpackStream *wps = wpc->streams [wpc->current_stream];
|
||||
|
||||
switch (wpmd->id) {
|
||||
case ID_DUMMY:
|
||||
return TRUE;
|
||||
|
||||
case ID_DECORR_TERMS:
|
||||
return read_decorr_terms (wps, wpmd);
|
||||
|
||||
case ID_DECORR_WEIGHTS:
|
||||
return read_decorr_weights (wps, wpmd);
|
||||
|
||||
case ID_DECORR_SAMPLES:
|
||||
return read_decorr_samples (wps, wpmd);
|
||||
|
||||
case ID_ENTROPY_VARS:
|
||||
return read_entropy_vars (wps, wpmd);
|
||||
|
||||
case ID_HYBRID_PROFILE:
|
||||
return read_hybrid_profile (wps, wpmd);
|
||||
|
||||
case ID_SHAPING_WEIGHTS:
|
||||
return read_shaping_info (wps, wpmd);
|
||||
|
||||
case ID_FLOAT_INFO:
|
||||
return read_float_info (wps, wpmd);
|
||||
|
||||
case ID_INT32_INFO:
|
||||
return read_int32_info (wps, wpmd);
|
||||
|
||||
case ID_CHANNEL_INFO:
|
||||
return read_channel_info (wpc, wpmd);
|
||||
|
||||
case ID_CONFIG_BLOCK:
|
||||
return read_config_info (wpc, wpmd);
|
||||
|
||||
case ID_SAMPLE_RATE:
|
||||
return read_sample_rate (wpc, wpmd);
|
||||
|
||||
case ID_WV_BITSTREAM:
|
||||
return init_wv_bitstream (wps, wpmd);
|
||||
|
||||
case ID_WVC_BITSTREAM:
|
||||
return init_wvc_bitstream (wps, wpmd);
|
||||
|
||||
case ID_WVX_BITSTREAM:
|
||||
return init_wvx_bitstream (wps, wpmd);
|
||||
|
||||
case ID_RIFF_HEADER: case ID_RIFF_TRAILER:
|
||||
return read_wrapper_data (wpc, wpmd);
|
||||
|
||||
case ID_MD5_CHECKSUM:
|
||||
if (wpmd->byte_length == 16) {
|
||||
memcpy (wpc->config.md5_checksum, wpmd->data, 16);
|
||||
wpc->config.flags |= CONFIG_MD5_CHECKSUM;
|
||||
wpc->config.md5_read = 1;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
||||
default:
|
||||
return (wpmd->id & ID_OPTIONAL_DATA) ? TRUE : FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef NO_PACK
|
||||
|
||||
int copy_metadata (WavpackMetadata *wpmd, unsigned char *buffer_start, unsigned char *buffer_end)
|
||||
{
|
||||
uint32_t mdsize = wpmd->byte_length + (wpmd->byte_length & 1);
|
||||
WavpackHeader *wphdr = (WavpackHeader *) buffer_start;
|
||||
|
||||
if (wpmd->byte_length & 1)
|
||||
((char *) wpmd->data) [wpmd->byte_length] = 0;
|
||||
|
||||
mdsize += (wpmd->byte_length > 510) ? 4 : 2;
|
||||
buffer_start += wphdr->ckSize + 8;
|
||||
|
||||
if (buffer_start + mdsize >= buffer_end)
|
||||
return FALSE;
|
||||
|
||||
buffer_start [0] = wpmd->id | (wpmd->byte_length & 1 ? ID_ODD_SIZE : 0);
|
||||
buffer_start [1] = (wpmd->byte_length + 1) >> 1;
|
||||
|
||||
if (wpmd->byte_length > 510) {
|
||||
buffer_start [0] |= ID_LARGE;
|
||||
buffer_start [2] = (wpmd->byte_length + 1) >> 9;
|
||||
buffer_start [3] = (wpmd->byte_length + 1) >> 17;
|
||||
}
|
||||
|
||||
if (wpmd->data && wpmd->byte_length) {
|
||||
if (wpmd->byte_length > 510) {
|
||||
buffer_start [0] |= ID_LARGE;
|
||||
buffer_start [2] = (wpmd->byte_length + 1) >> 9;
|
||||
buffer_start [3] = (wpmd->byte_length + 1) >> 17;
|
||||
memcpy (buffer_start + 4, wpmd->data, mdsize - 4);
|
||||
}
|
||||
else
|
||||
memcpy (buffer_start + 2, wpmd->data, mdsize - 2);
|
||||
}
|
||||
|
||||
wphdr->ckSize += mdsize;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int add_to_metadata (WavpackContext *wpc, void *data, uint32_t bcount, unsigned char id)
|
||||
{
|
||||
WavpackMetadata *mdp;
|
||||
unsigned char *src = data;
|
||||
|
||||
while (bcount) {
|
||||
if (wpc->metacount) {
|
||||
uint32_t bc = bcount;
|
||||
|
||||
mdp = wpc->metadata + wpc->metacount - 1;
|
||||
|
||||
if (mdp->id == id) {
|
||||
if (wpc->metabytes + bcount > 1000000)
|
||||
bc = 1000000 - wpc->metabytes;
|
||||
|
||||
mdp->data = realloc (mdp->data, mdp->byte_length + bc);
|
||||
memcpy ((char *) mdp->data + mdp->byte_length, src, bc);
|
||||
mdp->byte_length += bc;
|
||||
wpc->metabytes += bc;
|
||||
bcount -= bc;
|
||||
src += bc;
|
||||
|
||||
if (wpc->metabytes >= 1000000 && !write_metadata_block (wpc))
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (bcount) {
|
||||
wpc->metadata = realloc (wpc->metadata, (wpc->metacount + 1) * sizeof (WavpackMetadata));
|
||||
mdp = wpc->metadata + wpc->metacount++;
|
||||
mdp->byte_length = 0;
|
||||
mdp->data = NULL;
|
||||
mdp->id = id;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static char *write_metadata (WavpackMetadata *wpmd, char *outdata)
|
||||
{
|
||||
unsigned char id = wpmd->id, wordlen [3];
|
||||
|
||||
wordlen [0] = (wpmd->byte_length + 1) >> 1;
|
||||
wordlen [1] = (wpmd->byte_length + 1) >> 9;
|
||||
wordlen [2] = (wpmd->byte_length + 1) >> 17;
|
||||
|
||||
if (wpmd->byte_length & 1) {
|
||||
// ((char *) wpmd->data) [wpmd->byte_length] = 0;
|
||||
id |= ID_ODD_SIZE;
|
||||
}
|
||||
|
||||
if (wordlen [1] || wordlen [2])
|
||||
id |= ID_LARGE;
|
||||
|
||||
*outdata++ = id;
|
||||
*outdata++ = wordlen [0];
|
||||
|
||||
if (id & ID_LARGE) {
|
||||
*outdata++ = wordlen [1];
|
||||
*outdata++ = wordlen [2];
|
||||
}
|
||||
|
||||
if (wpmd->data && wpmd->byte_length) {
|
||||
memcpy (outdata, wpmd->data, wpmd->byte_length);
|
||||
outdata += wpmd->byte_length;
|
||||
|
||||
if (wpmd->byte_length & 1)
|
||||
*outdata++ = 0;
|
||||
}
|
||||
|
||||
return outdata;
|
||||
}
|
||||
|
||||
int write_metadata_block (WavpackContext *wpc)
|
||||
{
|
||||
char *block_buff, *block_ptr;
|
||||
WavpackHeader *wphdr;
|
||||
|
||||
if (wpc->metacount) {
|
||||
int metacount = wpc->metacount, block_size = sizeof (WavpackHeader);
|
||||
WavpackMetadata *wpmdp = wpc->metadata;
|
||||
|
||||
while (metacount--) {
|
||||
block_size += wpmdp->byte_length + (wpmdp->byte_length & 1);
|
||||
block_size += (wpmdp->byte_length > 510) ? 4 : 2;
|
||||
wpmdp++;
|
||||
}
|
||||
|
||||
wphdr = (WavpackHeader *) (block_buff = malloc (block_size));
|
||||
|
||||
CLEAR (*wphdr);
|
||||
memcpy (wphdr->ckID, "wvpk", 4);
|
||||
wphdr->total_samples = wpc->total_samples;
|
||||
wphdr->version = wpc->stream_version;
|
||||
wphdr->ckSize = block_size - 8;
|
||||
wphdr->block_samples = 0;
|
||||
|
||||
block_ptr = (char *)(wphdr + 1);
|
||||
|
||||
wpmdp = wpc->metadata;
|
||||
|
||||
while (wpc->metacount) {
|
||||
block_ptr = write_metadata (wpmdp, block_ptr);
|
||||
wpc->metabytes -= wpmdp->byte_length;
|
||||
free_metadata (wpmdp++);
|
||||
wpc->metacount--;
|
||||
}
|
||||
|
||||
free (wpc->metadata);
|
||||
wpc->metadata = NULL;
|
||||
native_to_little_endian ((WavpackHeader *) block_buff, WavpackHeaderFormat);
|
||||
|
||||
if (!wpc->blockout (wpc->wv_out, block_buff, block_size)) {
|
||||
free (block_buff);
|
||||
strcpy (wpc->error_message, "can't write WavPack data, disk probably full!");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
free (block_buff);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void free_metadata (WavpackMetadata *wpmd)
|
||||
{
|
||||
if (wpmd->data) {
|
||||
free (wpmd->data);
|
||||
wpmd->data = NULL;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
#! /bin/sh
|
||||
# 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.
|
||||
# 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
|
||||
# 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
|
||||
# distribute this file as part of a program that contains a
|
||||
|
@ -33,6 +33,8 @@ if test $# -eq 0; then
|
|||
fi
|
||||
|
||||
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
|
||||
# srcdir already.
|
||||
|
@ -44,7 +46,7 @@ fi
|
|||
|
||||
msg="missing on your system"
|
||||
|
||||
case "$1" in
|
||||
case $1 in
|
||||
--run)
|
||||
# Try to run requested program, and just exit if it succeeds.
|
||||
run=
|
||||
|
@ -77,6 +79,7 @@ Supported PROGRAM values:
|
|||
aclocal touch file \`aclocal.m4'
|
||||
autoconf touch file \`configure'
|
||||
autoheader touch file \`config.h.in'
|
||||
autom4te touch the output file, or create a stub one
|
||||
automake touch all \`Makefile.in' files
|
||||
bison create \`y.tab.[ch]', if possible, from existing .[ch]
|
||||
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
|
||||
# don't have it and --version was passed (most likely to detect
|
||||
# the program).
|
||||
case "$1" in
|
||||
case $1 in
|
||||
lex|yacc)
|
||||
# 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),
|
||||
# try to emulate it.
|
||||
case "$1" in
|
||||
case $1 in
|
||||
aclocal*)
|
||||
echo 1>&2 "\
|
||||
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"
|
||||
touch_files=
|
||||
for f in $files; do
|
||||
case "$f" in
|
||||
case $f in
|
||||
*:*) touch_files="$touch_files "`echo "$f" |
|
||||
sed -e 's/^[^:]*://' -e 's/:.*//'`;;
|
||||
*) 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
|
||||
archive site."
|
||||
|
||||
file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'`
|
||||
test -z "$file" && 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 -f "$file"; then
|
||||
touch $file
|
||||
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
|
||||
\`Bison' from any GNU archive site."
|
||||
rm -f y.tab.c y.tab.h
|
||||
if [ $# -ne 1 ]; then
|
||||
if test $# -ne 1; then
|
||||
eval LASTARG="\${$#}"
|
||||
case "$LASTARG" in
|
||||
case $LASTARG in
|
||||
*.y)
|
||||
SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
|
||||
if [ -f "$SRCFILE" ]; then
|
||||
if test -f "$SRCFILE"; then
|
||||
cp "$SRCFILE" y.tab.c
|
||||
fi
|
||||
SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
|
||||
if [ -f "$SRCFILE" ]; then
|
||||
if test -f "$SRCFILE"; then
|
||||
cp "$SRCFILE" y.tab.h
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
if [ ! -f y.tab.h ]; then
|
||||
if test ! -f y.tab.h; then
|
||||
echo >y.tab.h
|
||||
fi
|
||||
if [ ! -f y.tab.c ]; then
|
||||
if test ! -f y.tab.c; then
|
||||
echo 'main() { return 0; }' >y.tab.c
|
||||
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
|
||||
\`Flex' from any GNU archive site."
|
||||
rm -f lex.yy.c
|
||||
if [ $# -ne 1 ]; then
|
||||
if test $# -ne 1; then
|
||||
eval LASTARG="\${$#}"
|
||||
case "$LASTARG" in
|
||||
case $LASTARG in
|
||||
*.l)
|
||||
SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
|
||||
if [ -f "$SRCFILE" ]; then
|
||||
if test -f "$SRCFILE"; then
|
||||
cp "$SRCFILE" lex.yy.c
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
if [ ! -f lex.yy.c ]; then
|
||||
if test ! -f lex.yy.c; then
|
||||
echo 'main() { return 0; }' >lex.yy.c
|
||||
fi
|
||||
;;
|
||||
|
@ -267,11 +270,9 @@ WARNING: \`$1' is $msg. You should only need it if
|
|||
\`Help2man' package in order for those modifications to take
|
||||
effect. You can get \`Help2man' from any GNU archive site."
|
||||
|
||||
file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
|
||||
if test -z "$file"; then
|
||||
file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'`
|
||||
fi
|
||||
if [ -f "$file" ]; then
|
||||
file=`echo "$*" | sed -n "$sed_output"`
|
||||
test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
|
||||
if test -f "$file"; then
|
||||
touch $file
|
||||
else
|
||||
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
|
||||
the \`GNU make' package. Grab either from any GNU archive site."
|
||||
# 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
|
||||
# ... or it is the one specified with @setfilename ...
|
||||
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)
|
||||
test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info
|
||||
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
|
||||
;;
|
||||
|
||||
|
@ -314,13 +324,13 @@ WARNING: \`$1' is $msg. You should only need it if
|
|||
fi
|
||||
firstarg="$1"
|
||||
if shift; then
|
||||
case "$firstarg" in
|
||||
case $firstarg in
|
||||
*o*)
|
||||
firstarg=`echo "$firstarg" | sed s/o//`
|
||||
tar "$firstarg" "$@" && exit 0
|
||||
;;
|
||||
esac
|
||||
case "$firstarg" in
|
||||
case $firstarg in
|
||||
*h*)
|
||||
firstarg=`echo "$firstarg" | sed s/h//`
|
||||
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,113 +1,113 @@
|
|||
////////////////////////////////////////////////////////////////////////////
|
||||
// **** WAVPACK **** //
|
||||
// Hybrid Lossless Wavefile Compressor //
|
||||
// Copyright (c) 1998 - 2005 Conifer Software. //
|
||||
// All Rights Reserved. //
|
||||
// Distributed under the BSD Software License (see license.txt) //
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// wavpack3.h
|
||||
|
||||
// This header file contains all the additional definitions required for
|
||||
// decoding old (versions 1, 2 & 3) WavPack files.
|
||||
|
||||
typedef struct {
|
||||
ushort FormatTag, NumChannels;
|
||||
uint32_t SampleRate, BytesPerSecond;
|
||||
ushort BlockAlign, BitsPerSample;
|
||||
} WaveHeader3;
|
||||
|
||||
#define WaveHeader3Format "SSLLSS"
|
||||
|
||||
typedef struct {
|
||||
char ckID [4];
|
||||
int32_t ckSize;
|
||||
short version;
|
||||
short bits; // added for version 2.00
|
||||
short flags, shift; // added for version 3.00
|
||||
int32_t total_samples, crc, crc2;
|
||||
char extension [4], extra_bc, extras [3];
|
||||
} WavpackHeader3;
|
||||
|
||||
#define WavpackHeader3Format "4LSSSSLLL4L"
|
||||
|
||||
// these flags added for version 3
|
||||
|
||||
#undef MONO_FLAG // these definitions changed for WavPack 4.0
|
||||
#undef CROSS_DECORR
|
||||
#undef JOINT_STEREO
|
||||
|
||||
#define MONO_FLAG 1 // not stereo
|
||||
#define FAST_FLAG 2 // non-adaptive predictor and stereo mode
|
||||
#define RAW_FLAG 4 // raw mode (no .wav header)
|
||||
#define CALC_NOISE 8 // calc noise in lossy mode (no longer stored)
|
||||
#define HIGH_FLAG 0x10 // high quality mode (all modes)
|
||||
#define BYTES_3 0x20 // files have 3-byte samples
|
||||
#define OVER_20 0x40 // samples are over 20 bits
|
||||
#define WVC_FLAG 0x80 // create/use .wvc (no longer stored)
|
||||
#define LOSSY_SHAPE 0x100 // noise shape (lossy mode only)
|
||||
#define VERY_FAST_FLAG 0x200 // double fast (no longer stored)
|
||||
#define NEW_HIGH_FLAG 0x400 // new high quality mode (lossless only)
|
||||
#define CANCEL_EXTREME 0x800 // cancel EXTREME_DECORR
|
||||
#define CROSS_DECORR 0x1000 // decorrelate chans (with EXTREME_DECORR flag)
|
||||
#define NEW_DECORR_FLAG 0x2000 // new high-mode decorrelator
|
||||
#define JOINT_STEREO 0x4000 // joint stereo (lossy and high lossless)
|
||||
#define EXTREME_DECORR 0x8000 // extra decorrelation (+ enables other flags)
|
||||
|
||||
#define STORED_FLAGS 0xfd77 // these are only flags that affect unpacking
|
||||
#define NOT_STORED_FLAGS (~STORED_FLAGS & 0xffff)
|
||||
|
||||
// BitStream stuff (bits.c)
|
||||
|
||||
typedef struct bs3 {
|
||||
void (*wrap)(struct bs3 *bs);
|
||||
uchar *buf, *end, *ptr;
|
||||
uint32_t bufsiz, fpos, sr;
|
||||
WavpackStreamReader *reader;
|
||||
int error, bc;
|
||||
void *id;
|
||||
} Bitstream3;
|
||||
|
||||
#define K_DEPTH 3
|
||||
#define MAX_NTERMS3 18
|
||||
|
||||
typedef struct {
|
||||
WavpackHeader3 wphdr;
|
||||
Bitstream3 wvbits, wvcbits;
|
||||
uint32_t sample_index;
|
||||
int num_terms;
|
||||
|
||||
#ifdef SEEKING
|
||||
struct index_point {
|
||||
char saved;
|
||||
uint32_t sample_index;
|
||||
} index_points [256];
|
||||
|
||||
uchar *unpack_data;
|
||||
uint32_t unpack_size;
|
||||
#endif
|
||||
|
||||
struct {
|
||||
int32_t sum_level, left_level, right_level, diff_level;
|
||||
int last_extra_bits, extra_bits_count, m;
|
||||
int32_t error [2], crc;
|
||||
int32_t sample [2] [2];
|
||||
int weight [2] [1];
|
||||
} dc;
|
||||
|
||||
struct decorr_pass decorr_passes [MAX_NTERMS3];
|
||||
|
||||
struct {
|
||||
uint index [2], k_value [2], ave_k [2];
|
||||
uint32_t zeros_acc, ave_level [K_DEPTH] [2];
|
||||
} w1;
|
||||
|
||||
struct { int last_dbits [2], last_delta_sign [2], bit_limit; } w2;
|
||||
|
||||
struct { int ave_dbits [2], bit_limit; } w3;
|
||||
|
||||
struct {
|
||||
uint32_t fast_level [2], slow_level [2];
|
||||
int bits_acc [2], bitrate;
|
||||
} w4;
|
||||
} WavpackStream3;
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// **** WAVPACK **** //
|
||||
// Hybrid Lossless Wavefile Compressor //
|
||||
// Copyright (c) 1998 - 2006 Conifer Software. //
|
||||
// All Rights Reserved. //
|
||||
// Distributed under the BSD Software License (see license.txt) //
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// wavpack3.h
|
||||
|
||||
// This header file contains all the additional definitions required for
|
||||
// decoding old (versions 1, 2 & 3) WavPack files.
|
||||
|
||||
typedef struct {
|
||||
unsigned short FormatTag, NumChannels;
|
||||
uint32_t SampleRate, BytesPerSecond;
|
||||
unsigned short BlockAlign, BitsPerSample;
|
||||
} WaveHeader3;
|
||||
|
||||
#define WaveHeader3Format "SSLLSS"
|
||||
|
||||
typedef struct {
|
||||
char ckID [4];
|
||||
int32_t ckSize;
|
||||
short version;
|
||||
short bits; // added for version 2.00
|
||||
short flags, shift; // added for version 3.00
|
||||
int32_t total_samples, crc, crc2;
|
||||
char extension [4], extra_bc, extras [3];
|
||||
} WavpackHeader3;
|
||||
|
||||
#define WavpackHeader3Format "4LSSSSLLL4L"
|
||||
|
||||
// these flags added for version 3
|
||||
|
||||
#undef MONO_FLAG // these definitions changed for WavPack 4.0
|
||||
#undef CROSS_DECORR
|
||||
#undef JOINT_STEREO
|
||||
|
||||
#define MONO_FLAG 1 // not stereo
|
||||
#define FAST_FLAG 2 // non-adaptive predictor and stereo mode
|
||||
#define RAW_FLAG 4 // raw mode (no .wav header)
|
||||
#define CALC_NOISE 8 // calc noise in lossy mode (no longer stored)
|
||||
#define HIGH_FLAG 0x10 // high quality mode (all modes)
|
||||
#define BYTES_3 0x20 // files have 3-byte samples
|
||||
#define OVER_20 0x40 // samples are over 20 bits
|
||||
#define WVC_FLAG 0x80 // create/use .wvc (no longer stored)
|
||||
#define LOSSY_SHAPE 0x100 // noise shape (lossy mode only)
|
||||
#define VERY_FAST_FLAG 0x200 // double fast (no longer stored)
|
||||
#define NEW_HIGH_FLAG 0x400 // new high quality mode (lossless only)
|
||||
#define CANCEL_EXTREME 0x800 // cancel EXTREME_DECORR
|
||||
#define CROSS_DECORR 0x1000 // decorrelate chans (with EXTREME_DECORR flag)
|
||||
#define NEW_DECORR_FLAG 0x2000 // new high-mode decorrelator
|
||||
#define JOINT_STEREO 0x4000 // joint stereo (lossy and high lossless)
|
||||
#define EXTREME_DECORR 0x8000 // extra decorrelation (+ enables other flags)
|
||||
|
||||
#define STORED_FLAGS 0xfd77 // these are only flags that affect unpacking
|
||||
#define NOT_STORED_FLAGS (~STORED_FLAGS & 0xffff)
|
||||
|
||||
// BitStream stuff (bits.c)
|
||||
|
||||
typedef struct bs3 {
|
||||
void (*wrap)(struct bs3 *bs);
|
||||
unsigned char *buf, *end, *ptr;
|
||||
uint32_t bufsiz, fpos, sr;
|
||||
WavpackStreamReader *reader;
|
||||
int error, bc;
|
||||
void *id;
|
||||
} Bitstream3;
|
||||
|
||||
#define K_DEPTH 3
|
||||
#define MAX_NTERMS3 18
|
||||
|
||||
typedef struct {
|
||||
WavpackHeader3 wphdr;
|
||||
Bitstream3 wvbits, wvcbits;
|
||||
uint32_t sample_index;
|
||||
int num_terms;
|
||||
|
||||
#ifndef NO_SEEKING
|
||||
struct index_point {
|
||||
char saved;
|
||||
uint32_t sample_index;
|
||||
} index_points [256];
|
||||
|
||||
unsigned char *unpack_data;
|
||||
uint32_t unpack_size;
|
||||
#endif
|
||||
|
||||
struct {
|
||||
int32_t sum_level, left_level, right_level, diff_level;
|
||||
int last_extra_bits, extra_bits_count, m;
|
||||
int32_t error [2], crc;
|
||||
int32_t sample [2] [2];
|
||||
int weight [2] [1];
|
||||
} dc;
|
||||
|
||||
struct decorr_pass decorr_passes [MAX_NTERMS3];
|
||||
|
||||
struct {
|
||||
unsigned int index [2], k_value [2], ave_k [2];
|
||||
uint32_t zeros_acc, ave_level [K_DEPTH] [2];
|
||||
} w1;
|
||||
|
||||
struct { int last_dbits [2], last_delta_sign [2], bit_limit; } w2;
|
||||
|
||||
struct { int ave_dbits [2], bit_limit; } w3;
|
||||
|
||||
struct {
|
||||
uint32_t fast_level [2], slow_level [2];
|
||||
int bits_acc [2], bitrate;
|
||||
} w4;
|
||||
} WavpackStream3;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,680 +1,302 @@
|
|||
////////////////////////////////////////////////////////////////////////////
|
||||
// **** WAVPACK **** //
|
||||
// Hybrid Lossless Wavefile Compressor //
|
||||
// Copyright (c) 1998 - 2005 Conifer Software. //
|
||||
// All Rights Reserved. //
|
||||
// Distributed under the BSD Software License (see license.txt) //
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// wavpack.h
|
||||
|
||||
#ifndef WAVPACK_H
|
||||
#define WAVPACK_H
|
||||
|
||||
#if defined(WIN32)
|
||||
#define FASTCALL __fastcall
|
||||
#else
|
||||
#define FASTCALL
|
||||
#define SetConsoleTitle(x)
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
// This header file contains all the definitions required by WavPack.
|
||||
|
||||
#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
|
||||
|
||||
#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
|
||||
// and pre-4.0 WavPack files that are not in the "raw" mode)
|
||||
|
||||
typedef struct {
|
||||
char ckID [4];
|
||||
uint32_t ckSize;
|
||||
char formType [4];
|
||||
} RiffChunkHeader;
|
||||
|
||||
typedef struct {
|
||||
char ckID [4];
|
||||
uint32_t ckSize;
|
||||
} ChunkHeader;
|
||||
|
||||
#define ChunkHeaderFormat "4L"
|
||||
|
||||
typedef struct {
|
||||
ushort FormatTag, NumChannels;
|
||||
uint32_t SampleRate, BytesPerSecond;
|
||||
ushort BlockAlign, BitsPerSample;
|
||||
ushort cbSize, ValidBitsPerSample;
|
||||
int32_t ChannelMask;
|
||||
ushort SubFormat;
|
||||
char GUID [14];
|
||||
} WaveHeader;
|
||||
|
||||
#define WaveHeaderFormat "SSLLSSSSLS"
|
||||
|
||||
////////////////////////////// WavPack Header /////////////////////////////////
|
||||
|
||||
// Note that this is the ONLY structure that is written to (or read from)
|
||||
// WavPack 4.0 files, and is the preamble to every block in both the .wv
|
||||
// and .wvc files.
|
||||
|
||||
typedef struct {
|
||||
char ckID [4];
|
||||
uint32_t ckSize;
|
||||
short version;
|
||||
uchar track_no, index_no;
|
||||
uint32_t total_samples, block_index, block_samples, flags, crc;
|
||||
} WavpackHeader;
|
||||
|
||||
#define WavpackHeaderFormat "4LS2LLLLL"
|
||||
|
||||
// or-values for "flags"
|
||||
|
||||
#define BYTES_STORED 3 // 1-4 bytes/sample
|
||||
#define MONO_FLAG 4 // not stereo
|
||||
#define HYBRID_FLAG 8 // hybrid mode
|
||||
#define JOINT_STEREO 0x10 // joint stereo
|
||||
#define CROSS_DECORR 0x20 // no-delay cross decorrelation
|
||||
#define HYBRID_SHAPE 0x40 // noise shape (hybrid mode only)
|
||||
#define FLOAT_DATA 0x80 // ieee 32-bit floating point data
|
||||
|
||||
#define INT32_DATA 0x100 // special extended int handling
|
||||
#define HYBRID_BITRATE 0x200 // bitrate noise (hybrid mode only)
|
||||
#define HYBRID_BALANCE 0x400 // balance noise (hybrid stereo mode only)
|
||||
|
||||
#define INITIAL_BLOCK 0x800 // initial block of multichannel segment
|
||||
#define FINAL_BLOCK 0x1000 // final block of multichannel segment
|
||||
|
||||
#define SHIFT_LSB 13
|
||||
#define SHIFT_MASK (0x1fL << SHIFT_LSB)
|
||||
|
||||
#define MAG_LSB 18
|
||||
#define MAG_MASK (0x1fL << MAG_LSB)
|
||||
|
||||
#define SRATE_LSB 23
|
||||
#define SRATE_MASK (0xfL << SRATE_LSB)
|
||||
|
||||
#define FALSE_STEREO 0x40000000 // block is stereo, but data is mono
|
||||
|
||||
#define IGNORED_FLAGS 0x18000000 // reserved, but ignore if encountered
|
||||
#define NEW_SHAPING 0x20000000 // use IIR filter for negative shaping
|
||||
#define UNKNOWN_FLAGS 0x80000000 // also reserved, but refuse decode if
|
||||
// encountered
|
||||
|
||||
#define MONO_DATA (MONO_FLAG | FALSE_STEREO)
|
||||
|
||||
#define MIN_STREAM_VERS 0x402 // lowest stream version we'll decode
|
||||
#define MAX_STREAM_VERS 0x410 // highest stream version we'll decode
|
||||
#define CUR_STREAM_VERS 0x404 // stream version we are writing now
|
||||
|
||||
|
||||
//////////////////////////// WavPack Metadata /////////////////////////////////
|
||||
|
||||
// This is an internal representation of metadata.
|
||||
|
||||
typedef struct {
|
||||
int32_t byte_length;
|
||||
void *data;
|
||||
uchar id;
|
||||
} WavpackMetadata;
|
||||
|
||||
#define ID_UNIQUE 0x3f
|
||||
#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 ///////////////////////////////
|
||||
|
||||
// This internal structure is used during encode to provide configuration to
|
||||
// the encoding engine and during decoding to provide fle information back to
|
||||
// the higher level functions. Not all fields are used in both modes.
|
||||
|
||||
typedef struct {
|
||||
float bitrate, shaping_weight;
|
||||
int bits_per_sample, bytes_per_sample;
|
||||
int qmode, flags, xmode, num_channels, float_norm_exp;
|
||||
int32_t block_samples, extra_flags, sample_rate, channel_mask;
|
||||
uchar md5_checksum [16], md5_read;
|
||||
int num_tag_strings;
|
||||
char **tag_strings;
|
||||
} WavpackConfig;
|
||||
|
||||
#define CONFIG_BYTES_STORED 3 // 1-4 bytes/sample
|
||||
#define CONFIG_MONO_FLAG 4 // not stereo
|
||||
#define CONFIG_HYBRID_FLAG 8 // hybrid mode
|
||||
#define CONFIG_JOINT_STEREO 0x10 // joint stereo
|
||||
#define CONFIG_CROSS_DECORR 0x20 // no-delay cross decorrelation
|
||||
#define CONFIG_HYBRID_SHAPE 0x40 // noise shape (hybrid mode only)
|
||||
#define CONFIG_FLOAT_DATA 0x80 // ieee 32-bit floating point data
|
||||
|
||||
#define CONFIG_ADOBE_MODE 0x100 // "adobe" mode for 32-bit floats
|
||||
#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 {
|
||||
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);
|
||||
|
||||
typedef struct {
|
||||
WavpackConfig config;
|
||||
|
||||
WavpackMetadata *metadata;
|
||||
uint32_t metabytes;
|
||||
int metacount;
|
||||
|
||||
uchar *wrapper_data;
|
||||
uint32_t wrapper_bytes;
|
||||
|
||||
WavpackBlockOutput blockout;
|
||||
void *wv_out, *wvc_out;
|
||||
|
||||
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
|
||||
|
||||
#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 *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 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);
|
||||
|
||||
#endif
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// **** WAVPACK **** //
|
||||
// Hybrid Lossless Wavefile Compressor //
|
||||
// Copyright (c) 1998 - 2006 Conifer Software. //
|
||||
// All Rights Reserved. //
|
||||
// Distributed under the BSD Software License (see license.txt) //
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// wavpack.h
|
||||
|
||||
#ifndef WAVPACK_H
|
||||
#define WAVPACK_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
|
||||
|
||||
// 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). Generally, an
|
||||
// application using the library to read or write WavPack files will not be
|
||||
// concerned with any of these.
|
||||
|
||||
typedef struct {
|
||||
char ckID [4];
|
||||
uint32_t ckSize;
|
||||
char formType [4];
|
||||
} RiffChunkHeader;
|
||||
|
||||
typedef struct {
|
||||
char ckID [4];
|
||||
uint32_t ckSize;
|
||||
} ChunkHeader;
|
||||
|
||||
#define ChunkHeaderFormat "4L"
|
||||
|
||||
typedef struct {
|
||||
unsigned short FormatTag, NumChannels;
|
||||
uint32_t SampleRate, BytesPerSecond;
|
||||
unsigned short BlockAlign, BitsPerSample;
|
||||
unsigned short cbSize, ValidBitsPerSample;
|
||||
int32_t ChannelMask;
|
||||
unsigned short SubFormat;
|
||||
char GUID [14];
|
||||
} WaveHeader;
|
||||
|
||||
#define WaveHeaderFormat "SSLLSSSSLS"
|
||||
|
||||
// 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
|
||||
// files (in little-endian format). Normally, this structure has no use
|
||||
// to an application using the library to read or write WavPack files,
|
||||
// but if an application needs to manually parse WavPack files then this
|
||||
// would be used (with appropriate endian correction).
|
||||
|
||||
typedef struct {
|
||||
char ckID [4];
|
||||
uint32_t ckSize;
|
||||
short version;
|
||||
unsigned char track_no, index_no;
|
||||
uint32_t total_samples, block_index, block_samples, flags, crc;
|
||||
} WavpackHeader;
|
||||
|
||||
#define WavpackHeaderFormat "4LS2LLLLL"
|
||||
|
||||
// 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 INT32_DATA 0x100 // special extended int handling
|
||||
#define HYBRID_BITRATE 0x200 // bitrate noise (hybrid mode only)
|
||||
#define HYBRID_BALANCE 0x400 // balance noise (hybrid stereo mode only)
|
||||
|
||||
#define INITIAL_BLOCK 0x800 // initial block of multichannel segment
|
||||
#define FINAL_BLOCK 0x1000 // final block of multichannel segment
|
||||
|
||||
#define SHIFT_LSB 13
|
||||
#define SHIFT_MASK (0x1fL << SHIFT_LSB)
|
||||
|
||||
#define MAG_LSB 18
|
||||
#define MAG_MASK (0x1fL << MAG_LSB)
|
||||
|
||||
#define SRATE_LSB 23
|
||||
#define SRATE_MASK (0xfL << SRATE_LSB)
|
||||
|
||||
#define FALSE_STEREO 0x40000000 // block is stereo, but data is mono
|
||||
|
||||
#define IGNORED_FLAGS 0x18000000 // reserved, but ignore if encountered
|
||||
#define NEW_SHAPING 0x20000000 // use IIR filter for negative shaping
|
||||
#define UNKNOWN_FLAGS 0x80000000 // also reserved, but refuse decode if
|
||||
// encountered
|
||||
|
||||
#define MONO_DATA (MONO_FLAG | FALSE_STEREO)
|
||||
|
||||
#define MIN_STREAM_VERS 0x402 // lowest stream version we'll decode
|
||||
#define MAX_STREAM_VERS 0x410 // highest stream version we'll decode or encode
|
||||
#define CUR_STREAM_VERS 0x407 // stream version we are writing now
|
||||
|
||||
// These are the mask bit definitions for the metadata chunk id byte (see format.txt)
|
||||
|
||||
#define ID_UNIQUE 0x3f
|
||||
#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) // never used (APEv2)
|
||||
#define ID_CUESHEET (ID_OPTIONAL_DATA | 0x4) // never used (APEv2)
|
||||
#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 ///////////////////////////////
|
||||
|
||||
// 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;
|
||||
unsigned char 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_VERY_HIGH_FLAG 0x1000 // very high
|
||||
#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
|
||||
|
||||
////////////// 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 /////////////////////////////
|
||||
|
||||
// Note: See wputils.c sourcecode for descriptions for using these functions.
|
||||
|
||||
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 // extra mode used, see MODE_XMODE for possible level
|
||||
#define MODE_APETAG 0x100
|
||||
#define MODE_SFX 0x200
|
||||
#define MODE_VERY_HIGH 0x400
|
||||
#define MODE_MD5 0x800
|
||||
#define MODE_XMODE 0x7000 // mask for extra level (1-6, 0=unknown)
|
||||
#define MODE_DNS 0x8000
|
||||
|
||||
char *WavpackGetErrorMessage (WavpackContext *wpc);
|
||||
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 WavpackGetChannelMask (WavpackContext *wpc);
|
||||
int WavpackGetReducedChannels (WavpackContext *wpc);
|
||||
int WavpackGetFloatNormExp (WavpackContext *wpc);
|
||||
int WavpackGetMD5Sum (WavpackContext *wpc, unsigned char data [16]);
|
||||
uint32_t WavpackGetWrapperBytes (WavpackContext *wpc);
|
||||
unsigned char *WavpackGetWrapperData (WavpackContext *wpc);
|
||||
void WavpackFreeWrapper (WavpackContext *wpc);
|
||||
void WavpackSeekTrailingWrapper (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 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 WavpackAppendBinaryTagItem (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, unsigned char 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);
|
||||
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
|
||||
|
|
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 = {
|
||||
|
||||
/* 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 */; };
|
||||
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, ); }; };
|
||||
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 */; };
|
||||
8E7574C609F31BD50080F1EE /* extra1.c in Sources */ = {isa = PBXBuildFile; fileRef = 8E7574B809F31BD50080F1EE /* extra1.c */; };
|
||||
8E7574C709F31BD50080F1EE /* extra2.c in Sources */ = {isa = PBXBuildFile; fileRef = 8E7574B909F31BD50080F1EE /* extra2.c */; };
|
||||
|
@ -29,12 +33,15 @@
|
|||
|
||||
/* Begin PBXFileReference section */
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
|
@ -120,6 +127,7 @@
|
|||
8E7574A809F31B940080F1EE /* Source */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
83DD1DD317FA03F900249519 /* tags.c */,
|
||||
8E7574B709F31BD50080F1EE /* bits.c */,
|
||||
8E7574B809F31BD50080F1EE /* extra1.c */,
|
||||
8E7574B909F31BD50080F1EE /* extra2.c */,
|
||||
|
@ -141,10 +149,12 @@
|
|||
8E7574A909F31B9A0080F1EE /* Headers */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
83DD1DCD17FA038A00249519 /* utils.h */,
|
||||
83DD1DCE17FA038A00249519 /* wavpack_local.h */,
|
||||
83DD1DCF17FA038A00249519 /* wavpack_version.h */,
|
||||
8E7574AF09F31BB90080F1EE /* md5.h */,
|
||||
8E7574B009F31BB90080F1EE /* unpack3.h */,
|
||||
8E7574B109F31BB90080F1EE /* wavpack.h */,
|
||||
8E7574B209F31BB90080F1EE /* wputils.h */,
|
||||
);
|
||||
name = Headers;
|
||||
sourceTree = "<group>";
|
||||
|
@ -157,9 +167,11 @@
|
|||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
8E7574B309F31BB90080F1EE /* md5.h in Headers */,
|
||||
83DD1DD117FA038A00249519 /* wavpack_local.h in Headers */,
|
||||
8E7574B409F31BB90080F1EE /* unpack3.h in Headers */,
|
||||
83DD1DD217FA038A00249519 /* wavpack_version.h in Headers */,
|
||||
83DD1DD017FA038A00249519 /* utils.h in Headers */,
|
||||
8E7574B509F31BB90080F1EE /* wavpack.h in Headers */,
|
||||
8E7574B609F31BB90080F1EE /* wputils.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -225,6 +237,8 @@
|
|||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
83DD1DD517FA04E100249519 /* wavpack.c in Sources */,
|
||||
83DD1DD417FA03F900249519 /* tags.c in Sources */,
|
||||
8E7574C509F31BD50080F1EE /* bits.c in Sources */,
|
||||
8E7574C609F31BD50080F1EE /* extra1.c in Sources */,
|
||||
8E7574C709F31BD50080F1EE /* extra2.c in Sources */,
|
||||
|
|
Loading…
Reference in New Issue