summaryrefslogtreecommitdiff
path: root/apps/codecs/libwavpack
diff options
context:
space:
mode:
Diffstat (limited to 'apps/codecs/libwavpack')
-rw-r--r--apps/codecs/libwavpack/SOURCES1
-rw-r--r--apps/codecs/libwavpack/bits.c163
-rw-r--r--apps/codecs/libwavpack/float.c90
-rw-r--r--apps/codecs/libwavpack/metadata.c136
-rw-r--r--apps/codecs/libwavpack/pack.c450
-rw-r--r--apps/codecs/libwavpack/unpack.c869
-rw-r--r--apps/codecs/libwavpack/wavpack.h317
-rw-r--r--apps/codecs/libwavpack/words.c798
-rw-r--r--apps/codecs/libwavpack/wputils.c431
9 files changed, 2156 insertions, 1099 deletions
diff --git a/apps/codecs/libwavpack/SOURCES b/apps/codecs/libwavpack/SOURCES
index a4f0f2f..1739935 100644
--- a/apps/codecs/libwavpack/SOURCES
+++ b/apps/codecs/libwavpack/SOURCES
@@ -2,6 +2,7 @@ bits.c
float.c
metadata.c
unpack.c
+pack.c
words.c
wputils.c
#if CONFIG_CPU==MCF5249 && !defined(SIMULATOR)
diff --git a/apps/codecs/libwavpack/bits.c b/apps/codecs/libwavpack/bits.c
index 1fe6aac..bf056a9 100644
--- a/apps/codecs/libwavpack/bits.c
+++ b/apps/codecs/libwavpack/bits.c
@@ -31,12 +31,12 @@ void bs_open_read (Bitstream *bs, uchar *buffer_start, uchar *buffer_end, read_s
bs->end = buffer_end;
if (file) {
- bs->ptr = bs->end - 1;
- bs->file_bytes = file_bytes;
- bs->file = file;
+ bs->ptr = bs->end - 1;
+ bs->file_bytes = file_bytes;
+ bs->file = file;
}
else
- bs->ptr = bs->buf - 1;
+ bs->ptr = bs->buf - 1;
bs->wrap = bs_read;
}
@@ -49,31 +49,70 @@ void bs_open_read (Bitstream *bs, uchar *buffer_start, uchar *buffer_end, read_s
static void bs_read (Bitstream *bs)
{
if (bs->file && bs->file_bytes) {
- ulong bytes_read, bytes_to_read = bs->end - bs->buf;
+ ulong bytes_read, bytes_to_read = bs->end - bs->buf;
- if (bytes_to_read > bs->file_bytes)
- bytes_to_read = bs->file_bytes;
+ if (bytes_to_read > bs->file_bytes)
+ bytes_to_read = bs->file_bytes;
- bytes_read = bs->file (bs->buf, bytes_to_read);
+ bytes_read = bs->file (bs->buf, bytes_to_read);
- if (bytes_read) {
- bs->end = bs->buf + bytes_read;
- bs->file_bytes -= bytes_read;
- }
- else {
- memset (bs->buf, -1, bs->end - bs->buf);
- bs->error = 1;
- }
+ if (bytes_read) {
+ bs->end = bs->buf + bytes_read;
+ bs->file_bytes -= bytes_read;
+ }
+ else {
+ memset (bs->buf, -1, bs->end - bs->buf);
+ bs->error = 1;
+ }
}
else
- bs->error = 1;
+ bs->error = 1;
if (bs->error)
- memset (bs->buf, -1, bs->end - bs->buf);
+ memset (bs->buf, -1, bs->end - bs->buf);
bs->ptr = bs->buf;
}
+// 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.
+
+ulong bs_close_write (Bitstream *bs)
+{
+ ulong bytes_written;
+
+ if (bs->error)
+ return (ulong) -1;
+
+ while (bs->bc || ((bs->ptr - bs->buf) & 1)) putbit_1 (bs);
+ bytes_written = bs->ptr - bs->buf;
+ CLEAR (*bs);
+ return bytes_written;
+}
+
/////////////////////// Endian Correction Routines ////////////////////////////
void little_endian_to_native (void *data, char *format)
@@ -82,27 +121,27 @@ void little_endian_to_native (void *data, char *format)
long temp;
while (*format) {
- switch (*format) {
- case 'L':
- temp = cp [0] + ((long) cp [1] << 8) + ((long) cp [2] << 16) + ((long) cp [3] << 24);
- * (long *) cp = temp;
- cp += 4;
- break;
-
- case 'S':
- temp = cp [0] + (cp [1] << 8);
- * (short *) cp = (short) temp;
- cp += 2;
- break;
-
- default:
- if (*format >= '0' && *format <= '9')
- cp += *format - '0';
-
- break;
- }
-
- format++;
+ switch (*format) {
+ case 'L':
+ temp = cp [0] + ((long) cp [1] << 8) + ((long) cp [2] << 16) + ((long) cp [3] << 24);
+ * (long *) cp = temp;
+ cp += 4;
+ break;
+
+ case 'S':
+ temp = cp [0] + (cp [1] << 8);
+ * (short *) cp = (short) temp;
+ cp += 2;
+ break;
+
+ default:
+ if (*format >= '0' && *format <= '9')
+ cp += *format - '0';
+
+ break;
+ }
+
+ format++;
}
}
@@ -112,28 +151,28 @@ void native_to_little_endian (void *data, char *format)
long temp;
while (*format) {
- switch (*format) {
- case 'L':
- temp = * (long *) 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 (*format >= '0' && *format <= '9')
- cp += *format - '0';
-
- break;
- }
-
- format++;
+ switch (*format) {
+ case 'L':
+ temp = * (long *) 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 (*format >= '0' && *format <= '9')
+ cp += *format - '0';
+
+ break;
+ }
+
+ format++;
}
}
diff --git a/apps/codecs/libwavpack/float.c b/apps/codecs/libwavpack/float.c
index 3e678e8..2208e61 100644
--- a/apps/codecs/libwavpack/float.c
+++ b/apps/codecs/libwavpack/float.c
@@ -1,8 +1,8 @@
////////////////////////////////////////////////////////////////////////////
-// **** WAVPACK **** //
-// Hybrid Lossless Wavefile Compressor //
-// Copyright (c) 1998 - 2004 Conifer Software. //
-// All Rights Reserved. //
+// **** WAVPACK **** //
+// Hybrid Lossless Wavefile Compressor //
+// Copyright (c) 1998 - 2004 Conifer Software. //
+// All Rights Reserved. //
// Distributed under the BSD Software License (see license.txt) //
////////////////////////////////////////////////////////////////////////////
@@ -16,7 +16,7 @@ int read_float_info (WavpackStream *wps, WavpackMetadata *wpmd)
char *byteptr = wpmd->data;
if (bytecnt != 4)
- return FALSE;
+ return FALSE;
wps->float_flags = *byteptr++;
wps->float_shift = *byteptr++;
@@ -28,35 +28,35 @@ int read_float_info (WavpackStream *wps, WavpackMetadata *wpmd)
void float_values (WavpackStream *wps, long *values, long 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)
- outval.exponent = 255;
- 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;
+ 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)
+ outval.exponent = 255;
+ 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;
}
}
@@ -66,18 +66,18 @@ void float_normalize (long *values, long num_values, int delta_exp)
int exp;
if (!delta_exp)
- return;
+ 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++;
+ 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++;
}
}
diff --git a/apps/codecs/libwavpack/metadata.c b/apps/codecs/libwavpack/metadata.c
index 661b25e..ebc7dcf 100644
--- a/apps/codecs/libwavpack/metadata.c
+++ b/apps/codecs/libwavpack/metadata.c
@@ -12,46 +12,48 @@
#include "wavpack.h"
+#include <string.h>
+
int read_metadata_buff (WavpackContext *wpc, WavpackMetadata *wpmd)
{
uchar tchar;
if (!wpc->infile (&wpmd->id, 1) || !wpc->infile (&tchar, 1))
- return FALSE;
+ return FALSE;
wpmd->byte_length = tchar << 1;
if (wpmd->id & ID_LARGE) {
- wpmd->id &= ~ID_LARGE;
+ wpmd->id &= ~ID_LARGE;
- if (!wpc->infile (&tchar, 1))
- return FALSE;
+ if (!wpc->infile (&tchar, 1))
+ return FALSE;
- wpmd->byte_length += (long) tchar << 9;
+ wpmd->byte_length += (long) tchar << 9;
- if (!wpc->infile (&tchar, 1))
- return FALSE;
+ if (!wpc->infile (&tchar, 1))
+ return FALSE;
- wpmd->byte_length += (long) tchar << 17;
+ wpmd->byte_length += (long) tchar << 17;
}
if (wpmd->id & ID_ODD_SIZE) {
- wpmd->id &= ~ID_ODD_SIZE;
- wpmd->byte_length--;
+ wpmd->id &= ~ID_ODD_SIZE;
+ wpmd->byte_length--;
}
if (wpmd->byte_length && wpmd->byte_length <= (long)sizeof (wpc->read_buffer)) {
- ulong bytes_to_read = wpmd->byte_length + (wpmd->byte_length & 1);
+ ulong bytes_to_read = wpmd->byte_length + (wpmd->byte_length & 1);
- if (wpc->infile (wpc->read_buffer, bytes_to_read) != (long) bytes_to_read) {
- wpmd->data = NULL;
- return FALSE;
- }
+ if (wpc->infile (wpc->read_buffer, bytes_to_read) != (long) bytes_to_read) {
+ wpmd->data = NULL;
+ return FALSE;
+ }
- wpmd->data = wpc->read_buffer;
+ wpmd->data = wpc->read_buffer;
}
else
- wpmd->data = NULL;
+ wpmd->data = NULL;
return TRUE;
}
@@ -61,45 +63,89 @@ int process_metadata (WavpackContext *wpc, WavpackMetadata *wpmd)
WavpackStream *wps = &wpc->stream;
switch (wpmd->id) {
- case ID_DUMMY:
- return TRUE;
+ 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_DECORR_TERMS:
- return read_decorr_terms (wps, wpmd);
+ case ID_HYBRID_PROFILE:
+ return read_hybrid_profile (wps, wpmd);
- case ID_DECORR_WEIGHTS:
- return read_decorr_weights (wps, wpmd);
+ case ID_FLOAT_INFO:
+ return read_float_info (wps, wpmd);
- case ID_DECORR_SAMPLES:
- return read_decorr_samples (wps, wpmd);
+ case ID_INT32_INFO:
+ return read_int32_info (wps, wpmd);
- case ID_ENTROPY_VARS:
- return read_entropy_vars (wps, wpmd);
+ case ID_CHANNEL_INFO:
+ return read_channel_info (wpc, wpmd);
- case ID_HYBRID_PROFILE:
- return read_hybrid_profile (wps, wpmd);
+ case ID_CONFIG_BLOCK:
+ return read_config_info (wpc, wpmd);
+
+ case ID_WV_BITSTREAM:
+ return init_wv_bitstream (wpc, wpmd);
+
+ case ID_SHAPING_WEIGHTS:
+ case ID_WVC_BITSTREAM:
+ case ID_WVX_BITSTREAM:
+ return TRUE;
+
+ default:
+ return (wpmd->id & ID_OPTIONAL_DATA) ? TRUE : FALSE;
+ }
+}
- case ID_FLOAT_INFO:
- return read_float_info (wps, wpmd);
+int copy_metadata (WavpackMetadata *wpmd, uchar *buffer_start, uchar *buffer_end)
+{
+ ulong mdsize = wpmd->byte_length + (wpmd->byte_length & 1);
+ WavpackHeader *wphdr = (WavpackHeader *) buffer_start;
- case ID_INT32_INFO:
- return read_int32_info (wps, wpmd);
+ if (wpmd->byte_length & 1)
+ ((char *) wpmd->data) [wpmd->byte_length] = 0;
- case ID_CHANNEL_INFO:
- return read_channel_info (wpc, wpmd);
+ mdsize += (wpmd->byte_length > 510) ? 4 : 2;
+ buffer_start += wphdr->ckSize + 8;
- case ID_CONFIG_BLOCK:
- return read_config_info (wpc, wpmd);
+ if (buffer_start + mdsize >= buffer_end)
+ return FALSE;
- case ID_WV_BITSTREAM:
- return init_wv_bitstream (wpc, wpmd);
+ buffer_start [0] = wpmd->id | (wpmd->byte_length & 1 ? ID_ODD_SIZE : 0);
+ buffer_start [1] = (wpmd->byte_length + 1) >> 1;
- case ID_SHAPING_WEIGHTS:
- case ID_WVC_BITSTREAM:
- case ID_WVX_BITSTREAM:
- return TRUE;
+ 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;
+ }
- default:
- return (wpmd->id & ID_OPTIONAL_DATA) ? TRUE : FALSE;
+ 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;
}
+
+void free_metadata (WavpackMetadata *wpmd)
+{
+ wpmd->data = NULL;
+}
+
diff --git a/apps/codecs/libwavpack/pack.c b/apps/codecs/libwavpack/pack.c
new file mode 100644
index 0000000..e695388
--- /dev/null
+++ b/apps/codecs/libwavpack/pack.c
@@ -0,0 +1,450 @@
+////////////////////////////////////////////////////////////////////////////
+// **** WAVPACK **** //
+// Hybrid Lossless Wavefile Compressor //
+// Copyright (c) 1998 - 2005 Conifer Software. //
+// All Rights Reserved. //
+// Distributed under the BSD Software License (see license.txt) //
+////////////////////////////////////////////////////////////////////////////
+
+// pack.c
+
+// This module actually handles the compression of the audio data, except for
+// the entropy coding which is handled by the words? modules. For efficiency,
+// the conversion is isolated to tight loops that handle an entire buffer.
+
+#include "wavpack.h"
+
+#include <string.h>
+
+// This flag provides faster encoding speed at the expense of more code. The
+// improvement applies to 16-bit stereo lossless only.
+
+//////////////////////////////// local tables ///////////////////////////////
+
+// These two tables specify the characteristics of the decorrelation filters.
+// Each term represents one layer of the sequential filter, where positive
+// values indicate the relative sample involved from the same channel (1=prev),
+// 17 & 18 are special functions using the previous 2 samples, and negative
+// values indicate cross channel decorrelation (in stereo only).
+
+static const char default_terms [] = { 18,18,2,3,-2,0 };
+static const char high_terms [] = { 18,18,2,3,-2,18,2,4,7,5,3,6,8,-1,18,2,0 };
+static const char fast_terms [] = { 17,17,0 };
+
+///////////////////////////// executable code ////////////////////////////////
+
+// This function initializes everything required to pack WavPack bitstreams
+// and must be called BEFORE any other function in this module.
+
+void pack_init (WavpackContext *wpc)
+{
+ WavpackStream *wps = &wpc->stream;
+ ulong flags = wps->wphdr.flags;
+ struct decorr_pass *dpp;
+ const char *term_string;
+ int ti;
+
+ wps->sample_index = 0;
+ CLEAR (wps->decorr_passes);
+
+ if (wpc->config.flags & CONFIG_HIGH_FLAG)
+ term_string = high_terms;
+ else if (wpc->config.flags & CONFIG_FAST_FLAG)
+ term_string = fast_terms;
+ else
+ term_string = default_terms;
+
+ for (dpp = wps->decorr_passes, ti = 0; term_string [ti]; ti++)
+ if (term_string [ti] >= 0 || (flags & CROSS_DECORR)) {
+ dpp->term = term_string [ti];
+ dpp++->delta = 2;
+ }
+ else if (!(flags & MONO_FLAG)) {
+ dpp->term = -3;
+ dpp++->delta = 2;
+ }
+
+ wps->num_terms = dpp - wps->decorr_passes;
+ init_words (wps);
+}
+
+// Allocate room for and copy the decorrelation terms from the decorr_passes
+// array into the specified metadata structure. Both the actual term id and
+// the delta are packed into single characters.
+
+static void write_decorr_terms (WavpackStream *wps, WavpackMetadata *wpmd)
+{
+ int tcount = wps->num_terms;
+ struct decorr_pass *dpp;
+ char *byteptr;
+
+ byteptr = wpmd->data = wpmd->temp_data;
+ wpmd->id = ID_DECORR_TERMS;
+
+ for (dpp = wps->decorr_passes; tcount--; ++dpp)
+ *byteptr++ = ((dpp->term + 5) & 0x1f) | ((dpp->delta << 5) & 0xe0);
+
+ wpmd->byte_length = byteptr - (char *) wpmd->data;
+}
+
+// Allocate room for and copy the decorrelation term weights from the
+// decorr_passes array into the specified metadata structure. The weights
+// range +/-1024, but are rounded and truncated to fit in signed chars for
+// metadata storage. Weights are separate for the two channels
+
+static void write_decorr_weights (WavpackStream *wps, WavpackMetadata *wpmd)
+{
+ int tcount = wps->num_terms;
+ struct decorr_pass *dpp;
+ char *byteptr;
+
+ byteptr = wpmd->data = wpmd->temp_data;
+ wpmd->id = ID_DECORR_WEIGHTS;
+
+ for (dpp = wps->decorr_passes; tcount--; ++dpp) {
+ dpp->weight_A = restore_weight (*byteptr++ = store_weight (dpp->weight_A));
+
+ if (!(wps->wphdr.flags & MONO_FLAG))
+ dpp->weight_B = restore_weight (*byteptr++ = store_weight (dpp->weight_B));
+ }
+
+ wpmd->byte_length = byteptr - (char *) wpmd->data;
+}
+
+// Allocate room for and copy the decorrelation samples from the decorr_passes
+// array into the specified metadata structure. The samples are signed 32-bit
+// values, but are converted to signed log2 values for storage in metadata.
+// Values are stored for both channels and are specified from the first term
+// with unspecified samples set to zero. The number of samples stored varies
+// with the actual term value, so those must obviously be specified before
+// these in the metadata list. Any number of terms can have their samples
+// specified from no terms to all the terms, however I have found that
+// sending more than the first term's samples is a waste. The "wcount"
+// variable can be set to the number of terms to have their samples stored.
+
+static void write_decorr_samples (WavpackStream *wps, WavpackMetadata *wpmd)
+{
+ int tcount = wps->num_terms, wcount = 1, temp;
+ struct decorr_pass *dpp;
+ uchar *byteptr;
+
+ byteptr = wpmd->data = wpmd->temp_data;
+ wpmd->id = ID_DECORR_SAMPLES;
+
+ for (dpp = wps->decorr_passes; tcount--; ++dpp)
+ if (wcount) {
+ if (dpp->term > MAX_TERM) {
+ dpp->samples_A [0] = exp2s (temp = log2s (dpp->samples_A [0]));
+ *byteptr++ = temp;
+ *byteptr++ = temp >> 8;
+ dpp->samples_A [1] = exp2s (temp = log2s (dpp->samples_A [1]));
+ *byteptr++ = temp;
+ *byteptr++ = temp >> 8;
+
+ if (!(wps->wphdr.flags & MONO_FLAG)) {
+ dpp->samples_B [0] = exp2s (temp = log2s (dpp->samples_B [0]));
+ *byteptr++ = temp;
+ *byteptr++ = temp >> 8;
+ dpp->samples_B [1] = exp2s (temp = log2s (dpp->samples_B [1]));
+ *byteptr++ = temp;
+ *byteptr++ = temp >> 8;
+ }
+ }
+ else if (dpp->term < 0) {
+ dpp->samples_A [0] = exp2s (temp = log2s (dpp->samples_A [0]));
+ *byteptr++ = temp;
+ *byteptr++ = temp >> 8;
+ dpp->samples_B [0] = exp2s (temp = log2s (dpp->samples_B [0]));
+ *byteptr++ = temp;
+ *byteptr++ = temp >> 8;
+ }
+ else {
+ int m = 0, cnt = dpp->term;
+
+ while (cnt--) {
+ dpp->samples_A [m] = exp2s (temp = log2s (dpp->samples_A [m]));
+ *byteptr++ = temp;
+ *byteptr++ = temp >> 8;
+
+ if (!(wps->wphdr.flags & MONO_FLAG)) {
+ dpp->samples_B [m] = exp2s (temp = log2s (dpp->samples_B [m]));
+ *byteptr++ = temp;
+ *byteptr++ = temp >> 8;
+ }
+
+ m++;
+ }
+ }
+
+ wcount--;
+ }
+ else {
+ CLEAR (dpp->samples_A);
+ CLEAR (dpp->samples_B);
+ }
+
+ wpmd->byte_length = byteptr - (uchar *) wpmd->data;
+}
+
+// Allocate room for and copy the configuration information into the specified
+// metadata structure. Currently, we just store the upper 3 bytes of
+// config.flags and only in the first block of audio data. Note that this is
+// for informational purposes not required for playback or decoding (like
+// whether high or fast mode was specified).
+
+static void write_config_info (WavpackContext *wpc, WavpackMetadata *wpmd)
+{
+ char *byteptr;
+
+ byteptr = wpmd->data = wpmd->temp_data;
+ wpmd->id = ID_CONFIG_BLOCK;
+ *byteptr++ = (char) (wpc->config.flags >> 8);
+ *byteptr++ = (char) (wpc->config.flags >> 16);
+ *byteptr++ = (char) (wpc->config.flags >> 24);
+ wpmd->byte_length = byteptr - (char *) wpmd->data;
+}
+
+// Pack an entire block of samples (either mono or stereo) into a completed
+// WavPack block. This function is actually a shell for pack_samples() and
+// performs tasks like handling any shift required by the format, preprocessing
+// of floating point data or integer data over 24 bits wide, and implementing
+// the "extra" mode (via the extra?.c modules). It is assumed that there is
+// sufficient space for the completed block at "wps->blockbuff" and that
+// "wps->blockend" points to the end of the available space. A return value of
+// FALSE indicates an error.
+
+static int pack_samples (WavpackContext *wpc, long *buffer);
+
+int pack_block (WavpackContext *wpc, long *buffer)
+{
+ WavpackStream *wps = &wpc->stream;
+ ulong flags = wps->wphdr.flags, sflags = wps->wphdr.flags;
+ ulong sample_count = wps->wphdr.block_samples;
+
+ if (flags & SHIFT_MASK) {
+ int shift = (flags & SHIFT_MASK) >> SHIFT_LSB;
+ int mag = (flags & MAG_MASK) >> MAG_LSB;
+ ulong cnt = sample_count;
+ long *ptr = buffer;
+
+ if (flags & MONO_FLAG)
+ while (cnt--)
+ *ptr++ >>= shift;
+ else
+ while (cnt--) {
+ *ptr++ >>= shift;
+ *ptr++ >>= shift;
+ }
+
+ if ((mag -= shift) < 0)
+ flags &= ~MAG_MASK;
+ else
+ flags -= (1 << MAG_LSB) * shift;
+
+ wps->wphdr.flags = flags;
+ }
+
+ if (!pack_samples (wpc, buffer)) {
+ wps->wphdr.flags = sflags;
+ return FALSE;
+ }
+ else {
+ wps->wphdr.flags = sflags;
+ return TRUE;
+ }
+}
+
+// Pack an entire block of samples (either mono or stereo) into a completed
+// WavPack block. It is assumed that there is sufficient space for the
+// completed block at "wps->blockbuff" and that "wps->blockend" points to the
+// end of the available space. A return value of FALSE indicates an error.
+// Any unsent metadata is transmitted first, then required metadata for this
+// block is sent, and finally the compressed integer data is sent. If a "wpx"
+// stream is required for floating point data or large integer data, then this
+// must be handled outside this function. To find out how much data was written
+// the caller must look at the ckSize field of the written WavpackHeader, NOT
+// the one in the WavpackStream.
+
+static int pack_samples (WavpackContext *wpc, long *buffer)
+{
+ WavpackStream *wps = &wpc->stream;
+ ulong sample_count = wps->wphdr.block_samples;
+ ulong flags = wps->wphdr.flags, data_count;
+ struct decorr_pass *dpp;
+ WavpackMetadata wpmd;
+ int tcount, m = 0;
+ ulong crc, i;
+ long *bptr;
+
+ crc = 0xffffffff;
+ wps->wphdr.ckSize = sizeof (WavpackHeader) - 8;
+ memcpy (wps->blockbuff, &wps->wphdr, sizeof (WavpackHeader));
+
+ if (wpc->wrapper_bytes) {
+ wpmd.id = ID_RIFF_HEADER;
+ wpmd.byte_length = wpc->wrapper_bytes;
+ wpmd.data = wpc->wrapper_data;
+ copy_metadata (&wpmd, wps->blockbuff, wps->blockend);
+ free_metadata (&wpmd);
+ wpc->wrapper_data = NULL;
+ wpc->wrapper_bytes = 0;
+ }
+
+ if (!sample_count)
+ return TRUE;
+
+ write_decorr_terms (wps, &wpmd);
+ copy_metadata (&wpmd, wps->blockbuff, wps->blockend);
+ free_metadata (&wpmd);
+
+ write_decorr_weights (wps, &wpmd);
+ copy_metadata (&wpmd, wps->blockbuff, wps->blockend);
+ free_metadata (&wpmd);
+
+ write_decorr_samples (wps, &wpmd);
+ copy_metadata (&wpmd, wps->blockbuff, wps->blockend);
+ free_metadata (&wpmd);
+
+ write_entropy_vars (wps, &wpmd);
+ copy_metadata (&wpmd, wps->blockbuff, wps->blockend);
+ free_metadata (&wpmd);
+
+ if ((flags & INITIAL_BLOCK) && !wps->sample_index) {
+ write_config_info (wpc, &wpmd);
+ copy_metadata (&wpmd, wps->blockbuff, wps->blockend);
+ free_metadata (&wpmd);
+ }
+
+ bs_open_write (&wps->wvbits, wps->blockbuff + ((WavpackHeader *) wps->blockbuff)->ckSize + 12, wps->blockend);
+
+ /////////////////////// handle lossless mono mode /////////////////////////
+
+ if (!(flags & HYBRID_FLAG) && (flags & MONO_FLAG))
+ for (bptr = buffer, i = 0; i < sample_count; ++i) {
+ long code;
+
+ crc = crc * 3 + (code = *bptr++);
+
+ for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++) {
+ long sam;
+
+ if (dpp->term > MAX_TERM) {
+ if (dpp->term & 1)
+ sam = 2 * dpp->samples_A [0] - dpp->samples_A [1];
+ else
+ sam = (3 * dpp->samples_A [0] - dpp->samples_A [1]) >> 1;
+
+ dpp->samples_A [1] = dpp->samples_A [0];
+ dpp->samples_A [0] = code;
+ }
+ else {
+ sam = dpp->samples_A [m];
+ dpp->samples_A [(m + dpp->term) & (MAX_TERM - 1)] = code;
+ }
+
+ code -= apply_weight_i (dpp->weight_A, sam);
+ update_weight (dpp->weight_A, 2, sam, code);
+ }
+
+ m = (m + 1) & (MAX_TERM - 1);
+ send_word_lossless (wps, code, 0);
+ }
+
+ //////////////////// handle the lossless stereo mode //////////////////////
+
+ else if (!(flags & HYBRID_FLAG) && !(flags & MONO_FLAG))
+ for (bptr = buffer, i = 0; i < sample_count; ++i, bptr += 2) {
+ long left, right, sam_A, sam_B;
+
+ crc = crc * 3 + (left = bptr [0]);
+ crc = crc * 3 + (right = bptr [1]);
+
+ if (flags & JOINT_STEREO)
+ right += ((left -= right) >> 1);
+
+ for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount-- ; dpp++) {
+ if (dpp->term > 0) {
+ if (dpp->term > MAX_TERM) {
+ if (dpp->term & 1) {
+ sam_A = 2 * dpp->samples_A [0] - dpp->samples_A [1];
+ sam_B = 2 * dpp->samples_B [0] - dpp->samples_B [1];
+ }
+ else {
+ sam_A = (3 * dpp->samples_A [0] - dpp->samples_A [1]) >> 1;
+ sam_B = (3 * dpp->samples_B [0] - dpp->samples_B [1]) >> 1;
+ }
+
+ dpp->samples_A [1] = dpp->samples_A [0];
+ dpp->samples_B [1] = dpp->samples_B [0];
+ dpp->samples_A [0] = left;
+ dpp->samples_B [0] = right;
+ }
+ else {
+ int k = (m + dpp->term) & (MAX_TERM - 1);
+
+ sam_A = dpp->samples_A [m];
+ sam_B = dpp->samples_B [m];
+ dpp->samples_A [k] = left;
+ dpp->samples_B [k] = right;
+ }
+
+ left -= apply_weight_i (dpp->weight_A, sam_A);
+ right -= apply_weight_i (dpp->weight_B, sam_B);
+ update_weight (dpp->weight_A, 2, sam_A, left);
+ update_weight (dpp->weight_B, 2, sam_B, right);
+ }
+ else {
+ sam_A = (dpp->term == -2) ? right : dpp->samples_A [0];
+ sam_B = (dpp->term == -1) ? left : dpp->samples_B [0];
+ dpp->samples_A [0] = right;
+ dpp->samples_B [0] = left;
+ left -= apply_weight_i (dpp->weight_A, sam_A);
+ right -= apply_weight_i (dpp->weight_B, sam_B);
+ update_weight_clip (dpp->weight_A, 2, sam_A, left);
+ update_weight_clip (dpp->weight_B, 2, sam_B, right);
+ }
+ }
+
+ m = (m + 1) & (MAX_TERM - 1);
+ send_word_lossless (wps, left, 0);
+ send_word_lossless (wps, right, 1);
+ }
+
+ if (m)
+ for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++)
+ if (dpp->term > 0 && dpp->term <= MAX_TERM) {
+ long temp_A [MAX_TERM], temp_B [MAX_TERM];
+ int k;
+
+ memcpy (temp_A, dpp->samples_A, sizeof (dpp->samples_A));
+ memcpy (temp_B, dpp->samples_B, sizeof (dpp->samples_B));
+
+ for (k = 0; k < MAX_TERM; k++) {
+ dpp->samples_A [k] = temp_A [m];
+ dpp->samples_B [k] = temp_B [m];
+ m = (m + 1) & (MAX_TERM - 1);
+ }
+ }
+
+ flush_word (wps);
+ data_count = bs_close_write (&wps->wvbits);
+
+ if (data_count) {
+ if (data_count != (ulong) -1) {
+ uchar *cptr = wps->blockbuff + ((WavpackHeader *) wps->blockbuff)->ckSize + 8;
+
+ *cptr++ = ID_WV_BITSTREAM | ID_LARGE;
+ *cptr++ = data_count >> 1;
+ *cptr++ = data_count >> 9;
+ *cptr++ = data_count >> 17;
+ ((WavpackHeader *) wps->blockbuff)->ckSize += data_count + 4;
+ }
+ else
+ return FALSE;
+ }
+
+ ((WavpackHeader *) wps->blockbuff)->crc = crc;
+
+ wps->sample_index += sample_count;
+ return TRUE;
+}
diff --git a/apps/codecs/libwavpack/unpack.c b/apps/codecs/libwavpack/unpack.c
index 5afaac3..aaab2aa 100644
--- a/apps/codecs/libwavpack/unpack.c
+++ b/apps/codecs/libwavpack/unpack.c
@@ -1,8 +1,8 @@
////////////////////////////////////////////////////////////////////////////
-// **** WAVPACK **** //
-// Hybrid Lossless Wavefile Compressor //
-// Copyright (c) 1998 - 2004 Conifer Software. //
-// All Rights Reserved. //
+// **** WAVPACK **** //
+// Hybrid Lossless Wavefile Compressor //
+// Copyright (c) 1998 - 2004 Conifer Software. //
+// All Rights Reserved. //
// Distributed under the BSD Software License (see license.txt) //
////////////////////////////////////////////////////////////////////////////
@@ -15,46 +15,13 @@
#include "wavpack.h"
+#include <stdlib.h>
#include <string.h>
-#include <math.h>
-static void strcpy_loc (char *dst, char *src) { while (*src) *dst++ = *src++; *dst = 0; }
+static void strcpy_loc (char *dst, char *src) { while ((*dst++ = *src++) != 0); }
#define LOSSY_MUTE
-//////////////////////////////// local macros /////////////////////////////////
-
-// these macros implement the weight application and update operations
-// that are at the heart of the decorrelation loops
-
-#if 0 // PERFCOND
-#define apply_weight_i(weight, sample) ((weight * sample + 512) >> 10)
-#else
-#define apply_weight_i(weight, sample) ((((weight * sample) >> 8) + 2) >> 2)
-#endif
-
-#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 0 // 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_clip(weight, delta, source, result) \
- if (source && result && ((source ^ result) < 0 ? (weight -= delta) < -1024 : (weight += delta) > 1024)) \
- weight = weight < 0 ? -1024 : 1024;
-
///////////////////////////// executable code ////////////////////////////////
// This function initializes everything required to unpack a WavPack block
@@ -69,7 +36,7 @@ int unpack_init (WavpackContext *wpc)
WavpackMetadata wpmd;
if (wps->wphdr.block_samples && wps->wphdr.block_index != (ulong) -1)
- wps->sample_index = wps->wphdr.block_index;
+ wps->sample_index = wps->wphdr.block_index;
wps->mute_error = FALSE;
wps->crc = 0xffffffff;
@@ -78,27 +45,27 @@ int unpack_init (WavpackContext *wpc)
CLEAR (wps->w);
while (read_metadata_buff (wpc, &wpmd)) {
- if (!process_metadata (wpc, &wpmd)) {
- strcpy_loc (wpc->error_message, "invalid metadata!");
- return FALSE;
- }
+ if (!process_metadata (wpc, &wpmd)) {
+ strcpy_loc (wpc->error_message, "invalid metadata!");
+ return FALSE;
+ }
- if (wpmd.id == ID_WV_BITSTREAM)
- break;
+ if (wpmd.id == ID_WV_BITSTREAM)
+ break;
}
if (wps->wphdr.block_samples && !bs_is_open (&wps->wvbits)) {
- strcpy_loc (wpc->error_message, "invalid WavPack file!");
- return FALSE;
+ strcpy_loc (wpc->error_message, "invalid WavPack file!");
+ return FALSE;
}
if (wps->wphdr.block_samples) {
- if ((wps->wphdr.flags & INT32_DATA) && wps->int32_sent_bits)
- wpc->lossy_blocks = TRUE;
+ if ((wps->wphdr.flags & INT32_DATA) && wps->int32_sent_bits)
+ wpc->lossy_blocks = TRUE;
- if ((wps->wphdr.flags & FLOAT_DATA) &&
- wps->float_flags & (FLOAT_EXCEPTIONS | FLOAT_ZEROS_SENT | FLOAT_SHIFT_SENT | FLOAT_SHIFT_SAME))
- wpc->lossy_blocks = TRUE;
+ if ((wps->wphdr.flags & FLOAT_DATA) &&
+ wps->float_flags & (FLOAT_EXCEPTIONS | FLOAT_ZEROS_SENT | FLOAT_SHIFT_SENT | FLOAT_SHIFT_SAME))
+ wpc->lossy_blocks = TRUE;
}
return TRUE;
@@ -112,10 +79,10 @@ int init_wv_bitstream (WavpackContext *wpc, WavpackMetadata *wpmd)
WavpackStream *wps = &wpc->stream;
if (wpmd->data)
- bs_open_read (&wps->wvbits, wpmd->data, (char *) wpmd->data + wpmd->byte_length, NULL, 0);
+ bs_open_read (&wps->wvbits, wpmd->data, (char *) wpmd->data + wpmd->byte_length, NULL, 0);
else if (wpmd->byte_length)
- bs_open_read (&wps->wvbits, wpc->read_buffer, wpc->read_buffer + sizeof (wpc->read_buffer),
- wpc->infile, wpmd->byte_length + (wpmd->byte_length & 1));
+ bs_open_read (&wps->wvbits, wpc->read_buffer, wpc->read_buffer + sizeof (wpc->read_buffer),
+ wpc->infile, wpmd->byte_length + (wpmd->byte_length & 1));
return TRUE;
}
@@ -134,16 +101,16 @@ int read_decorr_terms (WavpackStream *wps, WavpackMetadata *wpmd)
struct decorr_pass *dpp;
if (termcnt > MAX_NTERMS)
- return FALSE;
+ return FALSE;
wps->num_terms = termcnt;
for (dpp = wps->decorr_passes + termcnt - 1; termcnt--; dpp--) {
- dpp->term = (int)(*byteptr & 0x1f) - 5;
- dpp->delta = (*byteptr++ >> 5) & 0x7;
+ dpp->term = (int)(*byteptr & 0x1f) - 5;
+ dpp->delta = (*byteptr++ >> 5) & 0x7;
- if (!dpp->term || dpp->term < -3 || (dpp->term > MAX_TERM && dpp->term < 17) || dpp->term > 18)
- return FALSE;
+ if (!dpp->term || dpp->term < -3 || (dpp->term > MAX_TERM && dpp->term < 17) || dpp->term > 18)
+ return FALSE;
}
return TRUE;
@@ -162,19 +129,19 @@ int read_decorr_weights (WavpackStream *wps, WavpackMetadata *wpmd)
struct decorr_pass *dpp;
if (!(wps->wphdr.flags & MONO_FLAG))
- termcnt /= 2;
+ termcnt /= 2;
if (termcnt > wps->num_terms)
- return FALSE;
+ return FALSE;
for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++)
- dpp->weight_A = dpp->weight_B = 0;
+ dpp->weight_A = dpp->weight_B = 0;
while (--dpp >= wps->decorr_passes && termcnt--) {
- dpp->weight_A = restore_weight (*byteptr++);
+ dpp->weight_A = restore_weight (*byteptr++);
- if (!(wps->wphdr.flags & MONO_FLAG))
- dpp->weight_B = restore_weight (*byteptr++);
+ if (!(wps->wphdr.flags & MONO_FLAG))
+ dpp->weight_B = restore_weight (*byteptr++);
}
return TRUE;
@@ -196,49 +163,49 @@ int read_decorr_samples (WavpackStream *wps, WavpackMetadata *wpmd)
int tcount;
for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++) {
- CLEAR (dpp->samples_A);
- CLEAR (dpp->samples_B);
+ CLEAR (dpp->samples_A);
+ CLEAR (dpp->samples_B);
}
if (wps->wphdr.version == 0x402 && (wps->wphdr.flags & HYBRID_FLAG)) {
- byteptr += 2;
+ byteptr += 2;
- if (!(wps->wphdr.flags & MONO_FLAG))
- byteptr += 2;
+ if (!(wps->wphdr.flags & MONO_FLAG))
+ byteptr += 2;
}
while (dpp-- > wps->decorr_passes && byteptr < endptr)
- if (dpp->term > MAX_TERM) {
- dpp->samples_A [0] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8)));
- dpp->samples_A [1] = exp2s ((short)(byteptr [2] + (byteptr [3] << 8)));
- byteptr += 4;
-
- if (!(wps->wphdr.flags & MONO_FLAG)) {
- dpp->samples_B [0] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8)));
- dpp->samples_B [1] = exp2s ((short)(byteptr [2] + (byteptr [3] << 8)));
- byteptr += 4;
- }
- }
- else if (dpp->term < 0) {
- dpp->samples_A [0] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8)));
- dpp->samples_B [0] = exp2s ((short)(byteptr [2] + (byteptr [3] << 8)));
- byteptr += 4;
- }
- else {
- int m = 0, cnt = dpp->term;
-
- while (cnt--) {
- dpp->samples_A [m] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8)));
- byteptr += 2;
-
- if (!(wps->wphdr.flags & MONO_FLAG)) {
- dpp->samples_B [m] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8)));
- byteptr += 2;
- }
-
- m++;
- }
- }
+ if (dpp->term > MAX_TERM) {
+ dpp->samples_A [0] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8)));
+ dpp->samples_A [1] = exp2s ((short)(byteptr [2] + (byteptr [3] << 8)));
+ byteptr += 4;
+
+ if (!(wps->wphdr.flags & MONO_FLAG)) {
+ dpp->samples_B [0] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8)));
+ dpp->samples_B [1] = exp2s ((short)(byteptr [2] + (byteptr [3] << 8)));
+ byteptr += 4;
+ }
+ }
+ else if (dpp->term < 0) {
+ dpp->samples_A [0] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8)));
+ dpp->samples_B [0] = exp2s ((short)(byteptr [2] + (byteptr [3] << 8)));
+ byteptr += 4;
+ }
+ else {
+ int m = 0, cnt = dpp->term;
+
+ while (cnt--) {
+ dpp->samples_A [m] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8)));
+ byteptr += 2;
+
+ if (!(wps->wphdr.flags & MONO_FLAG)) {
+ dpp->samples_B [m] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8)));
+ byteptr += 2;
+ }
+
+ m++;
+ }
+ }
return byteptr == endptr;
}
@@ -253,7 +220,7 @@ int read_int32_info (WavpackStream *wps, WavpackMetadata *wpmd)
char *byteptr = wpmd->data;
if (bytecnt != 4)
- return FALSE;
+ return FALSE;
wps->int32_sent_bits = *byteptr++;
wps->int32_zeros = *byteptr++;
@@ -273,13 +240,13 @@ int read_channel_info (WavpackContext *wpc, WavpackMetadata *wpmd)
ulong mask = 0;
if (!bytecnt || bytecnt > 5)
- return FALSE;
+ return FALSE;
wpc->config.num_channels = *byteptr++;
while (--bytecnt) {
- mask |= (ulong) *byteptr++ << shift;
- shift += 8;
+ mask |= (ulong) *byteptr++ << shift;
+ shift += 8;
}
wpc->config.channel_mask = mask;
@@ -294,10 +261,10 @@ int read_config_info (WavpackContext *wpc, WavpackMetadata *wpmd)
uchar *byteptr = wpmd->data;
if (bytecnt >= 3) {
- wpc->config.flags &= 0xff;
- wpc->config.flags |= (long) *byteptr++ << 8;
- wpc->config.flags |= (long) *byteptr++ << 16;
- wpc->config.flags |= (long) *byteptr << 24;
+ wpc->config.flags &= 0xff;
+ wpc->config.flags |= (long) *byteptr++ << 8;
+ wpc->config.flags |= (long) *byteptr++ << 16;
+ wpc->config.flags |= (long) *byteptr << 24;
}
return TRUE;
@@ -339,88 +306,88 @@ long unpack_samples (WavpackContext *wpc, long *buffer, ulong sample_count)
int tcount;
if (wps->sample_index + sample_count > wps->wphdr.block_index + wps->wphdr.block_samples)
- sample_count = wps->wphdr.block_index + wps->wphdr.block_samples - wps->sample_index;
+ sample_count = wps->wphdr.block_index + wps->wphdr.block_samples - wps->sample_index;
if (wps->mute_error) {
- memset (buffer, 0, sample_count * (flags & MONO_FLAG ? 4 : 8));
- wps->sample_index += sample_count;
- return sample_count;
+ memset (buffer, 0, sample_count * (flags & MONO_FLAG ? 4 : 8));
+ wps->sample_index += sample_count;
+ return sample_count;
}
if (flags & HYBRID_FLAG)
- mute_limit *= 2;
+ mute_limit *= 2;
///////////////////// handle version 4 mono data /////////////////////////
if (flags & MONO_FLAG) {
- eptr = buffer + sample_count;
- i = get_words (wps, 1, sample_count, buffer);
+ eptr = buffer + sample_count;
+ i = get_words (buffer, sample_count, flags, &wps->w, &wps->wvbits);
- for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++)
- decorr_mono_pass (dpp, buffer, sample_count);
+ for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++)
+ decorr_mono_pass (dpp, buffer, sample_count);
- for (bptr = buffer; bptr < eptr; ++bptr) {
- if (labs (bptr [0]) > mute_limit) {
- i = bptr - buffer;
- break;
- }
+ for (bptr = buffer; bptr < eptr; ++bptr) {
+ if (labs (bptr [0]) > mute_limit) {
+ i = bptr - buffer;
+ break;
+ }
- crc = crc * 3 + bptr [0];
- }
+ crc = crc * 3 + bptr [0];
+ }
}
//////////////////// handle version 4 stereo data ////////////////////////
else {
- eptr = buffer + (sample_count * 2);
- i = get_words (wps, 2, sample_count, buffer);
-
- if (sample_count < 16)
- for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++)
- decorr_stereo_pass (dpp, buffer, sample_count);
- else
- for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++) {
- decorr_stereo_pass (dpp, buffer, 8);
+ eptr = buffer + (sample_count * 2);
+ i = get_words (buffer, sample_count, flags, &wps->w, &wps->wvbits);
+
+ if (sample_count < 16)
+ for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++)
+ decorr_stereo_pass (dpp, buffer, sample_count);
+ else
+ for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++) {
+ decorr_stereo_pass (dpp, buffer, 8);
#if CONFIG_CPU==MCF5249 && !defined(SIMULATOR)
- decorr_stereo_pass_cont_mcf5249 (dpp, buffer + 16, sample_count - 8);
+ decorr_stereo_pass_cont_mcf5249 (dpp, buffer + 16, sample_count - 8);
#else
- decorr_stereo_pass_cont (dpp, buffer + 16, sample_count - 8);
+ decorr_stereo_pass_cont (dpp, buffer + 16, sample_count - 8);
#endif
- }
-
- if (flags & JOINT_STEREO)
- for (bptr = buffer; bptr < eptr; bptr += 2) {
- bptr [0] += (bptr [1] -= (bptr [0] >> 1));
-
- if (labs (bptr [0]) > mute_limit || labs (bptr [1]) > mute_limit) {
- i = (bptr - buffer) / 2;
- break;
- }
-
- crc = (crc * 3 + bptr [0]) * 3 + bptr [1];
- }
- else
- for (bptr = buffer; bptr < eptr; bptr += 2) {
- if (labs (bptr [0]) > mute_limit || labs (bptr [1]) > mute_limit) {
- i = (bptr - buffer) / 2;
- break;
- }
-
- crc = (crc * 3 + bptr [0]) * 3 + bptr [1];
- }
+ }
+
+ if (flags & JOINT_STEREO)
+ for (bptr = buffer; bptr < eptr; bptr += 2) {
+ bptr [0] += (bptr [1] -= (bptr [0] >> 1));
+
+ if (labs (bptr [0]) > mute_limit || labs (bptr [1]) > mute_limit) {
+ i = (bptr - buffer) / 2;
+ break;
+ }
+
+ crc = (crc * 3 + bptr [0]) * 3 + bptr [1];
+ }
+ else
+ for (bptr = buffer; bptr < eptr; bptr += 2) {
+ if (labs (bptr [0]) > mute_limit || labs (bptr [1]) > mute_limit) {
+ i = (bptr - buffer) / 2;
+ break;
+ }
+
+ crc = (crc * 3 + bptr [0]) * 3 + bptr [1];
+ }
}
if (i != sample_count) {
- memset (buffer, 0, sample_count * (flags & MONO_FLAG ? 4 : 8));
- wps->mute_error = TRUE;
- i = sample_count;
+ memset (buffer, 0, sample_count * (flags & MONO_FLAG ? 4 : 8));
+ wps->mute_error = TRUE;
+ i = sample_count;
}
fixup_samples (wps, buffer, i);
if (flags & FLOAT_DATA)
- float_normalize (buffer, (flags & MONO_FLAG) ? i : i * 2,
- 127 - wps->float_norm_exp + wpc->norm_offset);
+ float_normalize (buffer, (flags & MONO_FLAG) ? i : i * 2,
+ 127 - wps->float_norm_exp + wpc->norm_offset);
wps->sample_index += i;
wps->crc = crc;
@@ -436,107 +403,107 @@ static void decorr_stereo_pass (struct decorr_pass *dpp, long *buffer, long samp
switch (dpp->term) {
- case 17:
- for (bptr = buffer; bptr < eptr; bptr += 2) {
- sam_A = 2 * dpp->samples_A [0] - dpp->samples_A [1];
- dpp->samples_A [1] = dpp->samples_A [0];
- dpp->samples_A [0] = apply_weight (weight_A, sam_A) + bptr [0];
- update_weight (weight_A, delta, sam_A, bptr [0]);
- bptr [0] = dpp->samples_A [0];
-
- sam_A = 2 * dpp->samples_B [0] - dpp->samples_B [1];
- dpp->samples_B [1] = dpp->samples_B [0];
- dpp->samples_B [0] = apply_weight (weight_B, sam_A) + bptr [1];
- update_weight (weight_B, delta, sam_A, bptr [1]);
- bptr [1] = dpp->samples_B [0];
- }
-
- break;
-
- case 18:
- for (bptr = buffer; bptr < eptr; bptr += 2) {
- sam_A = (3 * dpp->samples_A [0] - dpp->samples_A [1]) >> 1;
- dpp->samples_A [1] = dpp->samples_A [0];
- dpp->samples_A [0] = apply_weight (weight_A, sam_A) + bptr [0];
- update_weight (weight_A, delta, sam_A, bptr [0]);
- bptr [0] = dpp->samples_A [0];
-
- sam_A = (3 * dpp->samples_B [0] - dpp->samples_B [1]) >> 1;
- dpp->samples_B [1] = dpp->samples_B [0];
- dpp->samples_B [0] = apply_weight (weight_B, sam_A) + bptr [1];
- update_weight (weight_B, delta, sam_A, bptr [1]);
- bptr [1] = dpp->samples_B [0];
- }
-
- break;
-
- default:
- for (m = 0, k = dpp->term & (MAX_TERM - 1), bptr = buffer; bptr < eptr; bptr += 2) {
- sam_A = dpp->samples_A [m];
- dpp->samples_A [k] = apply_weight (weight_A, sam_A) + bptr [0];
- update_weight (weight_A, delta, sam_A, bptr [0]);
- bptr [0] = dpp->samples_A [k];
-
- sam_A = dpp->samples_B [m];
- dpp->samples_B [k] = apply_weight (weight_B, sam_A) + bptr [1];
- update_weight (weight_B, delta, sam_A, bptr [1]);
- bptr [1] = dpp->samples_B [k];
-
- m = (m + 1) & (MAX_TERM - 1);
- k = (k + 1) & (MAX_TERM - 1);
- }
-
- if (m) {
- long temp_samples [MAX_TERM];
-
- memcpy (temp_samples, dpp->samples_A, sizeof (dpp->samples_A));
-
- for (k = 0; k < MAX_TERM; k++, m++)
- dpp->samples_A [k] = temp_samples [m & (MAX_TERM - 1)];
-
- memcpy (temp_samples, dpp->samples_B, sizeof (dpp->samples_B));
-
- for (k = 0; k < MAX_TERM; k++, m++)
- dpp->samples_B [k] = temp_samples [m & (MAX_TERM - 1)];
- }
-
- break;
-
- case -1:
- for (bptr = buffer; bptr < eptr; bptr += 2) {
- sam_A = bptr [0] + apply_weight (weight_A, dpp->samples_A [0]);
- update_weight_clip (weight_A, delta, dpp->samples_A [0], bptr [0]);
- bptr [0] = sam_A;
- dpp->samples_A [0] = bptr [1] + apply_weight (weight_B, sam_A);
- update_weight_clip (weight_B, delta, sam_A, bptr [1]);
- bptr [1] = dpp->samples_A [0];
- }
-
- break;
-
- case -2:
- for (bptr = buffer; bptr < eptr; bptr += 2) {
- sam_B = bptr [1] + apply_weight (weight_B, dpp->samples_B [0]);
- update_weight_clip (weight_B, delta, dpp->samples_B [0], bptr [1]);
- bptr [1] = sam_B;
- dpp->samples_B [0] = bptr [0] + apply_weight (weight_A, sam_B);
- update_weight_clip (weight_A, delta, sam_B, bptr [0]);
- bptr [0] = dpp->samples_B [0];
- }
-
- break;
-
- case -3:
- for (bptr = buffer; bptr < eptr; bptr += 2) {
- sam_A = bptr [0] + apply_weight (weight_A, dpp->samples_A [0]);
- update_weight_clip (weight_A, delta, dpp->samples_A [0], bptr [0]);
- sam_B = bptr [1] + apply_weight (weight_B, dpp->samples_B [0]);
- update_weight_clip (weight_B, delta, dpp->samples_B [0], bptr [1]);
- bptr [0] = dpp->samples_B [0] = sam_A;
- bptr [1] = dpp->samples_A [0] = sam_B;
- }
-
- break;
+ case 17:
+ for (bptr = buffer; bptr < eptr; bptr += 2) {
+ sam_A = 2 * dpp->samples_A [0] - dpp->samples_A [1];
+ dpp->samples_A [1] = dpp->samples_A [0];
+ dpp->samples_A [0] = apply_weight (weight_A, sam_A) + bptr [0];
+ update_weight (weight_A, delta, sam_A, bptr [0]);
+ bptr [0] = dpp->samples_A [0];
+
+ sam_A = 2 * dpp->samples_B [0] - dpp->samples_B [1];
+ dpp->samples_B [1] = dpp->samples_B [0];
+ dpp->samples_B [0] = apply_weight (weight_B, sam_A) + bptr [1];
+ update_weight (weight_B, delta, sam_A, bptr [1]);
+ bptr [1] = dpp->samples_B [0];
+ }
+
+ break;
+
+ case 18:
+ for (bptr = buffer; bptr < eptr; bptr += 2) {
+ sam_A = (3 * dpp->samples_A [0] - dpp->samples_A [1]) >> 1;
+ dpp->samples_A [1] = dpp->samples_A [0];
+ dpp->samples_A [0] = apply_weight (weight_A, sam_A) + bptr [0];
+ update_weight (weight_A, delta, sam_A, bptr [0]);
+ bptr [0] = dpp->samples_A [0];
+
+ sam_A = (3 * dpp->samples_B [0] - dpp->samples_B [1]) >> 1;
+ dpp->samples_B [1] = dpp->samples_B [0];
+ dpp->samples_B [0] = apply_weight (weight_B, sam_A) + bptr [1];
+ update_weight (weight_B, delta, sam_A, bptr [1]);
+ bptr [1] = dpp->samples_B [0];
+ }
+
+ break;
+
+ default:
+ for (m = 0, k = dpp->term & (MAX_TERM - 1), bptr = buffer; bptr < eptr; bptr += 2) {
+ sam_A = dpp->samples_A [m];
+ dpp->samples_A [k] = apply_weight (weight_A, sam_A) + bptr [0];
+ update_weight (weight_A, delta, sam_A, bptr [0]);
+ bptr [0] = dpp->samples_A [k];
+
+ sam_A = dpp->samples_B [m];
+ dpp->samples_B [k] = apply_weight (weight_B, sam_A) + bptr [1];
+ update_weight (weight_B, delta, sam_A, bptr [1]);
+ bptr [1] = dpp->samples_B [k];
+
+ m = (m + 1) & (MAX_TERM - 1);
+ k = (k + 1) & (MAX_TERM - 1);
+ }
+
+ if (m) {
+ long temp_samples [MAX_TERM];
+
+ memcpy (temp_samples, dpp->samples_A, sizeof (dpp->samples_A));
+
+ for (k = 0; k < MAX_TERM; k++, m++)
+ dpp->samples_A [k] = temp_samples [m & (MAX_TERM - 1)];
+
+ memcpy (temp_samples, dpp->samples_B, sizeof (dpp->samples_B));
+
+ for (k = 0; k < MAX_TERM; k++, m++)
+ dpp->samples_B [k] = temp_samples [m & (MAX_TERM - 1)];
+ }
+
+ break;
+
+ case -1:
+ for (bptr = buffer; bptr < eptr; bptr += 2) {
+ sam_A = bptr [0] + apply_weight (weight_A, dpp->samples_A [0]);
+ update_weight_clip (weight_A, delta, dpp->samples_A [0], bptr [0]);
+ bptr [0] = sam_A;
+ dpp->samples_A [0] = bptr [1] + apply_weight (weight_B, sam_A);
+ update_weight_clip (weight_B, delta, sam_A, bptr [1]);
+ bptr [1] = dpp->samples_A [0];
+ }
+
+ break;
+
+ case -2:
+ for (bptr = buffer; bptr < eptr; bptr += 2) {
+ sam_B = bptr [1] + apply_weight (weight_B, dpp->samples_B [0]);
+ update_weight_clip (weight_B, delta, dpp->samples_B [0], bptr [1]);
+ bptr [1] = sam_B;
+ dpp->samples_B [0] = bptr [0] + apply_weight (weight_A, sam_B);
+ update_weight_clip (weight_A, delta, sam_B, bptr [0]);
+ bptr [0] = dpp->samples_B [0];
+ }
+
+ break;
+
+ case -3:
+ for (bptr = buffer; bptr < eptr; bptr += 2) {
+ sam_A = bptr [0] + apply_weight (weight_A, dpp->samples_A [0]);
+ update_weight_clip (weight_A, delta, dpp->samples_A [0], bptr [0]);
+ sam_B = bptr [1] + apply_weight (weight_B, dpp->samples_B [0]);
+ update_weight_clip (weight_B, delta, dpp->samples_B [0], bptr [1]);
+ bptr [0] = dpp->samples_B [0] = sam_A;
+ bptr [1] = dpp->samples_A [0] = sam_B;
+ }
+
+ break;
}
dpp->weight_A = weight_A;
@@ -553,89 +520,89 @@ static void decorr_stereo_pass_cont (struct decorr_pass *dpp, long *buffer, long
switch (dpp->term) {
- case 17:
- for (bptr = buffer; bptr < eptr; bptr += 2) {
- sam_A = 2 * bptr [-2] - bptr [-4];
- bptr [0] = apply_weight (weight_A, sam_A) + (sam_B = bptr [0]);
- update_weight (weight_A, delta, sam_A, sam_B);
-
- sam_A = 2 * bptr [-1] - bptr [-3];
- bptr [1] = apply_weight (weight_B, sam_A) + (sam_B = bptr [1]);
- update_weight (weight_B, delta, sam_A, sam_B);
- }
-
- dpp->samples_B [0] = bptr [-1];
- dpp->samples_A [0] = bptr [-2];
- dpp->samples_B [1] = bptr [-3];
- dpp->samples_A [1] = bptr [-4];
- break;
-
- case 18:
- for (bptr = buffer; bptr < eptr; bptr += 2) {
- sam_A = (3 * bptr [-2] - bptr [-4]) >> 1;
- bptr [0] = apply_weight (weight_A, sam_A) + (sam_B = bptr [0]);
- update_weight (weight_A, delta, sam_A, sam_B);
-
- sam_A = (3 * bptr [-1] - bptr [-3]) >> 1;
- bptr [1] = apply_weight (weight_B, sam_A) + (sam_B = bptr [1]);
- update_weight (weight_B, delta, sam_A, sam_B);
- }
-
- dpp->samples_B [0] = bptr [-1];
- dpp->samples_A [0] = bptr [-2];
- dpp->samples_B [1] = bptr [-3];
- dpp->samples_A [1] = bptr [-4];
- break;
-
- default:
- for (bptr = buffer, tptr = buffer - (dpp->term * 2); bptr < eptr; bptr += 2, tptr += 2) {
- bptr [0] = apply_weight (weight_A, tptr [0]) + (sam_A = bptr [0]);
- update_weight (weight_A, delta, tptr [0], sam_A);
-
- bptr [1] = apply_weight (weight_B, tptr [1]) + (sam_A = bptr [1]);
- update_weight (weight_B, delta, tptr [1], sam_A);
- }
-
- for (k = dpp->term - 1, i = 8; i--; k--) {
- dpp->samples_B [k & (MAX_TERM - 1)] = *--bptr;
- dpp->samples_A [k & (MAX_TERM - 1)] = *--bptr;
- }
-
- break;
-
- case -1:
- for (bptr = buffer; bptr < eptr; bptr += 2) {
- bptr [0] = apply_weight (weight_A, bptr [-1]) + (sam_A = bptr [0]);
- update_weight_clip (weight_A, delta, bptr [-1], sam_A);
- bptr [1] = apply_weight (weight_B, bptr [0]) + (sam_A = bptr [1]);
- update_weight_clip (weight_B, delta, bptr [0], sam_A);
- }
-
- dpp->samples_A [0] = bptr [-1];
- break;
-
- case -2:
- for (bptr = buffer; bptr < eptr; bptr += 2) {
- bptr [1] = apply_weight (weight_B, bptr [-2]) + (sam_A = bptr [1]);
- update_weight_clip (weight_B, delta, bptr [-2], sam_A);
- bptr [0] = apply_weight (weight_A, bptr [1]) + (sam_A = bptr [0]);
- update_weight_clip (weight_A, delta, bptr [1], sam_A);
- }
-
- dpp->samples_B [0] = bptr [-2];
- break;
-
- case -3:
- for (bptr = buffer; bptr < eptr; bptr += 2) {
- bptr [0] = apply_weight (weight_A, bptr [-1]) + (sam_A = bptr [0]);
- update_weight_clip (weight_A, delta, bptr [-1], sam_A);
- bptr [1] = apply_weight (weight_B, bptr [-2]) + (sam_A = bptr [1]);
- update_weight_clip (weight_B, delta, bptr [-2], sam_A);
- }
-
- dpp->samples_A [0] = bptr [-1];
- dpp->samples_B [0] = bptr [-2];
- break;
+ case 17:
+ for (bptr = buffer; bptr < eptr; bptr += 2) {
+ sam_A = 2 * bptr [-2] - bptr [-4];
+ bptr [0] = apply_weight (weight_A, sam_A) + (sam_B = bptr [0]);
+ update_weight (weight_A, delta, sam_A, sam_B);
+
+ sam_A = 2 * bptr [-1] - bptr [-3];
+ bptr [1] = apply_weight (weight_B, sam_A) + (sam_B = bptr [1]);
+ update_weight (weight_B, delta, sam_A, sam_B);
+ }
+
+ dpp->samples_B [0] = bptr [-1];
+ dpp->samples_A [0] = bptr [-2];
+ dpp->samples_B [1] = bptr [-3];
+ dpp->samples_A [1] = bptr [-4];
+ break;
+
+ case 18:
+ for (bptr = buffer; bptr < eptr; bptr += 2) {
+ sam_A = (3 * bptr [-2] - bptr [-4]) >> 1;
+ bptr [0] = apply_weight (weight_A, sam_A) + (sam_B = bptr [0]);
+ update_weight (weight_A, delta, sam_A, sam_B);
+
+ sam_A = (3 * bptr [-1] - bptr [-3]) >> 1;
+ bptr [1] = apply_weight (weight_B, sam_A) + (sam_B = bptr [1]);
+ update_weight (weight_B, delta, sam_A, sam_B);
+ }
+
+ dpp->samples_B [0] = bptr [-1];
+ dpp->samples_A [0] = bptr [-2];
+ dpp->samples_B [1] = bptr [-3];
+ dpp->samples_A [1] = bptr [-4];
+ break;
+
+ default:
+ for (bptr = buffer, tptr = buffer - (dpp->term * 2); bptr < eptr; bptr += 2, tptr += 2) {
+ bptr [0] = apply_weight (weight_A, tptr [0]) + (sam_A = bptr [0]);
+ update_weight (weight_A, delta, tptr [0], sam_A);
+
+ bptr [1] = apply_weight (weight_B, tptr [1]) + (sam_A = bptr [1]);
+ update_weight (weight_B, delta, tptr [1], sam_A);
+ }
+
+ for (k = dpp->term - 1, i = 8; i--; k--) {
+ dpp->samples_B [k & (MAX_TERM - 1)] = *--bptr;
+ dpp->samples_A [k & (MAX_TERM - 1)] = *--bptr;
+ }
+
+ break;
+
+ case -1:
+ for (bptr = buffer; bptr < eptr; bptr += 2) {
+ bptr [0] = apply_weight (weight_A, bptr [-1]) + (sam_A = bptr [0]);
+ update_weight_clip (weight_A, delta, bptr [-1], sam_A);
+ bptr [1] = apply_weight (weight_B, bptr [0]) + (sam_A = bptr [1]);
+ update_weight_clip (weight_B, delta, bptr [0], sam_A);
+ }
+
+ dpp->samples_A [0] = bptr [-1];
+ break;
+
+ case -2:
+ for (bptr = buffer; bptr < eptr; bptr += 2) {
+ bptr [1] = apply_weight (weight_B, bptr [-2]) + (sam_A = bptr [1]);
+ update_weight_clip (weight_B, delta, bptr [-2], sam_A);
+ bptr [0] = apply_weight (weight_A, bptr [1]) + (sam_A = bptr [0]);
+ update_weight_clip (weight_A, delta, bptr [1], sam_A);
+ }
+
+ dpp->samples_B [0] = bptr [-2];
+ break;
+
+ case -3:
+ for (bptr = buffer; bptr < eptr; bptr += 2) {
+ bptr [0] = apply_weight (weight_A, bptr [-1]) + (sam_A = bptr [0]);
+ update_weight_clip (weight_A, delta, bptr [-1], sam_A);
+ bptr [1] = apply_weight (weight_B, bptr [-2]) + (sam_A = bptr [1]);
+ update_weight_clip (weight_B, delta, bptr [-2], sam_A);
+ }
+
+ dpp->samples_A [0] = bptr [-1];
+ dpp->samples_B [0] = bptr [-2];
+ break;
}
dpp->weight_A = weight_A;
@@ -652,48 +619,48 @@ static void decorr_mono_pass (struct decorr_pass *dpp, long *buffer, long sample
switch (dpp->term) {
- case 17:
- for (bptr = buffer; bptr < eptr; bptr++) {
- sam_A = 2 * dpp->samples_A [0] - dpp->samples_A [1];
- dpp->samples_A [1] = dpp->samples_A [0];
- dpp->samples_A [0] = apply_weight (weight_A, sam_A) + bptr [0];
- update_weight (weight_A, delta, sam_A, bptr [0]);
- bptr [0] = dpp->samples_A [0];
- }
-
- break;
-
- case 18:
- for (bptr = buffer; bptr < eptr; bptr++) {
- sam_A = (3 * dpp->samples_A [0] - dpp->samples_A [1]) >> 1;
- dpp->samples_A [1] = dpp->samples_A [0];
- dpp->samples_A [0] = apply_weight (weight_A, sam_A) + bptr [0];
- update_weight (weight_A, delta, sam_A, bptr [0]);
- bptr [0] = dpp->samples_A [0];
- }
-
- break;
-
- default:
- for (m = 0, k = dpp->term & (MAX_TERM - 1), bptr = buffer; bptr < eptr; bptr++) {
- sam_A = dpp->samples_A [m];
- dpp->samples_A [k] = apply_weight (weight_A, sam_A) + bptr [0];
- update_weight (weight_A, delta, sam_A, bptr [0]);
- bptr [0] = dpp->samples_A [k];
- m = (m + 1) & (MAX_TERM - 1);
- k = (k + 1) & (MAX_TERM - 1);
- }
-
- if (m) {
- long temp_samples [MAX_TERM];
-
- memcpy (temp_samples, dpp->samples_A, sizeof (dpp->samples_A));
-
- for (k = 0; k < MAX_TERM; k++, m++)
- dpp->samples_A [k] = temp_samples [m & (MAX_TERM - 1)];
- }
-
- break;
+ case 17:
+ for (bptr = buffer; bptr < eptr; bptr++) {
+ sam_A = 2 * dpp->samples_A [0] - dpp->samples_A [1];
+ dpp->samples_A [1] = dpp->samples_A [0];
+ dpp->samples_A [0] = apply_weight (weight_A, sam_A) + bptr [0];
+ update_weight (weight_A, delta, sam_A, bptr [0]);
+ bptr [0] = dpp->samples_A [0];
+ }
+
+ break;
+
+ case 18:
+ for (bptr = buffer; bptr < eptr; bptr++) {
+ sam_A = (3 * dpp->samples_A [0] - dpp->samples_A [1]) >> 1;
+ dpp->samples_A [1] = dpp->samples_A [0];
+ dpp->samples_A [0] = apply_weight (weight_A, sam_A) + bptr [0];
+ update_weight (weight_A, delta, sam_A, bptr [0]);
+ bptr [0] = dpp->samples_A [0];
+ }
+
+ break;
+
+ default:
+ for (m = 0, k = dpp->term & (MAX_TERM - 1), bptr = buffer; bptr < eptr; bptr++) {
+ sam_A = dpp->samples_A [m];
+ dpp->samples_A [k] = apply_weight (weight_A, sam_A) + bptr [0];
+ update_weight (weight_A, delta, sam_A, bptr [0]);
+ bptr [0] = dpp->samples_A [k];
+ m = (m + 1) & (MAX_TERM - 1);
+ k = (k + 1) & (MAX_TERM - 1);
+ }
+
+ if (m) {
+ long temp_samples [MAX_TERM];
+
+ memcpy (temp_samples, dpp->samples_A, sizeof (dpp->samples_A));
+
+ for (k = 0; k < MAX_TERM; k++, m++)
+ dpp->samples_A [k] = temp_samples [m & (MAX_TERM - 1)];
+ }
+
+ break;
}
dpp->weight_A = weight_A;
@@ -714,76 +681,76 @@ static void fixup_samples (WavpackStream *wps, long *buffer, ulong sample_count)
int shift = (flags & SHIFT_MASK) >> SHIFT_LSB;
if (flags & FLOAT_DATA) {
- float_values (wps, buffer, (flags & MONO_FLAG) ? sample_count : sample_count * 2);
- return;
+ float_values (wps, buffer, (flags & MONO_FLAG) ? sample_count : sample_count * 2);
+ return;
}
if (flags & INT32_DATA) {
- ulong count = (flags & MONO_FLAG) ? sample_count : sample_count * 2;
- int sent_bits = wps->int32_sent_bits, zeros = wps->int32_zeros;
- int ones = wps->int32_ones, dups = wps->int32_dups;
-// ulong mask = (1 << sent_bits) - 1;
- long *dptr = buffer;
-
- if (!(flags & HYBRID_FLAG) && !sent_bits && (zeros + ones + dups))
- while (count--) {
- if (zeros)
- *dptr <<= zeros;
- else if (ones)
- *dptr = ((*dptr + 1) << ones) - 1;
- else if (dups)
- *dptr = ((*dptr + (*dptr & 1)) << dups) - (*dptr & 1);
-
- dptr++;
- }
- else
- shift += zeros + sent_bits + ones + dups;
+ ulong count = (flags & MONO_FLAG) ? sample_count : sample_count * 2;
+ int sent_bits = wps->int32_sent_bits, zeros = wps->int32_zeros;
+ int ones = wps->int32_ones, dups = wps->int32_dups;
+// ulong mask = (1 << sent_bits) - 1;
+ long *dptr = buffer;
+
+ if (!(flags & HYBRID_FLAG) && !sent_bits && (zeros + ones + dups))
+ while (count--) {
+ if (zeros)
+ *dptr <<= zeros;
+ else if (ones)
+ *dptr = ((*dptr + 1) << ones) - 1;
+ else if (dups)
+ *dptr = ((*dptr + (*dptr & 1)) << dups) - (*dptr & 1);
+
+ dptr++;
+ }
+ else
+ shift += zeros + sent_bits + ones + dups;
}
if (flags & HYBRID_FLAG) {
- long min_value, max_value, min_shifted, max_shifted;
-
- switch (flags & BYTES_STORED) {
- case 0:
- min_shifted = (min_value = -128 >> shift) << shift;
- max_shifted = (max_value = 127 >> shift) << shift;
- break;
-
- case 1:
- min_shifted = (min_value = -32768 >> shift) << shift;
- max_shifted = (max_value = 32767 >> shift) << shift;
- break;
-
- case 2:
- min_shifted = (min_value = -8388608 >> shift) << shift;
- max_shifted = (max_value = 8388607 >> shift) << shift;
- break;
-
- case 3:
- default:
+ long min_value, max_value, min_shifted, max_shifted;
+
+ switch (flags & BYTES_STORED) {
+ case 0:
+ min_shifted = (min_value = -128 >> shift) << shift;
+ max_shifted = (max_value = 127 >> shift) << shift;
+ break;
+
+ case 1:
+ min_shifted = (min_value = -32768 >> shift) << shift;
+ max_shifted = (max_value = 32767 >> shift) << shift;
+ break;
+
+ case 2:
+ min_shifted = (min_value = -8388608 >> shift) << shift;
+ max_shifted = (max_value = 8388607 >> shift) << shift;
+ break;
+
+ case 3:
+ default:
min_shifted = (min_value = (long) 0x80000000 >> shift) << shift;
max_shifted = (max_value = (long) 0x7FFFFFFF >> shift) << shift;
- break;
- }
-
- if (!(flags & MONO_FLAG))
- sample_count *= 2;
-
- while (sample_count--) {
- if (*buffer < min_value)
- *buffer++ = min_shifted;
- else if (*buffer > max_value)
- *buffer++ = max_shifted;
- else
- *buffer++ <<= shift;
- }
+ break;
+ }
+
+ if (!(flags & MONO_FLAG))
+ sample_count *= 2;
+
+ while (sample_count--) {
+ if (*buffer < min_value)
+ *buffer++ = min_shifted;
+ else if (*buffer > max_value)
+ *buffer++ = max_shifted;
+ else
+ *buffer++ <<= shift;
+ }
}
else if (shift) {
- if (!(flags & MONO_FLAG))
- sample_count *= 2;
+ if (!(flags & MONO_FLAG))
+ sample_count *= 2;
- while (sample_count--)
- *buffer++ <<= shift;
+ while (sample_count--)
+ *buffer++ <<= shift;
}
}
@@ -800,7 +767,7 @@ int check_crc_error (WavpackContext *wpc)
int result = 0;
if (wps->crc != wps->wphdr.crc)
- ++result;
+ ++result;
return result;
}
diff --git a/apps/codecs/libwavpack/wavpack.h b/apps/codecs/libwavpack/wavpack.h
index 3aee471..12212bb 100644
--- a/apps/codecs/libwavpack/wavpack.h
+++ b/apps/codecs/libwavpack/wavpack.h
@@ -14,11 +14,10 @@
// This header file contains all the definitions required by WavPack.
-// not sure about them.. testing will bring more light into it..
-typedef unsigned char uchar;
-typedef unsigned short ushort;
-typedef unsigned long ulong;
-typedef unsigned int uint;
+typedef unsigned char uchar;
+typedef unsigned short ushort;
+typedef unsigned long ulong;
+typedef unsigned int uint;
// This structure is used to access the individual fields of 32-bit ieee
// floating point numbers. This will not be compatible with compilers that
@@ -54,70 +53,71 @@ typedef struct {
// 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 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 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 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 SHIFT_LSB 13
+#define SHIFT_MASK (0x1fL << SHIFT_LSB)
-#define MAG_LSB 18
-#define MAG_MASK (0x1fL << MAG_LSB)
+#define MAG_LSB 18
+#define MAG_MASK (0x1fL << MAG_LSB)
-#define SRATE_LSB 23
-#define SRATE_MASK (0xfL << SRATE_LSB)
+#define SRATE_LSB 23
+#define SRATE_MASK (0xfL << SRATE_LSB)
-#define IGNORED_FLAGS 0x18000000 // reserved, but ignore if encountered
-#define NEW_SHAPING 0x20000000 // use IIR filter for negative shaping
-#define UNKNOWN_FLAGS 0xC0000000 // also reserved, but refuse decode if
- // encountered
+#define IGNORED_FLAGS 0x18000000 // reserved, but ignore if encountered
+#define NEW_SHAPING 0x20000000 // use IIR filter for negative shaping
+#define UNKNOWN_FLAGS 0xC0000000 // also reserved, but refuse decode if
+ // encountered
//////////////////////////// WavPack Metadata /////////////////////////////////
// This is an internal representation of metadata.
typedef struct {
+ uchar temp_data [64];
long byte_length;
void *data;
uchar id;
} WavpackMetadata;
-#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_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)
///////////////////////// WavPack Configuration ///////////////////////////////
@@ -127,39 +127,39 @@ typedef struct {
typedef struct {
int bits_per_sample, bytes_per_sample;
- int qmode, flags, xmode, num_channels, float_norm_exp;
- long block_samples, extra_flags, sample_rate, channel_mask;
+ int flags, num_channels, float_norm_exp;
+ ulong sample_rate, channel_mask;
} 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 (not yet)
-#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_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 (not yet)
+#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 %
//////////////////////////////// WavPack Stream ///////////////////////////////
@@ -191,35 +191,38 @@ struct entropy_data {
ulong median [3], slow_level, error_limit;
};
+struct words_data {
+ ulong bitrate_delta [2], bitrate_acc [2];
+ ulong pend_data, holding_one, zeros_acc;
+ int holding_zero, pend_count;
+ struct entropy_data c [2];
+};
+
typedef struct {
WavpackHeader wphdr;
Bitstream wvbits;
- struct {
- ulong bitrate_delta [2], bitrate_acc [2];
- ulong pend_data, holding_one, zeros_acc;
- int holding_zero, pend_count;
- struct entropy_data c [2];
- } w;
+ struct words_data w;
int num_terms, mute_error;
ulong sample_index, crc;
uchar int32_sent_bits, int32_zeros, int32_ones, int32_dups;
uchar float_flags, float_shift, float_max_exp, float_norm_exp;
-
+ uchar *blockbuff, *blockend;
+
struct decorr_pass decorr_passes [MAX_NTERMS];
} 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.)
+#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 ///////////////////////////////
@@ -231,6 +234,13 @@ typedef struct {
WavpackStream stream;
WavpackConfig config;
+ WavpackMetadata *metadata;
+ ulong metabytes;
+ int metacount;
+
+ uchar *wrapper_data;
+ int wrapper_bytes;
+
uchar read_buffer [1024];
char error_message [80];
@@ -247,32 +257,96 @@ typedef struct {
// bits.c
void bs_open_read (Bitstream *bs, uchar *buffer_start, uchar *buffer_end, read_stream file, ulong file_bytes);
+void bs_open_write (Bitstream *bs, uchar *buffer_start, uchar *buffer_end);
+ulong bs_close_write (Bitstream *bs);
#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)->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) \
+ ((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 |= (long)*((bs)->ptr) << (bs)->bc; \
- (bs)->bc += 8; \
+ if (++((bs)->ptr) == (bs)->end) (bs)->wrap (bs); \
+ (bs)->sr |= (long)*((bs)->ptr) << (bs)->bc; \
+ (bs)->bc += 8; \
} \
*(value) = (bs)->sr; \
(bs)->sr >>= (nbits); \
(bs)->bc -= (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 |= (long)(value) << (bs)->bc; \
+ if (((bs)->bc += (nbits)) >= 8) \
+ do { \
+ *((bs)->ptr) = (bs)->sr; \
+ (bs)->sr >>= 8; \
+ if (++((bs)->ptr) == (bs)->end) (bs)->wrap (bs); \
+ } while (((bs)->bc -= 8) >= 8); \
+}
+
void little_endian_to_native (void *data, char *format);
void native_to_little_endian (void *data, char *format);
+// these macros implement the weight application and update operations
+// that are at the heart of the decorrelation loops
+
+#if 0 // PERFCOND
+#define apply_weight_i(weight, sample) ((weight * sample + 512) >> 10)
+#else
+#define apply_weight_i(weight, sample) ((((weight * sample) >> 8) + 2) >> 2)
+#endif
+
+#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 0 // 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_clip(weight, delta, source, result) \
+ if (source && result && ((source ^ result) < 0 ? (weight -= delta) < -1024 : (weight += delta) > 1024)) \
+ weight = weight < 0 ? -1024 : 1024;
+
// unpack.c
int unpack_init (WavpackContext *wpc);
@@ -287,17 +361,31 @@ int read_config_info (WavpackContext *wpc, WavpackMetadata *wpmd);
long unpack_samples (WavpackContext *wpc, long *buffer, ulong sample_count);
int check_crc_error (WavpackContext *wpc);
+// pack.c
+
+void pack_init (WavpackContext *wpc);
+int pack_block (WavpackContext *wpc, long *buffer);
+
// metadata.c stuff
int read_metadata_buff (WavpackContext *wpc, WavpackMetadata *wpmd);
int process_metadata (WavpackContext *wpc, WavpackMetadata *wpmd);
+int copy_metadata (WavpackMetadata *wpmd, uchar *buffer_start, uchar *buffer_end);
+void free_metadata (WavpackMetadata *wpmd);
// words.c stuff
+void init_words (WavpackStream *wps);
int read_entropy_vars (WavpackStream *wps, WavpackMetadata *wpmd);
+void write_entropy_vars (WavpackStream *wps, WavpackMetadata *wpmd);
int read_hybrid_profile (WavpackStream *wps, WavpackMetadata *wpmd);
-long get_words (WavpackStream *wps, int nchans, int nsamples, long *buffer);
+long get_words (long *buffer, int nsamples, ulong flags,
+ struct words_data *w, Bitstream *bs);
+void send_word_lossless (WavpackStream *wps, long value, int chan);
+void flush_word (WavpackStream *wps);
+int log2s (long value);
long exp2s (int log);
+char store_weight (int weight);
int restore_weight (char weight);
#define WORD_EOF (1L << 31)
@@ -314,13 +402,13 @@ WavpackContext *WavpackOpenFileInput (read_stream infile, char *error);
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_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
ulong WavpackUnpackSamples (WavpackContext *wpc, long *buffer, ulong samples);
ulong WavpackGetNumSamples (WavpackContext *wpc);
@@ -332,3 +420,10 @@ int WavpackGetBitsPerSample (WavpackContext *wpc);
int WavpackGetBytesPerSample (WavpackContext *wpc);
int WavpackGetNumChannels (WavpackContext *wpc);
int WavpackGetReducedChannels (WavpackContext *wpc);
+WavpackContext *WavpackOpenFileOutput (void);
+void WavpackSetOutputBuffer (WavpackContext *wpc, uchar *begin, uchar *end);
+int WavpackSetConfiguration (WavpackContext *wpc, WavpackConfig *config, ulong total_samples);
+void WavpackAddWrapper (WavpackContext *wpc, void *data, ulong bcount);
+ulong WavpackPackSamples (WavpackContext *wpc, long *sample_buffer, ulong sample_count);
+
+
diff --git a/apps/codecs/libwavpack/words.c b/apps/codecs/libwavpack/words.c
index 8e2fc42..75d8a86 100644
--- a/apps/codecs/libwavpack/words.c
+++ b/apps/codecs/libwavpack/words.c
@@ -29,7 +29,7 @@
//////////////////////////////// local macros /////////////////////////////////
-#define LIMIT_ONES 16 // maximum consecutive 1s sent for "div" data
+#define LIMIT_ONES 16 // maximum consecutive 1s sent for "div" data
// these control the time constant "slow_level" which is used for hybrid mode
// that controls bitrate as a function of residual level (HYBRID_BITRATE).
@@ -37,9 +37,9 @@
#define SLO ((1 << (SLS - 1)))
// these control the time constant of the 3 median level breakpoints
-#define DIV0 128 // 5/7 of samples
-#define DIV1 64 // 10/49 of samples
-#define DIV2 32 // 20/343 of samples
+#define DIV0 128 // 5/7 of samples
+#define DIV1 64 // 10/49 of samples
+#define DIV2 32 // 20/343 of samples
// this macro retrieves the specified median breakpoint (without frac; min = 1)
#define GET_MED(med) (((c->median [med]) >> 4) + 1)
@@ -66,23 +66,45 @@
///////////////////////////// local table storage ////////////////////////////
+const ulong bitset [] = {
+ 1L << 0, 1L << 1, 1L << 2, 1L << 3,
+ 1L << 4, 1L << 5, 1L << 6, 1L << 7,
+ 1L << 8, 1L << 9, 1L << 10, 1L << 11,
+ 1L << 12, 1L << 13, 1L << 14, 1L << 15,
+ 1L << 16, 1L << 17, 1L << 18, 1L << 19,
+ 1L << 20, 1L << 21, 1L << 22, 1L << 23,
+ 1L << 24, 1L << 25, 1L << 26, 1L << 27,
+ 1L << 28, 1L << 29, 1L << 30, 1L << 31
+};
+
+const ulong bitmask [] = {
+ (1L << 0) - 1, (1L << 1) - 1, (1L << 2) - 1, (1L << 3) - 1,
+ (1L << 4) - 1, (1L << 5) - 1, (1L << 6) - 1, (1L << 7) - 1,
+ (1L << 8) - 1, (1L << 9) - 1, (1L << 10) - 1, (1L << 11) - 1,
+ (1L << 12) - 1, (1L << 13) - 1, (1L << 14) - 1, (1L << 15) - 1,
+ (1L << 16) - 1, (1L << 17) - 1, (1L << 18) - 1, (1L << 19) - 1,
+ (1L << 20) - 1, (1L << 21) - 1, (1L << 22) - 1, (1L << 23) - 1,
+ (1L << 24) - 1, (1L << 25) - 1, (1L << 26) - 1, (1L << 27) - 1,
+ (1L << 28) - 1, (1L << 29) - 1, (1L << 30) - 1, 0x7fffffff
+};
+
const char nbits_table [] = {
- 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, // 0 - 15
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, // 16 - 31
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, // 32 - 47
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, // 48 - 63
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 64 - 79
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 80 - 95
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 96 - 111
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 112 - 127
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, // 128 - 143
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, // 144 - 159
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, // 160 - 175
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, // 176 - 191
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, // 192 - 207
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, // 208 - 223
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, // 224 - 239
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 // 240 - 255
+ 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, // 0 - 15
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, // 16 - 31
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, // 32 - 47
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, // 48 - 63
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 64 - 79
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 80 - 95
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 96 - 111
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 112 - 127
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, // 128 - 143
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, // 144 - 159
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, // 160 - 175
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, // 176 - 191
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, // 192 - 207
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, // 208 - 223
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, // 224 - 239
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 // 240 - 255
};
static const uchar log2_table [] = {
@@ -136,6 +158,11 @@ static const char ones_count_table [] = {
///////////////////////////// executable code ////////////////////////////////
+void init_words (WavpackStream *wps)
+{
+ CLEAR (wps->w);
+}
+
static int mylog2 (unsigned long avalue);
// Read the median log2 values from the specifed metadata structure, convert
@@ -147,21 +174,55 @@ int read_entropy_vars (WavpackStream *wps, WavpackMetadata *wpmd)
uchar *byteptr = wpmd->data;
if (wpmd->byte_length != ((wps->wphdr.flags & MONO_FLAG) ? 6 : 12))
- return FALSE;
+ return FALSE;
wps->w.c [0].median [0] = exp2s (byteptr [0] + (byteptr [1] << 8));
wps->w.c [0].median [1] = exp2s (byteptr [2] + (byteptr [3] << 8));
wps->w.c [0].median [2] = exp2s (byteptr [4] + (byteptr [5] << 8));
if (!(wps->wphdr.flags & MONO_FLAG)) {
- wps->w.c [1].median [0] = exp2s (byteptr [6] + (byteptr [7] << 8));
- wps->w.c [1].median [1] = exp2s (byteptr [8] + (byteptr [9] << 8));
- wps->w.c [1].median [2] = exp2s (byteptr [10] + (byteptr [11] << 8));
+ wps->w.c [1].median [0] = exp2s (byteptr [6] + (byteptr [7] << 8));
+ wps->w.c [1].median [1] = exp2s (byteptr [8] + (byteptr [9] << 8));
+ wps->w.c [1].median [2] = exp2s (byteptr [10] + (byteptr [11] << 8));
}
return TRUE;
}
+// Allocates the correct space in the metadata structure and writes the
+// current median values to it. Values are converted from 32-bit unsigned
+// to our internal 16-bit mylog2 values, and read_entropy_vars () is called
+// to read the values back because we must compensate for the loss through
+// the log function.
+
+void write_entropy_vars (WavpackStream *wps, WavpackMetadata *wpmd)
+{
+ uchar *byteptr;
+ int temp;
+
+ byteptr = wpmd->data = wpmd->temp_data;
+ wpmd->id = ID_ENTROPY_VARS;
+
+ *byteptr++ = temp = mylog2 (wps->w.c [0].median [0]);
+ *byteptr++ = temp >> 8;
+ *byteptr++ = temp = mylog2 (wps->w.c [0].median [1]);
+ *byteptr++ = temp >> 8;
+ *byteptr++ = temp = mylog2 (wps->w.c [0].median [2]);
+ *byteptr++ = temp >> 8;
+
+ if (!(wps->wphdr.flags & MONO_FLAG)) {
+ *byteptr++ = temp = mylog2 (wps->w.c [1].median [0]);
+ *byteptr++ = temp >> 8;
+ *byteptr++ = temp = mylog2 (wps->w.c [1].median [1]);
+ *byteptr++ = temp >> 8;
+ *byteptr++ = temp = mylog2 (wps->w.c [1].median [2]);
+ *byteptr++ = temp >> 8;
+ }
+
+ wpmd->byte_length = byteptr - (uchar *) wpmd->data;
+ read_entropy_vars (wps, wpmd);
+}
+
// Read the hybrid related values from the specifed metadata structure, convert
// them back to their internal formats and store them. The extended profile
// stuff is not implemented yet, so return an error if we get more data than
@@ -173,37 +234,37 @@ int read_hybrid_profile (WavpackStream *wps, WavpackMetadata *wpmd)
uchar *endptr = byteptr + wpmd->byte_length;
if (wps->wphdr.flags & HYBRID_BITRATE) {
- wps->w.c [0].slow_level = exp2s (byteptr [0] + (byteptr [1] << 8));
- byteptr += 2;
+ wps->w.c [0].slow_level = exp2s (byteptr [0] + (byteptr [1] << 8));
+ byteptr += 2;
- if (!(wps->wphdr.flags & MONO_FLAG)) {
- wps->w.c [1].slow_level = exp2s (byteptr [0] + (byteptr [1] << 8));
- byteptr += 2;
- }
+ if (!(wps->wphdr.flags & MONO_FLAG)) {
+ wps->w.c [1].slow_level = exp2s (byteptr [0] + (byteptr [1] << 8));
+ byteptr += 2;
+ }
}
wps->w.bitrate_acc [0] = (long)(byteptr [0] + (byteptr [1] << 8)) << 16;
byteptr += 2;
if (!(wps->wphdr.flags & MONO_FLAG)) {
- wps->w.bitrate_acc [1] = (long)(byteptr [0] + (byteptr [1] << 8)) << 16;
- byteptr += 2;
+ wps->w.bitrate_acc [1] = (long)(byteptr [0] + (byteptr [1] << 8)) << 16;
+ byteptr += 2;
}
if (byteptr < endptr) {
- wps->w.bitrate_delta [0] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8)));
- byteptr += 2;
+ wps->w.bitrate_delta [0] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8)));
+ byteptr += 2;
- if (!(wps->wphdr.flags & MONO_FLAG)) {
- wps->w.bitrate_delta [1] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8)));
- byteptr += 2;
- }
+ if (!(wps->wphdr.flags & MONO_FLAG)) {
+ wps->w.bitrate_delta [1] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8)));
+ byteptr += 2;
+ }
- if (byteptr < endptr)
- return FALSE;
+ if (byteptr < endptr)
+ return FALSE;
}
else
- wps->w.bitrate_delta [0] = wps->w.bitrate_delta [1] = 0;
+ wps->w.bitrate_delta [0] = wps->w.bitrate_delta [1] = 0;
return TRUE;
}
@@ -214,60 +275,60 @@ int read_hybrid_profile (WavpackStream *wps, WavpackMetadata *wpmd)
// currently implemented) this is calculated from the slow_level values and the
// bitrate accumulators. Note that the bitrate accumulators can be changing.
-static void update_error_limit (WavpackStream *wps)
+void update_error_limit (struct words_data *w, ulong flags)
{
- int bitrate_0 = (wps->w.bitrate_acc [0] += wps->w.bitrate_delta [0]) >> 16;
-
- if (wps->wphdr.flags & MONO_FLAG) {
- if (wps->wphdr.flags & HYBRID_BITRATE) {
- int slow_log_0 = (wps->w.c [0].slow_level + SLO) >> SLS;
-
- if (slow_log_0 - bitrate_0 > -0x100)
- wps->w.c [0].error_limit = exp2s (slow_log_0 - bitrate_0 + 0x100);
- else
- wps->w.c [0].error_limit = 0;
- }
- else
- wps->w.c [0].error_limit = exp2s (bitrate_0);
+ int bitrate_0 = (w->bitrate_acc [0] += w->bitrate_delta [0]) >> 16;
+
+ if (flags & MONO_FLAG) {
+ if (flags & HYBRID_BITRATE) {
+ int slow_log_0 = (w->c [0].slow_level + SLO) >> SLS;
+
+ if (slow_log_0 - bitrate_0 > -0x100)
+ w->c [0].error_limit = exp2s (slow_log_0 - bitrate_0 + 0x100);
+ else
+ w->c [0].error_limit = 0;
+ }
+ else
+ w->c [0].error_limit = exp2s (bitrate_0);
}
else {
- int bitrate_1 = (wps->w.bitrate_acc [1] += wps->w.bitrate_delta [1]) >> 16;
-
- if (wps->wphdr.flags & HYBRID_BITRATE) {
- int slow_log_0 = (wps->w.c [0].slow_level + SLO) >> SLS;
- int slow_log_1 = (wps->w.c [1].slow_level + SLO) >> SLS;
-
- if (wps->wphdr.flags & HYBRID_BALANCE) {
- int balance = (slow_log_1 - slow_log_0 + bitrate_1 + 1) >> 1;
-
- if (balance > bitrate_0) {
- bitrate_1 = bitrate_0 * 2;
- bitrate_0 = 0;
- }
- else if (-balance > bitrate_0) {
- bitrate_0 = bitrate_0 * 2;
- bitrate_1 = 0;
- }
- else {
- bitrate_1 = bitrate_0 + balance;
- bitrate_0 = bitrate_0 - balance;
- }
- }
-
- if (slow_log_0 - bitrate_0 > -0x100)
- wps->w.c [0].error_limit = exp2s (slow_log_0 - bitrate_0 + 0x100);
- else
- wps->w.c [0].error_limit = 0;
-
- if (slow_log_1 - bitrate_1 > -0x100)
- wps->w.c [1].error_limit = exp2s (slow_log_1 - bitrate_1 + 0x100);
- else
- wps->w.c [1].error_limit = 0;
- }
- else {
- wps->w.c [0].error_limit = exp2s (bitrate_0);
- wps->w.c [1].error_limit = exp2s (bitrate_1);
- }
+ int bitrate_1 = (w->bitrate_acc [1] += w->bitrate_delta [1]) >> 16;
+
+ if (flags & HYBRID_BITRATE) {
+ int slow_log_0 = (w->c [0].slow_level + SLO) >> SLS;
+ int slow_log_1 = (w->c [1].slow_level + SLO) >> SLS;
+
+ if (flags & HYBRID_BALANCE) {
+ int balance = (slow_log_1 - slow_log_0 + bitrate_1 + 1) >> 1;
+
+ if (balance > bitrate_0) {
+ bitrate_1 = bitrate_0 * 2;
+ bitrate_0 = 0;
+ }
+ else if (-balance > bitrate_0) {
+ bitrate_0 = bitrate_0 * 2;
+ bitrate_1 = 0;
+ }
+ else {
+ bitrate_1 = bitrate_0 + balance;
+ bitrate_0 = bitrate_0 - balance;
+ }
+ }
+
+ if (slow_log_0 - bitrate_0 > -0x100)
+ w->c [0].error_limit = exp2s (slow_log_0 - bitrate_0 + 0x100);
+ else
+ w->c [0].error_limit = 0;
+
+ if (slow_log_1 - bitrate_1 > -0x100)
+ w->c [1].error_limit = exp2s (slow_log_1 - bitrate_1 + 0x100);
+ else
+ w->c [1].error_limit = 0;
+ }
+ else {
+ w->c [0].error_limit = exp2s (bitrate_0);
+ w->c [1].error_limit = exp2s (bitrate_1);
+ }
}
}
@@ -281,168 +342,171 @@ static ulong read_code (Bitstream *bs, ulong maxcode);
// of WORD_EOF indicates that the end of the bitstream was reached (all 1s) or
// some other error occurred.
-long get_words (WavpackStream *wps, int nchans, int nsamples, long *buffer)
+long get_words (long *buffer, int nsamples, ulong flags,
+ struct words_data *w, Bitstream *bs)
{
- ulong ones_count, low, mid, high;
- register struct entropy_data *c;
- long *bptr = buffer;
-
- nsamples *= nchans;
-
- while (nsamples--) {
-
- c = wps->w.c + ((nchans == 1) ? 0 : (~nsamples & 1));
-
- if (!(wps->w.c [0].median [0] & ~1) && !wps->w.holding_zero && !wps->w.holding_one && !(wps->w.c [1].median [0] & ~1)) {
- ulong mask;
- int cbits;
-
- if (wps->w.zeros_acc) {
- if (--wps->w.zeros_acc) {
- c->slow_level -= (c->slow_level + SLO) >> SLS;
- *bptr++ = 0;
- continue;
- }
- }
- else {
- for (cbits = 0; cbits < 33 && getbit (&wps->wvbits); ++cbits);
-
- if (cbits == 33)
- break;
-
- if (cbits < 2)
- wps->w.zeros_acc = cbits;
- else {
- for (mask = 1, wps->w.zeros_acc = 0; --cbits; mask <<= 1)
- if (getbit (&wps->wvbits))
- wps->w.zeros_acc |= mask;
-
- wps->w.zeros_acc |= mask;
- }
-
- if (wps->w.zeros_acc) {
- c->slow_level -= (c->slow_level + SLO) >> SLS;
- CLEAR (wps->w.c [0].median);
- CLEAR (wps->w.c [1].median);
- *bptr++ = 0;
- continue;
- }
- }
- }
-
- if (wps->w.holding_zero)
- ones_count = wps->w.holding_zero = 0;
- else {
- int next8;
-
- if (wps->wvbits.bc < 8) {
- if (++(wps->wvbits.ptr) == wps->wvbits.end)
- wps->wvbits.wrap (&wps->wvbits);
-
- next8 = (wps->wvbits.sr |= *(wps->wvbits.ptr) << wps->wvbits.bc) & 0xff;
- wps->wvbits.bc += 8;
- }
- else
- next8 = wps->wvbits.sr & 0xff;
-
- if (next8 == 0xff) {
- wps->wvbits.bc -= 8;
- wps->wvbits.sr >>= 8;
-
- for (ones_count = 8; ones_count < (LIMIT_ONES + 1) && getbit (&wps->wvbits); ++ones_count);
-
- if (ones_count == (LIMIT_ONES + 1))
- break;
-
- if (ones_count == LIMIT_ONES) {
- ulong mask;
- int cbits;
-
- for (cbits = 0; cbits < 33 && getbit (&wps->wvbits); ++cbits);
-
- if (cbits == 33)
- break;
-
- if (cbits < 2)
- ones_count = cbits;
- else {
- for (mask = 1, ones_count = 0; --cbits; mask <<= 1)
- if (getbit (&wps->wvbits))
- ones_count |= mask;
-
- ones_count |= mask;
- }
-
- ones_count += LIMIT_ONES;
- }
- }
- else {
- wps->wvbits.bc -= (ones_count = ones_count_table [next8]) + 1;
- wps->wvbits.sr >>= ones_count + 1;
- }
-
- if (wps->w.holding_one) {
- wps->w.holding_one = ones_count & 1;
- ones_count = (ones_count >> 1) + 1;
- }
- else {
- wps->w.holding_one = ones_count & 1;
- ones_count >>= 1;
- }
-
- wps->w.holding_zero = ~wps->w.holding_one & 1;
- }
-
- if ((wps->wphdr.flags & HYBRID_FLAG) && (nchans == 1 || (nsamples & 1)))
- update_error_limit (wps);
-
- if (ones_count == 0) {
- low = 0;
- high = GET_MED (0) - 1;
- DEC_MED0 ();
- }
- else {
- low = GET_MED (0);
- INC_MED0 ();
-
- if (ones_count == 1) {
- high = low + GET_MED (1) - 1;
- DEC_MED1 ();
- }
- else {
- low += GET_MED (1);
- INC_MED1 ();
-
- if (ones_count == 2) {
- high = low + GET_MED (2) - 1;
- DEC_MED2 ();
- }
- else {
- low += (ones_count - 2) * GET_MED (2);
- high = low + GET_MED (2) - 1;
- INC_MED2 ();
- }
- }
- }
-
- mid = (high + low + 1) >> 1;
-
- if (!c->error_limit)
- mid = read_code (&wps->wvbits, high - low) + low;
- else while (high - low > c->error_limit) {
- if (getbit (&wps->wvbits))
- mid = (high + (low = mid) + 1) >> 1;
- else
- mid = ((high = mid - 1) + low + 1) >> 1;
- }
-
- *bptr++ = getbit (&wps->wvbits) ? ~mid : mid;
-
- if (wps->wphdr.flags & HYBRID_BITRATE)
- c->slow_level = c->slow_level - ((c->slow_level + SLO) >> SLS) + mylog2 (mid);
+ register struct entropy_data *c = w->c;
+ int csamples;
+
+ if (!(flags & MONO_FLAG))
+ nsamples *= 2;
+
+ for (csamples = 0; csamples < nsamples; ++csamples) {
+ ulong ones_count, low, mid, high;
+
+ if (!(flags & MONO_FLAG))
+ c = w->c + (csamples & 1);
+
+ if (!(w->c [0].median [0] & ~1) && !w->holding_zero && !w->holding_one && !(w->c [1].median [0] & ~1)) {
+ ulong mask;
+ int cbits;
+
+ if (w->zeros_acc) {
+ if (--w->zeros_acc) {
+ c->slow_level -= (c->slow_level + SLO) >> SLS;
+ *buffer++ = 0;
+ continue;
+ }
+ }
+ else {
+ for (cbits = 0; cbits < 33 && getbit (bs); ++cbits);
+
+ if (cbits == 33)
+ break;
+
+ if (cbits < 2)
+ w->zeros_acc = cbits;
+ else {
+ for (mask = 1, w->zeros_acc = 0; --cbits; mask <<= 1)
+ if (getbit (bs))
+ w->zeros_acc |= mask;
+
+ w->zeros_acc |= mask;
+ }
+
+ if (w->zeros_acc) {
+ c->slow_level -= (c->slow_level + SLO) >> SLS;
+ CLEAR (w->c [0].median);
+ CLEAR (w->c [1].median);
+ *buffer++ = 0;
+ continue;
+ }
+ }
+ }
+
+ if (w->holding_zero)
+ ones_count = w->holding_zero = 0;
+ else {
+ int next8;
+
+ if (bs->bc < 8) {
+ if (++(bs->ptr) == bs->end)
+ bs->wrap (bs);
+
+ next8 = (bs->sr |= *(bs->ptr) << bs->bc) & 0xff;
+ bs->bc += 8;
+ }
+ else
+ next8 = bs->sr & 0xff;
+
+ if (next8 == 0xff) {
+ bs->bc -= 8;
+ bs->sr >>= 8;
+
+ for (ones_count = 8; ones_count < (LIMIT_ONES + 1) && getbit (bs); ++ones_count);
+
+ if (ones_count == (LIMIT_ONES + 1))
+ break;
+
+ if (ones_count == LIMIT_ONES) {
+ ulong mask;
+ int cbits;
+
+ for (cbits = 0; cbits < 33 && getbit (bs); ++cbits);
+
+ if (cbits == 33)
+ break;
+
+ if (cbits < 2)
+ ones_count = cbits;
+ else {
+ for (mask = 1, ones_count = 0; --cbits; mask <<= 1)
+ if (getbit (bs))
+ ones_count |= mask;
+
+ ones_count |= mask;
+ }
+
+ ones_count += LIMIT_ONES;
+ }
+ }
+ else {
+ bs->bc -= (ones_count = ones_count_table [next8]) + 1;
+ bs->sr >>= ones_count + 1;
+ }
+
+ if (w->holding_one) {
+ w->holding_one = ones_count & 1;
+ ones_count = (ones_count >> 1) + 1;
+ }
+ else {
+ w->holding_one = ones_count & 1;
+ ones_count >>= 1;
+ }
+
+ w->holding_zero = ~w->holding_one & 1;
+ }
+
+ if ((flags & HYBRID_FLAG) && ((flags & MONO_FLAG) || !(csamples & 1)))
+ update_error_limit (w, flags);
+
+ if (ones_count == 0) {
+ low = 0;
+ high = GET_MED (0) - 1;
+ DEC_MED0 ();
+ }
+ else {
+ low = GET_MED (0);
+ INC_MED0 ();
+
+ if (ones_count == 1) {
+ high = low + GET_MED (1) - 1;
+ DEC_MED1 ();
+ }
+ else {
+ low += GET_MED (1);
+ INC_MED1 ();
+
+ if (ones_count == 2) {
+ high = low + GET_MED (2) - 1;
+ DEC_MED2 ();
+ }
+ else {
+ low += (ones_count - 2) * GET_MED (2);
+ high = low + GET_MED (2) - 1;
+ INC_MED2 ();
+ }
+ }
+ }
+
+ mid = (high + low + 1) >> 1;
+
+ if (!c->error_limit)
+ mid = read_code (bs, high - low) + low;
+ else while (high - low > c->error_limit) {
+ if (getbit (bs))
+ mid = (high + (low = mid) + 1) >> 1;
+ else
+ mid = ((high = mid - 1) + low + 1) >> 1;
+ }
+
+ *buffer++ = getbit (bs) ? ~mid : mid;
+
+ if (flags & HYBRID_BITRATE)
+ c->slow_level = c->slow_level - ((c->slow_level + SLO) >> SLS) + mylog2 (mid);
}
- return nchans == 1 ? (bptr - buffer) : ((bptr - buffer) / 2);
+ return (flags & MONO_FLAG) ? csamples : (csamples / 2);
}
// Read a single unsigned value from the specified bitstream with a value
@@ -457,21 +521,195 @@ static ulong read_code (Bitstream *bs, ulong maxcode)
ulong extras = (1L << bitcount) - maxcode - 1, code;
if (!bitcount)
- return 0;
+ return 0;
getbits (&code, bitcount - 1, bs);
code &= (1L << (bitcount - 1)) - 1;
if (code >= extras) {
- code = (code << 1) - extras;
+ code = (code << 1) - extras;
- if (getbit (bs))
- ++code;
+ if (getbit (bs))
+ ++code;
}
return code;
}
+// This function is an optimized version of send_word() that only handles
+// lossless (error_limit == 0). It does not return a value because it always
+// encodes the exact value passed.
+
+void send_word_lossless (WavpackStream *wps, long value, int chan)
+{
+ register struct words_data *w = &wps->w;
+ register struct entropy_data *c = w->c + chan;
+ int sign = (value < 0) ? 1 : 0;
+ ulong ones_count, low, high;
+
+ if (!(wps->w.c [0].median [0] & ~1) && !wps->w.holding_zero && !(wps->w.c [1].median [0] & ~1)) {
+ if (wps->w.zeros_acc) {
+ if (value)
+ flush_word (wps);
+ else {
+ wps->w.zeros_acc++;
+ return;
+ }
+ }
+ else if (value) {
+ putbit_0 (&wps->wvbits);
+ }
+ else {
+ CLEAR (wps->w.c [0].median);
+ CLEAR (wps->w.c [1].median);
+ wps->w.zeros_acc = 1;
+ return;
+ }
+ }
+
+ if (sign)
+ value = ~value;
+
+ if ((unsigned long) value < GET_MED (0)) {
+ ones_count = low = 0;
+ high = GET_MED (0) - 1;
+ DEC_MED0 ();
+ }
+ else {
+ low = GET_MED (0);
+ INC_MED0 ();
+
+ if (value - low < GET_MED (1)) {
+ ones_count = 1;
+ high = low + GET_MED (1) - 1;
+ DEC_MED1 ();
+ }
+ else {
+ low += GET_MED (1);
+ INC_MED1 ();
+
+ if (value - low < GET_MED (2)) {
+ ones_count = 2;
+ high = low + GET_MED (2) - 1;
+ DEC_MED2 ();
+ }
+ else {
+ ones_count = 2 + (value - low) / GET_MED (2);
+ low += (ones_count - 2) * GET_MED (2);
+ high = low + GET_MED (2) - 1;
+ INC_MED2 ();
+ }
+ }
+ }
+
+ if (wps->w.holding_zero) {
+ if (ones_count)
+ wps->w.holding_one++;
+
+ flush_word (wps);
+
+ if (ones_count) {
+ wps->w.holding_zero = 1;
+ ones_count--;
+ }
+ else
+ wps->w.holding_zero = 0;
+ }
+ else
+ wps->w.holding_zero = 1;
+
+ wps->w.holding_one = ones_count * 2;
+
+ if (high != low) {
+ ulong maxcode = high - low, code = value - low;
+ int bitcount = count_bits (maxcode);
+ ulong extras = bitset [bitcount] - maxcode - 1;
+
+ if (code < extras) {
+ wps->w.pend_data |= code << wps->w.pend_count;
+ wps->w.pend_count += bitcount - 1;
+ }
+ else {
+ wps->w.pend_data |= ((code + extras) >> 1) << wps->w.pend_count;
+ wps->w.pend_count += bitcount - 1;
+ wps->w.pend_data |= ((code + extras) & 1) << wps->w.pend_count++;
+ }
+ }
+
+ wps->w.pend_data |= ((long) sign << wps->w.pend_count++);
+
+ if (!wps->w.holding_zero)
+ flush_word (wps);
+}
+
+// Used by send_word() and send_word_lossless() to actually send most the
+// accumulated data onto the bitstream. This is also called directly from
+// clients when all words have been sent.
+
+void flush_word (WavpackStream *wps)
+{
+ if (wps->w.zeros_acc) {
+ int cbits = count_bits (wps->w.zeros_acc);
+
+ while (cbits--) {
+ putbit_1 (&wps->wvbits);
+ }
+
+ putbit_0 (&wps->wvbits);
+
+ while (wps->w.zeros_acc > 1) {
+ putbit (wps->w.zeros_acc & 1, &wps->wvbits);
+ wps->w.zeros_acc >>= 1;
+ }
+
+ wps->w.zeros_acc = 0;
+ }
+
+ if (wps->w.holding_one) {
+ if (wps->w.holding_one >= LIMIT_ONES) {
+ int cbits;
+
+ putbits ((1L << LIMIT_ONES) - 1, LIMIT_ONES + 1, &wps->wvbits);
+ wps->w.holding_one -= LIMIT_ONES;
+ cbits = count_bits (wps->w.holding_one);
+
+ while (cbits--) {
+ putbit_1 (&wps->wvbits);
+ }
+
+ putbit_0 (&wps->wvbits);
+
+ while (wps->w.holding_one > 1) {
+ putbit (wps->w.holding_one & 1, &wps->wvbits);
+ wps->w.holding_one >>= 1;
+ }
+
+ wps->w.holding_zero = 0;
+ }
+ else
+ putbits (bitmask [wps->w.holding_one], wps->w.holding_one, &wps->wvbits);
+
+ wps->w.holding_one = 0;
+ }
+
+ if (wps->w.holding_zero) {
+ putbit_0 (&wps->wvbits);
+ wps->w.holding_zero = 0;
+ }
+
+ if (wps->w.pend_count) {
+
+ while (wps->w.pend_count > 24) {
+ putbit (wps->w.pend_data & 1, &wps->wvbits);
+ wps->w.pend_data >>= 1;
+ wps->w.pend_count--;
+ }
+
+ putbits (wps->w.pend_data, wps->w.pend_count, &wps->wvbits);
+ wps->w.pend_data = wps->w.pend_count = 0;
+ }
+}
+
// The concept of a base 2 logarithm is used in many parts of WavPack. It is
// a way of sufficiently accurately representing 32-bit signed and unsigned
// values storing only 16 bits (actually fewer). It is also used in the hybrid
@@ -492,21 +730,30 @@ static int mylog2 (unsigned long avalue)
int dbits;
if ((avalue += avalue >> 9) < (1 << 8)) {
- dbits = nbits_table [avalue];
- return (dbits << 8) + log2_table [(avalue << (9 - dbits)) & 0xff];
+ dbits = nbits_table [avalue];
+ return (dbits << 8) + log2_table [(avalue << (9 - dbits)) & 0xff];
}
else {
- if (avalue < (1L << 16))
- dbits = nbits_table [avalue >> 8] + 8;
- else if (avalue < (1L << 24))
- dbits = nbits_table [avalue >> 16] + 16;
- else
- dbits = nbits_table [avalue >> 24] + 24;
-
- return (dbits << 8) + log2_table [(avalue >> (dbits - 9)) & 0xff];
+ if (avalue < (1L << 16))
+ dbits = nbits_table [avalue >> 8] + 8;
+ else if (avalue < (1L << 24))
+ dbits = nbits_table [avalue >> 16] + 16;
+ else
+ dbits = nbits_table [avalue >> 24] + 24;
+
+ return (dbits << 8) + log2_table [(avalue >> (dbits - 9)) & 0xff];
}
}
+// This function returns the log2 for the specified 32-bit signed value.
+// All input values are valid and the return values are in the range of
+// +/- 8192.
+
+int log2s (long value)
+{
+ return (value < 0) ? -mylog2 (-value) : mylog2 (value);
+}
+
// This function returns the original integer represented by the supplied
// logarithm (at least within the provided accuracy). The log is signed,
// but since a full 32-bit value is returned this can be used for unsigned
@@ -517,26 +764,39 @@ long exp2s (int log)
ulong value;
if (log < 0)
- return -exp2s (-log);
+ return -exp2s (-log);
value = exp2_table [log & 0xff] | 0x100;
if ((log >>= 8) <= 9)
- return value >> (9 - log);
+ return value >> (9 - log);
else
- return value << (log - 9);
+ return value << (log - 9);
}
// These two functions convert internal weights (which are normally +/-1024)
// to and from an 8-bit signed character version for storage in metadata. The
// weights are clipped here in the case that they are outside that range.
+char store_weight (int weight)
+{
+ if (weight > 1024)
+ weight = 1024;
+ else if (weight < -1024)
+ weight = -1024;
+
+ if (weight > 0)
+ weight -= (weight + 64) >> 7;
+
+ return (weight + 4) >> 3;
+}
+
int restore_weight (char weight)
{
int result;
if ((result = (int) weight << 3) > 0)
- result += (result + 64) >> 7;
+ result += (result + 64) >> 7;
return result;
}
diff --git a/apps/codecs/libwavpack/wputils.c b/apps/codecs/libwavpack/wputils.c
index 8d58b3b..7f2ab14 100644
--- a/apps/codecs/libwavpack/wputils.c
+++ b/apps/codecs/libwavpack/wputils.c
@@ -1,8 +1,8 @@
////////////////////////////////////////////////////////////////////////////
-// **** WAVPACK **** //
-// Hybrid Lossless Wavefile Compressor //
-// Copyright (c) 1998 - 2004 Conifer Software. //
-// All Rights Reserved. //
+// **** WAVPACK **** //
+// Hybrid Lossless Wavefile Compressor //
+// Copyright (c) 1998 - 2004 Conifer Software. //
+// All Rights Reserved. //
// Distributed under the BSD Software License (see license.txt) //
////////////////////////////////////////////////////////////////////////////
@@ -19,7 +19,7 @@
#include <string.h>
-static void strcpy_loc (char *dst, char *src) { while (*src) *dst++ = *src++; *dst = 0; }
+static void strcpy_loc (char *dst, char *src) { while ((*dst++ = *src++) != 0); }
///////////////////////////// local table storage ////////////////////////////
@@ -29,7 +29,7 @@ const ulong sample_rates [] = { 6000, 8000, 9600, 11025, 12000, 16000, 22050,
///////////////////////////// executable code ////////////////////////////////
static ulong read_next_header (read_stream infile, WavpackHeader *wphdr);
-
+
// This function reads data from the specified stream in search of a valid
// WavPack 4.0 audio block. If this fails in 1 megabyte (or an invalid or
// unsupported WavPack block is encountered) then an appropriate message is
@@ -62,27 +62,27 @@ WavpackContext *WavpackOpenFileInput (read_stream infile, char *error)
while (!wps->wphdr.block_samples) {
- bcount = read_next_header (wpc.infile, &wps->wphdr);
+ bcount = read_next_header (wpc.infile, &wps->wphdr);
- if (bcount == (ulong) -1) {
- strcpy_loc (error, "invalid WavPack file!");
- return NULL;
- }
+ if (bcount == (ulong) -1) {
+ strcpy_loc (error, "invalid WavPack file!");
+ return NULL;
+ }
- if ((wps->wphdr.flags & UNKNOWN_FLAGS) || wps->wphdr.version < 0x402 || wps->wphdr.version > 0x40f) {
- strcpy_loc (error, "invalid WavPack file!");
- return NULL;
- }
+ if ((wps->wphdr.flags & UNKNOWN_FLAGS) || wps->wphdr.version < 0x402 || wps->wphdr.version > 0x40f) {
+ strcpy_loc (error, "invalid WavPack file!");
+ return NULL;
+ }
- if (wps->wphdr.block_samples && wps->wphdr.total_samples != (ulong) -1)
- wpc.total_samples = wps->wphdr.total_samples;
+ if (wps->wphdr.block_samples && wps->wphdr.total_samples != (ulong) -1)
+ wpc.total_samples = wps->wphdr.total_samples;
- if (!unpack_init (&wpc)) {
- strcpy_loc (error, wpc.error_message [0] ? wpc.error_message :
- "invalid WavPack file!");
+ if (!unpack_init (&wpc)) {
+ strcpy_loc (error, wpc.error_message [0] ? wpc.error_message :
+ "invalid WavPack file!");
- return NULL;
- }
+ return NULL;
+ }
}
wpc.config.flags &= ~0xff;
@@ -91,22 +91,22 @@ WavpackContext *WavpackOpenFileInput (read_stream infile, char *error)
wpc.config.float_norm_exp = wps->float_norm_exp;
wpc.config.bits_per_sample = (wpc.config.bytes_per_sample * 8) -
- ((wps->wphdr.flags & SHIFT_MASK) >> SHIFT_LSB);
+ ((wps->wphdr.flags & SHIFT_MASK) >> SHIFT_LSB);
if (!wpc.config.sample_rate) {
- if (!wps || !wps->wphdr.block_samples || (wps->wphdr.flags & SRATE_MASK) == SRATE_MASK)
- wpc.config.sample_rate = 44100;
- else
- wpc.config.sample_rate = sample_rates [(wps->wphdr.flags & SRATE_MASK) >> SRATE_LSB];
+ if (!wps || !wps->wphdr.block_samples || (wps->wphdr.flags & SRATE_MASK) == SRATE_MASK)
+ wpc.config.sample_rate = 44100;
+ else
+ wpc.config.sample_rate = sample_rates [(wps->wphdr.flags & SRATE_MASK) >> SRATE_LSB];
}
if (!wpc.config.num_channels) {
- wpc.config.num_channels = (wps->wphdr.flags & MONO_FLAG) ? 1 : 2;
- wpc.config.channel_mask = 0x5 - wpc.config.num_channels;
+ wpc.config.num_channels = (wps->wphdr.flags & MONO_FLAG) ? 1 : 2;
+ wpc.config.channel_mask = 0x5 - wpc.config.num_channels;
}
if (!(wps->wphdr.flags & FINAL_BLOCK))
- wpc.reduced_channels = (wps->wphdr.flags & MONO_FLAG) ? 1 : 2;
+ wpc.reduced_channels = (wps->wphdr.flags & MONO_FLAG) ? 1 : 2;
return &wpc;
}
@@ -125,22 +125,22 @@ int WavpackGetMode (WavpackContext *wpc)
int mode = 0;
if (wpc) {
- if (wpc->config.flags & CONFIG_HYBRID_FLAG)
- mode |= MODE_HYBRID;
- else if (!(wpc->config.flags & CONFIG_LOSSY_MODE))
- mode |= MODE_LOSSLESS;
+ if (wpc->config.flags & CONFIG_HYBRID_FLAG)
+ mode |= MODE_HYBRID;
+ else if (!(wpc->config.flags & CONFIG_LOSSY_MODE))
+ mode |= MODE_LOSSLESS;
- if (wpc->lossy_blocks)
- mode &= ~MODE_LOSSLESS;
+ if (wpc->lossy_blocks)
+ mode &= ~MODE_LOSSLESS;
- if (wpc->config.flags & CONFIG_FLOAT_DATA)
- mode |= MODE_FLOAT;
+ if (wpc->config.flags & CONFIG_FLOAT_DATA)
+ mode |= MODE_FLOAT;
- if (wpc->config.flags & CONFIG_HIGH_FLAG)
- mode |= MODE_HIGH;
+ if (wpc->config.flags & CONFIG_HIGH_FLAG)
+ mode |= MODE_HIGH;
- if (wpc->config.flags & CONFIG_FAST_FLAG)
- mode |= MODE_FAST;
+ if (wpc->config.flags & CONFIG_FAST_FLAG)
+ mode |= MODE_FAST;
}
return mode;
@@ -163,70 +163,70 @@ ulong WavpackUnpackSamples (WavpackContext *wpc, long *buffer, ulong samples)
int num_channels = wpc->config.num_channels;
while (samples) {
- if (!wps->wphdr.block_samples || !(wps->wphdr.flags & INITIAL_BLOCK) ||
- wps->sample_index >= wps->wphdr.block_index + wps->wphdr.block_samples) {
- bcount = read_next_header (wpc->infile, &wps->wphdr);
+ if (!wps->wphdr.block_samples || !(wps->wphdr.flags & INITIAL_BLOCK) ||
+ wps->sample_index >= wps->wphdr.block_index + wps->wphdr.block_samples) {
+ bcount = read_next_header (wpc->infile, &wps->wphdr);
- if (bcount == (ulong) -1)
- break;
+ if (bcount == (ulong) -1)
+ break;
- if (wps->wphdr.version < 0x402 || wps->wphdr.version > 0x40f) {
- strcpy_loc (wpc->error_message, "invalid WavPack file!");
- break;
- }
+ if (wps->wphdr.version < 0x402 || wps->wphdr.version > 0x40f) {
+ strcpy_loc (wpc->error_message, "invalid WavPack file!");
+ break;
+ }
- if (!wps->wphdr.block_samples || wps->sample_index == wps->wphdr.block_index)
- if (!unpack_init (wpc))
- break;
- }
+ if (!wps->wphdr.block_samples || wps->sample_index == wps->wphdr.block_index)
+ if (!unpack_init (wpc))
+ break;
+ }
- if (!wps->wphdr.block_samples || !(wps->wphdr.flags & INITIAL_BLOCK) ||
- wps->sample_index >= wps->wphdr.block_index + wps->wphdr.block_samples)
- continue;
+ if (!wps->wphdr.block_samples || !(wps->wphdr.flags & INITIAL_BLOCK) ||
+ wps->sample_index >= wps->wphdr.block_index + wps->wphdr.block_samples)
+ continue;
- if (wps->sample_index < wps->wphdr.block_index) {
- samples_to_unpack = wps->wphdr.block_index - wps->sample_index;
+ if (wps->sample_index < wps->wphdr.block_index) {
+ samples_to_unpack = wps->wphdr.block_index - wps->sample_index;
- if (samples_to_unpack > samples)
- samples_to_unpack = samples;
+ if (samples_to_unpack > samples)
+ samples_to_unpack = samples;
- wps->sample_index += samples_to_unpack;
- samples_unpacked += samples_to_unpack;
- samples -= samples_to_unpack;
+ wps->sample_index += samples_to_unpack;
+ samples_unpacked += samples_to_unpack;
+ samples -= samples_to_unpack;
- if (wpc->reduced_channels)
- samples_to_unpack *= wpc->reduced_channels;
- else
- samples_to_unpack *= num_channels;
+ if (wpc->reduced_channels)
+ samples_to_unpack *= wpc->reduced_channels;
+ else
+ samples_to_unpack *= num_channels;
- while (samples_to_unpack--)
- *buffer++ = 0;
+ while (samples_to_unpack--)
+ *buffer++ = 0;
- continue;
- }
+ continue;
+ }
- samples_to_unpack = wps->wphdr.block_index + wps->wphdr.block_samples - wps->sample_index;
+ samples_to_unpack = wps->wphdr.block_index + wps->wphdr.block_samples - wps->sample_index;
- if (samples_to_unpack > samples)
- samples_to_unpack = samples;
+ if (samples_to_unpack > samples)
+ samples_to_unpack = samples;
- unpack_samples (wpc, buffer, samples_to_unpack);
+ unpack_samples (wpc, buffer, samples_to_unpack);
- if (wpc->reduced_channels)
- buffer += samples_to_unpack * wpc->reduced_channels;
- else
- buffer += samples_to_unpack * num_channels;
+ if (wpc->reduced_channels)
+ buffer += samples_to_unpack * wpc->reduced_channels;
+ else
+ buffer += samples_to_unpack * num_channels;
- samples_unpacked += samples_to_unpack;
- samples -= samples_to_unpack;
+ samples_unpacked += samples_to_unpack;
+ samples -= samples_to_unpack;
- if (wps->sample_index == wps->wphdr.block_index + wps->wphdr.block_samples) {
- if (check_crc_error (wpc))
- wpc->crc_errors++;
- }
+ if (wps->sample_index == wps->wphdr.block_index + wps->wphdr.block_samples) {
+ if (check_crc_error (wpc))
+ wpc->crc_errors++;
+ }
- if (wps->sample_index == wpc->total_samples)
- break;
+ if (wps->sample_index == wpc->total_samples)
+ break;
}
return samples_unpacked;
@@ -244,7 +244,7 @@ ulong WavpackGetNumSamples (WavpackContext *wpc)
ulong WavpackGetSampleIndex (WavpackContext *wpc)
{
if (wpc)
- return wpc->stream.sample_index;
+ return wpc->stream.sample_index;
return (ulong) -1;
}
@@ -310,9 +310,9 @@ int WavpackGetBytesPerSample (WavpackContext *wpc)
int WavpackGetReducedChannels (WavpackContext *wpc)
{
if (wpc)
- return wpc->reduced_channels ? wpc->reduced_channels : wpc->config.num_channels;
+ return wpc->reduced_channels ? wpc->reduced_channels : wpc->config.num_channels;
else
- return 2;
+ return 2;
}
// Read from current file position until a valid 32-byte WavPack 4.0 header is
@@ -328,29 +328,228 @@ static ulong read_next_header (read_stream infile, WavpackHeader *wphdr)
int bleft;
while (1) {
- if (sp < ep) {
- bleft = ep - sp;
- memcpy (buffer, sp, bleft);
- }
- else
- bleft = 0;
-
- if (infile (buffer + bleft, sizeof (*wphdr) - bleft) != (long) sizeof (*wphdr) - bleft)
- return -1;
-
- sp = buffer;
-
- if (*sp++ == 'w' && *sp == 'v' && *++sp == 'p' && *++sp == 'k' &&
- !(*++sp & 1) && sp [2] < 16 && !sp [3] && sp [5] == 4 && sp [4] >= 2 && sp [4] <= 0xf) {
- memcpy (wphdr, buffer, sizeof (*wphdr));
- little_endian_to_native (wphdr, WavpackHeaderFormat);
- return bytes_skipped;
- }
-
- while (sp < ep && *sp != 'w')
- sp++;
-
- if ((bytes_skipped += sp - buffer) > 1024 * 1024)
- return -1;
+ if (sp < ep) {
+ bleft = ep - sp;
+ memcpy (buffer, sp, bleft);
+ }
+ else
+ bleft = 0;
+
+ if (infile (buffer + bleft, sizeof (*wphdr) - bleft) != (long) sizeof (*wphdr) - bleft)
+ return -1;
+
+ sp = buffer;
+
+ if (*sp++ == 'w' && *sp == 'v' && *++sp == 'p' && *++sp == 'k' &&
+ !(*++sp & 1) && sp [2] < 16 && !sp [3] && sp [5] == 4 && sp [4] >= 2 && sp [4] <= 0xf) {
+ memcpy (wphdr, buffer, sizeof (*wphdr));
+ little_endian_to_native (wphdr, WavpackHeaderFormat);
+ return bytes_skipped;
+ }
+
+ while (sp < ep && *sp != 'w')
+ sp++;
+
+ if ((bytes_skipped += sp - buffer) > 1024 * 1024)
+ return -1;
}
}
+
+// Open context for writing WavPack files. The returned context pointer is used
+// in all following calls to the library. A return value of NULL indicates
+// that memory could not be allocated for the context.
+
+WavpackContext *WavpackOpenFileOutput (void)
+{
+ CLEAR (wpc);
+ return &wpc;
+}
+
+// Set the output buffer limits. This must be done before calling
+// WavpackPackSamples(), but also may be done afterward to adjust
+// the usable buffer. Note that writing CANNOT wrap in the buffer; the
+// entire output block must fit in the buffer.
+
+void WavpackSetOutputBuffer (WavpackContext *wpc, uchar *begin, uchar *end)
+{
+ wpc->stream.blockbuff = begin;
+ wpc->stream.blockend = end;
+}
+
+// Set configuration for writing WavPack files. This must be done before
+// sending any actual samples, however it is okay to send wrapper or other
+// metadata before calling this. The "config" structure contains the following
+// required information:
+
+// config->bytes_per_sample see WavpackGetBytesPerSample() for info
+// config->bits_per_sample see WavpackGetBitsPerSample() for info
+// config->num_channels self evident
+// config->sample_rate self evident
+
+// In addition, the following fields and flags may be set:
+
+// config->flags:
+// --------------
+// o CONFIG_HYBRID_FLAG select hybrid mode (must set bitrate)
+// o CONFIG_JOINT_STEREO select joint stereo (must set override also)
+// o CONFIG_JOINT_OVERRIDE override default joint stereo selection
+// o CONFIG_HYBRID_SHAPE select hybrid noise shaping (set override &
+// shaping_weight != 0.0)
+// o CONFIG_SHAPE_OVERRIDE override default hybrid noise shaping
+// (set CONFIG_HYBRID_SHAPE and shaping_weight)
+// o CONFIG_FAST_FLAG "fast" compression mode
+// o CONFIG_HIGH_FLAG "high" compression mode
+// o CONFIG_BITRATE_KBPS hybrid bitrate is kbps, not bits / sample
+
+// config->bitrate hybrid bitrate in either bits/sample or kbps
+// config->shaping_weight hybrid noise shaping coefficient override
+// config->float_norm_exp select floating-point data (127 for +/-1.0)
+
+// If the number of samples to be written is known then it should be passed
+// here. If the duration is not known then pass -1. In the case that the size
+// is not known (or the writing is terminated early) then it is suggested that
+// the application retrieve the first block written and let the library update
+// the total samples indication. A function is provided to do this update and
+// it should be done to the "correction" file also. If this cannot be done
+// (because a pipe is being used, for instance) then a valid WavPack will still
+// be created, but when applications want to access that file they will have
+// to seek all the way to the end to determine the actual duration. Also, if
+// a RIFF header has been included then it should be updated as well or the
+// WavPack file will not be directly unpackable to a valid wav file (although
+// it will still be usable by itself). A return of FALSE indicates an error.
+
+int WavpackSetConfiguration (WavpackContext *wpc, WavpackConfig *config, ulong total_samples)
+{
+ WavpackStream *wps = &wpc->stream;
+ ulong flags = (config->bytes_per_sample - 1), shift = 0;
+ int num_chans = config->num_channels;
+ int i;
+
+ if ((wpc->config.flags & CONFIG_HYBRID_FLAG) ||
+ wpc->config.float_norm_exp ||
+ num_chans < 1 || num_chans > 2)
+ return FALSE;
+
+ wpc->total_samples = total_samples;
+ wpc->config.sample_rate = config->sample_rate;
+ wpc->config.num_channels = config->num_channels;
+ wpc->config.bits_per_sample = config->bits_per_sample;
+ wpc->config.bytes_per_sample = config->bytes_per_sample;
+ wpc->config.flags = config->flags;
+
+ shift = (config->bytes_per_sample * 8) - config->bits_per_sample;
+
+ for (i = 0; i < 15; ++i)
+ if (wpc->config.sample_rate == sample_rates [i])
+ break;
+
+ flags |= i << SRATE_LSB;
+ flags |= shift << SHIFT_LSB;
+ flags |= CROSS_DECORR;
+
+ if (!(config->flags & CONFIG_JOINT_OVERRIDE) || (config->flags & CONFIG_JOINT_STEREO))
+ flags |= JOINT_STEREO;
+
+ memcpy (wps->wphdr.ckID, "wvpk", 4);
+ wps->wphdr.ckSize = sizeof (WavpackHeader) - 8;
+ wps->wphdr.total_samples = wpc->total_samples;
+ wps->wphdr.version = 0x403;
+ wps->wphdr.flags = flags;
+
+ wps->wphdr.flags |= INITIAL_BLOCK;
+ wps->wphdr.flags |= FINAL_BLOCK;
+
+ if (num_chans == 1) {
+ wps->wphdr.flags &= ~(JOINT_STEREO | CROSS_DECORR | HYBRID_BALANCE);
+ wps->wphdr.flags |= MONO_FLAG;
+ }
+
+ pack_init (wpc);
+ return TRUE;
+}
+
+// Add wrapper (currently RIFF only) to WavPack blocks. This should be called
+// before sending any audio samples for the RIFF header or after all samples
+// have been sent for any RIFF trailer. WavpackFlushSamples() should be called
+// between sending the last samples and calling this for trailer data to make
+// sure that headers and trailers don't get mixed up in very short files. If
+// the exact contents of the RIFF header are not known because, for example,
+// the file duration is uncertain or trailing chunks are possible, simply write
+// a "dummy" header of the correct length. When all data has been written it
+// will be possible to read the first block written and update the header
+// directly. An example of this can be found in the Audition filter. A
+// return of FALSE indicates an error.
+
+void WavpackAddWrapper (WavpackContext *wpc, void *data, ulong bcount)
+{
+ wpc->wrapper_data = data;
+ wpc->wrapper_bytes = bcount;
+}
+
+// Pack the specified samples. Samples must be stored in longs in the native
+// endian format of the executing processor. The number of samples specified
+// indicates composite samples (sometimes called "frames"). So, the actual
+// number of data points would be this "sample_count" times the number of
+// channels. Note that samples are accumulated here until enough exist to
+// create a complete WavPack block (or several blocks for multichannel audio).
+// If an application wants to break a block at a specific sample, then it must
+// simply call WavpackFlushSamples() to force an early termination. Completed
+// WavPack blocks are send to the function provided in the initial call to
+// WavpackOpenFileOutput(). A return of FALSE indicates an error.
+
+ulong WavpackPackSamples (WavpackContext *wpc, long *sample_buffer, ulong sample_count)
+{
+ WavpackStream *wps = &wpc->stream;
+ ulong flags = wps->wphdr.flags;
+ ulong bcount;
+ int result;
+
+ flags &= ~MAG_MASK;
+ flags += (1 << MAG_LSB) * ((flags & BYTES_STORED) * 8 + 7);
+
+ wps->wphdr.block_index = wps->sample_index;
+ wps->wphdr.block_samples = sample_count;
+ wps->wphdr.flags = flags;
+
+ result = pack_block (wpc, sample_buffer);
+
+ if (!result) {
+ strcpy_loc (wpc->error_message, "output buffer overflowed!");
+ return 0;
+ }
+
+ bcount = ((WavpackHeader *) wps->blockbuff)->ckSize + 8;
+ native_to_little_endian ((WavpackHeader *) wps->blockbuff, WavpackHeaderFormat);
+
+ return bcount;
+}
+
+// Given the pointer to the first block written (to either a .wv or .wvc file),
+// update the block with the actual number of samples written. This should
+// be done if WavpackSetConfiguration() was called with an incorrect number
+// of samples (or -1). It is the responsibility of the application to read and
+// rewrite the block. An example of this can be found in the Audition filter.
+
+void WavpackUpdateNumSamples (WavpackContext *wpc, void *first_block)
+{
+ little_endian_to_native (wpc, WavpackHeaderFormat);
+ ((WavpackHeader *) first_block)->total_samples = WavpackGetSampleIndex (wpc);
+ native_to_little_endian (wpc, WavpackHeaderFormat);
+}
+
+// Given the pointer to the first block written to a WavPack file, this
+// function returns the location of the stored RIFF header that was originally
+// written with WavpackAddWrapper(). This would normally be used to update
+// the wav header to indicate that a different number of samples was actually
+// written or if additional RIFF chunks are written at the end of the file.
+// It is the responsibility of the application to read and rewrite the block.
+// An example of this can be found in the Audition filter.
+
+void *WavpackGetWrapperLocation (void *first_block)
+{
+ if (((uchar *) first_block) [32] == ID_RIFF_HEADER)
+ return ((uchar *) first_block) + 34;
+ else
+ return NULL;
+}
+