summaryrefslogtreecommitdiff
path: root/apps/codecs
diff options
context:
space:
mode:
Diffstat (limited to 'apps/codecs')
-rw-r--r--apps/codecs/libwavpack/pack.c270
-rw-r--r--apps/codecs/libwavpack/wavpack.h20
-rw-r--r--apps/codecs/libwavpack/words.c256
-rw-r--r--apps/codecs/libwavpack/wputils.c98
4 files changed, 322 insertions, 322 deletions
diff --git a/apps/codecs/libwavpack/pack.c b/apps/codecs/libwavpack/pack.c
index e695388..ef5feca 100644
--- a/apps/codecs/libwavpack/pack.c
+++ b/apps/codecs/libwavpack/pack.c
@@ -28,7 +28,7 @@
// 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 high_terms [] = { 18,18,2,3,-2,18,2,4,7,5,3,6,0 };
static const char fast_terms [] = { 17,17,0 };
///////////////////////////// executable code ////////////////////////////////
@@ -205,56 +205,6 @@ static void write_config_info (WavpackContext *wpc, WavpackMetadata *wpmd)
}
// 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.
@@ -265,21 +215,18 @@ int pack_block (WavpackContext *wpc, long *buffer)
// 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)
+int pack_start_block (WavpackContext *wpc)
{
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));
+ ((WavpackHeader *) wps->blockbuff)->ckSize = sizeof (WavpackHeader) - 8;
+ ((WavpackHeader *) wps->blockbuff)->block_index = wps->sample_index;
+ ((WavpackHeader *) wps->blockbuff)->block_samples = 0;
+ ((WavpackHeader *) wps->blockbuff)->crc = 0xffffffff;
+
if (wpc->wrapper_bytes) {
wpmd.id = ID_RIFF_HEADER;
wpmd.byte_length = wpc->wrapper_bytes;
@@ -290,9 +237,6 @@ static int pack_samples (WavpackContext *wpc, long *buffer)
wpc->wrapper_bytes = 0;
}
- if (!sample_count)
- return TRUE;
-
write_decorr_terms (wps, &wpmd);
copy_metadata (&wpmd, wps->blockbuff, wps->blockend);
free_metadata (&wpmd);
@@ -309,7 +253,7 @@ static int pack_samples (WavpackContext *wpc, long *buffer)
copy_metadata (&wpmd, wps->blockbuff, wps->blockend);
free_metadata (&wpmd);
- if ((flags & INITIAL_BLOCK) && !wps->sample_index) {
+ if ((wps->wphdr.flags & INITIAL_BLOCK) && !wps->sample_index) {
write_config_info (wpc, &wpmd);
copy_metadata (&wpmd, wps->blockbuff, wps->blockend);
free_metadata (&wpmd);
@@ -317,13 +261,37 @@ static int pack_samples (WavpackContext *wpc, long *buffer)
bs_open_write (&wps->wvbits, wps->blockbuff + ((WavpackHeader *) wps->blockbuff)->ckSize + 12, wps->blockend);
+ return TRUE;
+}
+
+static void decorr_stereo_pass (struct decorr_pass *dpp, long *bptr, long *eptr, int m);
+static void decorr_stereo_pass_18 (struct decorr_pass *dpp, long *bptr, long *eptr);
+static void decorr_stereo_pass_17 (struct decorr_pass *dpp, long *bptr, long *eptr);
+static void decorr_stereo_pass_m2 (struct decorr_pass *dpp, long *bptr, long *eptr);
+
+int pack_samples (WavpackContext *wpc, long *buffer, ulong sample_count)
+{
+ WavpackStream *wps = &wpc->stream;
+ ulong flags = wps->wphdr.flags;
+ struct decorr_pass *dpp;
+ long *bptr, *eptr;
+ int tcount, m;
+ ulong crc;
+
+ if (!sample_count)
+ return TRUE;
+
+ eptr = buffer + sample_count * ((flags & MONO_FLAG) ? 1 : 2);
+ m = ((WavpackHeader *) wps->blockbuff)->block_samples & (MAX_TERM - 1);
+ crc = ((WavpackHeader *) wps->blockbuff)->crc;
+
/////////////////////// handle lossless mono mode /////////////////////////
if (!(flags & HYBRID_FLAG) && (flags & MONO_FLAG))
- for (bptr = buffer, i = 0; i < sample_count; ++i) {
+ for (bptr = buffer; bptr < eptr;) {
long code;
- crc = crc * 3 + (code = *bptr++);
+ crc = crc * 3 + (code = *bptr);
for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++) {
long sam;
@@ -347,68 +315,123 @@ static int pack_samples (WavpackContext *wpc, long *buffer)
}
m = (m + 1) & (MAX_TERM - 1);
- send_word_lossless (wps, code, 0);
+ *bptr++ = code;
}
//////////////////// 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);
+ else if (!(flags & HYBRID_FLAG) && !(flags & MONO_FLAG)) {
+ if (flags & JOINT_STEREO)
+ for (bptr = buffer; bptr < eptr; bptr += 2) {
+ crc = crc * 9 + (bptr [0] * 3) + bptr [1];
+ bptr [1] += ((bptr [0] -= bptr [1]) >> 1);
+ }
+ else
+ for (bptr = buffer; bptr < eptr; bptr += 2)
+ crc = crc * 9 + (bptr [0] * 3) + bptr [1];
+
+ for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount-- ; dpp++) {
+ if (dpp->term == 17)
+ decorr_stereo_pass_17 (dpp, buffer, eptr);
+ else if (dpp->term == 18)
+ decorr_stereo_pass_18 (dpp, buffer, eptr);
+ else if (dpp->term >= 1 && dpp->term <= 7)
+ decorr_stereo_pass (dpp, buffer, eptr, m);
+ else if (dpp->term == -2)
+ decorr_stereo_pass_m2 (dpp, buffer, eptr);
+ }
+ }
- sam_A = dpp->samples_A [m];
- sam_B = dpp->samples_B [m];
- dpp->samples_A [k] = left;
- dpp->samples_B [k] = right;
- }
+ send_words (buffer, sample_count, flags, &wps->w, &wps->wvbits);
+ ((WavpackHeader *) wps->blockbuff)->crc = crc;
+ ((WavpackHeader *) wps->blockbuff)->block_samples += sample_count;
+ wps->sample_index += sample_count;
- 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);
- }
- }
+ return TRUE;
+}
- m = (m + 1) & (MAX_TERM - 1);
- send_word_lossless (wps, left, 0);
- send_word_lossless (wps, right, 1);
- }
+static void decorr_stereo_pass (struct decorr_pass *dpp, long *bptr, long *eptr, int m)
+{
+ int k = (m + dpp->term) & (MAX_TERM - 1);
+ long sam;
+
+ while (bptr < eptr) {
+ dpp->samples_A [k] = bptr [0];
+ bptr [0] -= apply_weight_i (dpp->weight_A, (sam = dpp->samples_A [m]));
+ update_weight (dpp->weight_A, 2, sam, bptr [0]);
+ bptr++;
+ dpp->samples_B [k] = bptr [0];
+ bptr [0] -= apply_weight_i (dpp->weight_B, (sam = dpp->samples_B [m]));
+ update_weight (dpp->weight_B, 2, sam, bptr [0]);
+ bptr++;
+ m = (m + 1) & (MAX_TERM - 1);
+ k = (k + 1) & (MAX_TERM - 1);
+ }
+}
+
+static void decorr_stereo_pass_18 (struct decorr_pass *dpp, long *bptr, long *eptr)
+{
+ long sam;
+
+ while (bptr < eptr) {
+ sam = (3 * dpp->samples_A [0] - dpp->samples_A [1]) >> 1;
+ dpp->samples_A [1] = dpp->samples_A [0];
+ dpp->samples_A [0] = bptr [0];
+ bptr [0] -= apply_weight_i (dpp->weight_A, sam);
+ update_weight (dpp->weight_A, 2, sam, bptr [0]);
+ bptr++;
+ sam = (3 * dpp->samples_B [0] - dpp->samples_B [1]) >> 1;
+ dpp->samples_B [1] = dpp->samples_B [0];
+ dpp->samples_B [0] = bptr [0];
+ bptr [0] -= apply_weight_i (dpp->weight_B, sam);
+ update_weight (dpp->weight_B, 2, sam, bptr [0]);
+ bptr++;
+ }
+}
+
+static void decorr_stereo_pass_m2 (struct decorr_pass *dpp, long *bptr, long *eptr)
+{
+ long sam_A, sam_B;
+
+ for (; bptr < eptr; bptr += 2) {
+ sam_A = bptr [1];
+ sam_B = dpp->samples_B [0];
+ dpp->samples_B [0] = bptr [0];
+ bptr [0] -= apply_weight_i (dpp->weight_A, sam_A);
+ update_weight_clip (dpp->weight_A, 2, sam_A, bptr [0]);
+ bptr [1] -= apply_weight_i (dpp->weight_B, sam_B);
+ update_weight_clip (dpp->weight_B, 2, sam_B, bptr [1]);
+ }
+}
+
+static void decorr_stereo_pass_17 (struct decorr_pass *dpp, long *bptr, long *eptr)
+{
+ long sam;
+
+ while (bptr < eptr) {
+ sam = 2 * dpp->samples_A [0] - dpp->samples_A [1];
+ dpp->samples_A [1] = dpp->samples_A [0];
+ dpp->samples_A [0] = bptr [0];
+ bptr [0] -= apply_weight_i (dpp->weight_A, sam);
+ update_weight (dpp->weight_A, 2, sam, bptr [0]);
+ bptr++;
+ sam = 2 * dpp->samples_B [0] - dpp->samples_B [1];
+ dpp->samples_B [1] = dpp->samples_B [0];
+ dpp->samples_B [0] = bptr [0];
+ bptr [0] -= apply_weight_i (dpp->weight_B, sam);
+ update_weight (dpp->weight_B, 2, sam, bptr [0]);
+ bptr++;
+ }
+}
+
+int pack_finish_block (WavpackContext *wpc)
+{
+ WavpackStream *wps = &wpc->stream;
+ struct decorr_pass *dpp;
+ ulong data_count;
+ int tcount, m;
+
+ m = ((WavpackHeader *) wps->blockbuff)->block_samples & (MAX_TERM - 1);
if (m)
for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++)
@@ -426,7 +449,7 @@ static int pack_samples (WavpackContext *wpc, long *buffer)
}
}
- flush_word (wps);
+ flush_word (&wps->w, &wps->wvbits);
data_count = bs_close_write (&wps->wvbits);
if (data_count) {
@@ -443,8 +466,5 @@ static int pack_samples (WavpackContext *wpc, long *buffer)
return FALSE;
}
- ((WavpackHeader *) wps->blockbuff)->crc = crc;
-
- wps->sample_index += sample_count;
return TRUE;
}
diff --git a/apps/codecs/libwavpack/wavpack.h b/apps/codecs/libwavpack/wavpack.h
index 12212bb..bf9b954 100644
--- a/apps/codecs/libwavpack/wavpack.h
+++ b/apps/codecs/libwavpack/wavpack.h
@@ -234,10 +234,6 @@ typedef struct {
WavpackStream stream;
WavpackConfig config;
- WavpackMetadata *metadata;
- ulong metabytes;
- int metacount;
-
uchar *wrapper_data;
int wrapper_bytes;
@@ -364,7 +360,9 @@ int check_crc_error (WavpackContext *wpc);
// pack.c
void pack_init (WavpackContext *wpc);
-int pack_block (WavpackContext *wpc, long *buffer);
+int pack_start_block (WavpackContext *wpc);
+int pack_samples (WavpackContext *wpc, long *buffer, ulong sample_count);
+int pack_finish_block (WavpackContext *wpc);
// metadata.c stuff
@@ -381,8 +379,11 @@ void write_entropy_vars (WavpackStream *wps, WavpackMetadata *wpmd);
int read_hybrid_profile (WavpackStream *wps, WavpackMetadata *wpmd);
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);
+void send_word_lossless (long value, int chan,
+ struct words_data *w, Bitstream *bs);
+void send_words (long *buffer, int nsamples, ulong flags,
+ struct words_data *w, Bitstream *bs);
+void flush_word (struct words_data *w, Bitstream *bs);
int log2s (long value);
long exp2s (int log);
char store_weight (int weight);
@@ -421,9 +422,10 @@ 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);
+int WavpackStartBlock (WavpackContext *wpc, uchar *begin, uchar *end);
+int WavpackPackSamples (WavpackContext *wpc, long *sample_buffer, ulong sample_count);
+ulong WavpackFinishBlock (WavpackContext *wpc);
diff --git a/apps/codecs/libwavpack/words.c b/apps/codecs/libwavpack/words.c
index 75d8a86..d46bb56 100644
--- a/apps/codecs/libwavpack/words.c
+++ b/apps/codecs/libwavpack/words.c
@@ -66,28 +66,6 @@
///////////////////////////// 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
@@ -536,177 +514,183 @@ static ulong read_code (Bitstream *bs, ulong maxcode)
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)
+void send_words (long *buffer, int nsamples, ulong flags,
+ struct words_data *w, Bitstream *bs)
{
- 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);
+ register struct entropy_data *c = w->c;
+
+ if (!(flags & MONO_FLAG))
+ nsamples *= 2;
+
+ while (nsamples--) {
+ long value = *buffer++;
+ int sign = (value < 0) ? 1 : 0;
+ ulong ones_count, low, high;
+
+ if (!(flags & MONO_FLAG))
+ c = w->c + (~nsamples & 1);
+
+ if (!(w->c [0].median [0] & ~1) && !w->holding_zero && !(w->c [1].median [0] & ~1)) {
+ if (w->zeros_acc) {
+ if (value)
+ flush_word (w, bs);
+ else {
+ w->zeros_acc++;
+ continue;
+ }
+ }
+ else if (value) {
+ putbit_0 (bs);
+ }
else {
- wps->w.zeros_acc++;
- return;
+ CLEAR (w->c [0].median);
+ CLEAR (w->c [1].median);
+ w->zeros_acc = 1;
+ continue;
}
}
- 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 (sign)
+ value = ~value;
- if (value - low < GET_MED (1)) {
- ones_count = 1;
- high = low + GET_MED (1) - 1;
- DEC_MED1 ();
+ if ((unsigned long) value < GET_MED (0)) {
+ ones_count = low = 0;
+ high = GET_MED (0) - 1;
+ DEC_MED0 ();
}
else {
- low += GET_MED (1);
- INC_MED1 ();
+ low = GET_MED (0);
+ INC_MED0 ();
- if (value - low < GET_MED (2)) {
- ones_count = 2;
- high = low + GET_MED (2) - 1;
- DEC_MED2 ();
+ if (value - low < GET_MED (1)) {
+ ones_count = 1;
+ high = low + GET_MED (1) - 1;
+ DEC_MED1 ();
}
else {
- ones_count = 2 + (value - low) / GET_MED (2);
- low += (ones_count - 2) * GET_MED (2);
- high = low + GET_MED (2) - 1;
- INC_MED2 ();
+ 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++;
+ if (w->holding_zero) {
+ if (ones_count)
+ w->holding_one++;
- flush_word (wps);
+ flush_word (w, bs);
- if (ones_count) {
- wps->w.holding_zero = 1;
- ones_count--;
+ if (ones_count) {
+ w->holding_zero = 1;
+ ones_count--;
+ }
+ else
+ w->holding_zero = 0;
}
else
- wps->w.holding_zero = 0;
- }
- else
- wps->w.holding_zero = 1;
+ w->holding_zero = 1;
- wps->w.holding_one = ones_count * 2;
+ 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 (high != low) {
+ ulong maxcode = high - low, code = value - low;
+ int bitcount = count_bits (maxcode);
+ ulong extras = (1L << 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++;
+ if (code < extras) {
+ w->pend_data |= code << w->pend_count;
+ w->pend_count += bitcount - 1;
+ }
+ else {
+ w->pend_data |= ((code + extras) >> 1) << w->pend_count;
+ w->pend_count += bitcount - 1;
+ w->pend_data |= ((code + extras) & 1) << w->pend_count++;
+ }
}
- }
- wps->w.pend_data |= ((long) sign << wps->w.pend_count++);
+ w->pend_data |= ((long) sign << w->pend_count++);
- if (!wps->w.holding_zero)
- flush_word (wps);
+ if (!w->holding_zero)
+ flush_word (w, bs);
+ }
}
// 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)
+void flush_word (struct words_data *w, Bitstream *bs)
{
- if (wps->w.zeros_acc) {
- int cbits = count_bits (wps->w.zeros_acc);
+ int cbits;
+
+ if (w->zeros_acc) {
+ cbits = count_bits (w->zeros_acc);
while (cbits--) {
- putbit_1 (&wps->wvbits);
+ putbit_1 (bs);
}
- putbit_0 (&wps->wvbits);
+ putbit_0 (bs);
- while (wps->w.zeros_acc > 1) {
- putbit (wps->w.zeros_acc & 1, &wps->wvbits);
- wps->w.zeros_acc >>= 1;
+ while (w->zeros_acc > 1) {
+ putbit (w->zeros_acc & 1, bs);
+ w->zeros_acc >>= 1;
}
- wps->w.zeros_acc = 0;
+ 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);
+ if (w->holding_one) {
+ if (w->holding_one >= LIMIT_ONES) {
+ putbits ((1L << LIMIT_ONES) - 1, LIMIT_ONES + 1, bs);
+ w->holding_one -= LIMIT_ONES;
+ cbits = count_bits (w->holding_one);
while (cbits--) {
- putbit_1 (&wps->wvbits);
+ putbit_1 (bs);
}
- putbit_0 (&wps->wvbits);
+ putbit_0 (bs);
- while (wps->w.holding_one > 1) {
- putbit (wps->w.holding_one & 1, &wps->wvbits);
- wps->w.holding_one >>= 1;
+ while (w->holding_one > 1) {
+ putbit (w->holding_one & 1, bs);
+ w->holding_one >>= 1;
}
- wps->w.holding_zero = 0;
+ w->holding_zero = 0;
}
else
- putbits (bitmask [wps->w.holding_one], wps->w.holding_one, &wps->wvbits);
+ putbits ((1L << w->holding_one) - 1, w->holding_one, bs);
- wps->w.holding_one = 0;
+ w->holding_one = 0;
}
- if (wps->w.holding_zero) {
- putbit_0 (&wps->wvbits);
- wps->w.holding_zero = 0;
+ if (w->holding_zero) {
+ putbit_0 (bs);
+ w->holding_zero = 0;
}
- if (wps->w.pend_count) {
+ if (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--;
+ while (w->pend_count > 24) {
+ putbit (w->pend_data & 1, bs);
+ w->pend_data >>= 1;
+ w->pend_count--;
}
- putbits (wps->w.pend_data, wps->w.pend_count, &wps->wvbits);
- wps->w.pend_data = wps->w.pend_count = 0;
+ putbits (w->pend_data, w->pend_count, bs);
+ w->pend_data = w->pend_count = 0;
}
}
diff --git a/apps/codecs/libwavpack/wputils.c b/apps/codecs/libwavpack/wputils.c
index 7f2ab14..479c180 100644
--- a/apps/codecs/libwavpack/wputils.c
+++ b/apps/codecs/libwavpack/wputils.c
@@ -365,17 +365,6 @@ WavpackContext *WavpackOpenFileOutput (void)
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
@@ -450,35 +439,33 @@ int WavpackSetConfiguration (WavpackContext *wpc, WavpackConfig *config, ulong t
if (!(config->flags & CONFIG_JOINT_OVERRIDE) || (config->flags & CONFIG_JOINT_STEREO))
flags |= JOINT_STEREO;
+ flags |= INITIAL_BLOCK | FINAL_BLOCK;
+
+ if (num_chans == 1) {
+ flags &= ~(JOINT_STEREO | CROSS_DECORR | HYBRID_BALANCE);
+ flags |= MONO_FLAG;
+ }
+
+ flags &= ~MAG_MASK;
+ flags += (1 << MAG_LSB) * ((flags & BYTES_STORED) * 8 + 7);
+
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.
+// before sending any audio samples. 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.
void WavpackAddWrapper (WavpackContext *wpc, void *data, ulong bcount)
{
@@ -486,38 +473,45 @@ void WavpackAddWrapper (WavpackContext *wpc, void *data, ulong bcount)
wpc->wrapper_bytes = bcount;
}
+// Start a WavPack block to be stored in the specified buffer. This must be
+// called before calling WavpackPackSamples(). Note that writing CANNOT wrap
+// in the buffer; the entire output block must fit in the buffer.
+
+int WavpackStartBlock (WavpackContext *wpc, uchar *begin, uchar *end)
+{
+ wpc->stream.blockbuff = begin;
+ wpc->stream.blockend = end;
+ return pack_start_block (wpc);
+}
+
// 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;
+// channels. The caller must decide how many samples to place in each
+// WavPack block (1/2 second is common), but this function may be called as
+// many times as desired to build the final block (and performs the actual
+// compression during the call). A return of FALSE indicates an error.
- flags &= ~MAG_MASK;
- flags += (1 << MAG_LSB) * ((flags & BYTES_STORED) * 8 + 7);
+int WavpackPackSamples (WavpackContext *wpc, long *sample_buffer, ulong sample_count)
+{
+ if (!sample_count || pack_samples (wpc, sample_buffer, sample_count))
+ return TRUE;
- wps->wphdr.block_index = wps->sample_index;
- wps->wphdr.block_samples = sample_count;
- wps->wphdr.flags = flags;
+ strcpy_loc (wpc->error_message, "output buffer overflowed!");
+ return FALSE;
+}
- result = pack_block (wpc, sample_buffer);
+// Finish the WavPack block being built, returning the total size of the
+// block in bytes. Note that the possible conversion of the WavPack header to
+// little-endian takes place here.
- if (!result) {
- strcpy_loc (wpc->error_message, "output buffer overflowed!");
- return 0;
- }
+ulong WavpackFinishBlock (WavpackContext *wpc)
+{
+ WavpackStream *wps = &wpc->stream;
+ ulong bcount;
+ pack_finish_block (wpc);
bcount = ((WavpackHeader *) wps->blockbuff)->ckSize + 8;
native_to_little_endian ((WavpackHeader *) wps->blockbuff, WavpackHeaderFormat);