summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThom Johansen <thomj@rockbox.org>2005-06-09 09:26:05 +0000
committerThom Johansen <thomj@rockbox.org>2005-06-09 09:26:05 +0000
commit614f0a333a6263def7e6cd053abfc222dae2ced5 (patch)
tree85661bc01ed5dd0f5d4d79ac0a86ea78c0d38c1b
parent3ca164549624cc3a107d326a759e40456cedfc21 (diff)
WavPack optimisation by David Bryant.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@6635 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/codecs/libwavpack/wavpack.h21
-rw-r--r--apps/codecs/libwavpack/words.c91
2 files changed, 59 insertions, 53 deletions
diff --git a/apps/codecs/libwavpack/wavpack.h b/apps/codecs/libwavpack/wavpack.h
index 06f86cb15a..3aee4718b1 100644
--- a/apps/codecs/libwavpack/wavpack.h
+++ b/apps/codecs/libwavpack/wavpack.h
@@ -187,24 +187,29 @@ struct decorr_pass {
long samples_A [MAX_TERM], samples_B [MAX_TERM];
};
+struct entropy_data {
+ ulong median [3], slow_level, error_limit;
+};
+
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;
int num_terms, mute_error;
ulong sample_index, crc;
- Bitstream wvbits;
uchar int32_sent_bits, int32_zeros, int32_ones, int32_dups;
uchar float_flags, float_shift, float_max_exp, float_norm_exp;
struct decorr_pass decorr_passes [MAX_NTERMS];
- struct {
- ulong bitrate_delta [2], bitrate_acc [2];
- ulong median [3] [2], slow_level [2], error_limit [2];
- ulong pend_data, holding_one, zeros_acc;
- int holding_zero, pend_count;
- } w;
} WavpackStream;
// flags for float_flags:
@@ -223,8 +228,8 @@ typedef struct {
// and the provided utilities used instead.
typedef struct {
- WavpackConfig config;
WavpackStream stream;
+ WavpackConfig config;
uchar read_buffer [1024];
char error_message [80];
diff --git a/apps/codecs/libwavpack/words.c b/apps/codecs/libwavpack/words.c
index 370c0d4857..8e2fc427a6 100644
--- a/apps/codecs/libwavpack/words.c
+++ b/apps/codecs/libwavpack/words.c
@@ -42,19 +42,19 @@
#define DIV2 32 // 20/343 of samples
// this macro retrieves the specified median breakpoint (without frac; min = 1)
-#define GET_MED(med) (((wps->w.median [med] [chan]) >> 4) + 1)
+#define GET_MED(med) (((c->median [med]) >> 4) + 1)
// These macros update the specified median breakpoints. Note that the median
// is incremented when the sample is higher than the median, else decremented.
// They are designed so that the median will never drop below 1 and the value
// is essentially stationary if there are 2 increments for every 5 decrements.
-#define INC_MED0() (wps->w.median [0] [chan] += ((wps->w.median [0] [chan] + DIV0) / DIV0) * 5)
-#define DEC_MED0() (wps->w.median [0] [chan] -= ((wps->w.median [0] [chan] + (DIV0-2)) / DIV0) * 2)
-#define INC_MED1() (wps->w.median [1] [chan] += ((wps->w.median [1] [chan] + DIV1) / DIV1) * 5)
-#define DEC_MED1() (wps->w.median [1] [chan] -= ((wps->w.median [1] [chan] + (DIV1-2)) / DIV1) * 2)
-#define INC_MED2() (wps->w.median [2] [chan] += ((wps->w.median [2] [chan] + DIV2) / DIV2) * 5)
-#define DEC_MED2() (wps->w.median [2] [chan] -= ((wps->w.median [2] [chan] + (DIV2-2)) / DIV2) * 2)
+#define INC_MED0() (c->median [0] += ((c->median [0] + DIV0) / DIV0) * 5)
+#define DEC_MED0() (c->median [0] -= ((c->median [0] + (DIV0-2)) / DIV0) * 2)
+#define INC_MED1() (c->median [1] += ((c->median [1] + DIV1) / DIV1) * 5)
+#define DEC_MED1() (c->median [1] -= ((c->median [1] + (DIV1-2)) / DIV1) * 2)
+#define INC_MED2() (c->median [2] += ((c->median [2] + DIV2) / DIV2) * 5)
+#define DEC_MED2() (c->median [2] -= ((c->median [2] + (DIV2-2)) / DIV2) * 2)
#define count_bits(av) ( \
(av) < (1 << 8) ? nbits_table [av] : \
@@ -149,14 +149,14 @@ int read_entropy_vars (WavpackStream *wps, WavpackMetadata *wpmd)
if (wpmd->byte_length != ((wps->wphdr.flags & MONO_FLAG) ? 6 : 12))
return FALSE;
- wps->w.median [0] [0] = exp2s (byteptr [0] + (byteptr [1] << 8));
- wps->w.median [1] [0] = exp2s (byteptr [2] + (byteptr [3] << 8));
- wps->w.median [2] [0] = exp2s (byteptr [4] + (byteptr [5] << 8));
+ 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.median [0] [1] = exp2s (byteptr [6] + (byteptr [7] << 8));
- wps->w.median [1] [1] = exp2s (byteptr [8] + (byteptr [9] << 8));
- wps->w.median [2] [1] = 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;
@@ -173,11 +173,11 @@ int read_hybrid_profile (WavpackStream *wps, WavpackMetadata *wpmd)
uchar *endptr = byteptr + wpmd->byte_length;
if (wps->wphdr.flags & HYBRID_BITRATE) {
- wps->w.slow_level [0] = exp2s (byteptr [0] + (byteptr [1] << 8));
+ wps->w.c [0].slow_level = exp2s (byteptr [0] + (byteptr [1] << 8));
byteptr += 2;
if (!(wps->wphdr.flags & MONO_FLAG)) {
- wps->w.slow_level [1] = exp2s (byteptr [0] + (byteptr [1] << 8));
+ wps->w.c [1].slow_level = exp2s (byteptr [0] + (byteptr [1] << 8));
byteptr += 2;
}
}
@@ -220,22 +220,22 @@ static void update_error_limit (WavpackStream *wps)
if (wps->wphdr.flags & MONO_FLAG) {
if (wps->wphdr.flags & HYBRID_BITRATE) {
- int slow_log_0 = (wps->w.slow_level [0] + SLO) >> SLS;
+ int slow_log_0 = (wps->w.c [0].slow_level + SLO) >> SLS;
if (slow_log_0 - bitrate_0 > -0x100)
- wps->w.error_limit [0] = exp2s (slow_log_0 - bitrate_0 + 0x100);
+ wps->w.c [0].error_limit = exp2s (slow_log_0 - bitrate_0 + 0x100);
else
- wps->w.error_limit [0] = 0;
+ wps->w.c [0].error_limit = 0;
}
else
- wps->w.error_limit [0] = exp2s (bitrate_0);
+ wps->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.slow_level [0] + SLO) >> SLS;
- int slow_log_1 = (wps->w.slow_level [1] + SLO) >> SLS;
+ 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;
@@ -255,18 +255,18 @@ static void update_error_limit (WavpackStream *wps)
}
if (slow_log_0 - bitrate_0 > -0x100)
- wps->w.error_limit [0] = exp2s (slow_log_0 - bitrate_0 + 0x100);
+ wps->w.c [0].error_limit = exp2s (slow_log_0 - bitrate_0 + 0x100);
else
- wps->w.error_limit [0] = 0;
+ wps->w.c [0].error_limit = 0;
if (slow_log_1 - bitrate_1 > -0x100)
- wps->w.error_limit [1] = exp2s (slow_log_1 - bitrate_1 + 0x100);
+ wps->w.c [1].error_limit = exp2s (slow_log_1 - bitrate_1 + 0x100);
else
- wps->w.error_limit [1] = 0;
+ wps->w.c [1].error_limit = 0;
}
else {
- wps->w.error_limit [0] = exp2s (bitrate_0);
- wps->w.error_limit [1] = exp2s (bitrate_1);
+ wps->w.c [0].error_limit = exp2s (bitrate_0);
+ wps->w.c [1].error_limit = exp2s (bitrate_1);
}
}
}
@@ -283,21 +283,23 @@ static ulong read_code (Bitstream *bs, ulong maxcode);
long get_words (WavpackStream *wps, int nchans, int nsamples, long *buffer)
{
- ulong tsamples = nsamples * nchans, ones_count, low, mid, high;
- int next8, sign, chan;
+ ulong ones_count, low, mid, high;
+ register struct entropy_data *c;
long *bptr = buffer;
- while (tsamples--) {
+ nsamples *= nchans;
- chan = (nchans == 1) ? 0 : (~tsamples & 1);
+ while (nsamples--) {
- if (!(wps->w.median [0] [0] & ~1) && !wps->w.holding_zero && !wps->w.holding_one && !(wps->w.median [0] [1] & ~1)) {
+ 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) {
- wps->w.slow_level [chan] -= (wps->w.slow_level [chan] + SLO) >> SLS;
+ c->slow_level -= (c->slow_level + SLO) >> SLS;
*bptr++ = 0;
continue;
}
@@ -319,8 +321,9 @@ long get_words (WavpackStream *wps, int nchans, int nsamples, long *buffer)
}
if (wps->w.zeros_acc) {
- wps->w.slow_level [chan] -= (wps->w.slow_level [chan] + SLO) >> SLS;
- CLEAR (wps->w.median);
+ c->slow_level -= (c->slow_level + SLO) >> SLS;
+ CLEAR (wps->w.c [0].median);
+ CLEAR (wps->w.c [1].median);
*bptr++ = 0;
continue;
}
@@ -330,6 +333,8 @@ long get_words (WavpackStream *wps, int nchans, int nsamples, long *buffer)
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);
@@ -388,7 +393,7 @@ long get_words (WavpackStream *wps, int nchans, int nsamples, long *buffer)
wps->w.holding_zero = ~wps->w.holding_one & 1;
}
- if ((wps->wphdr.flags & HYBRID_FLAG) && !chan)
+ if ((wps->wphdr.flags & HYBRID_FLAG) && (nchans == 1 || (nsamples & 1)))
update_error_limit (wps);
if (ones_count == 0) {
@@ -422,23 +427,19 @@ long get_words (WavpackStream *wps, int nchans, int nsamples, long *buffer)
mid = (high + low + 1) >> 1;
- if (!wps->w.error_limit [chan])
+ if (!c->error_limit)
mid = read_code (&wps->wvbits, high - low) + low;
- else while (high - low > wps->w.error_limit [chan]) {
+ 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;
}
- sign = getbit (&wps->wvbits);
-
- if (wps->wphdr.flags & HYBRID_BITRATE) {
- wps->w.slow_level [chan] -= (wps->w.slow_level [chan] + SLO) >> SLS;
- wps->w.slow_level [chan] += mylog2 (mid);
- }
+ *bptr++ = getbit (&wps->wvbits) ? ~mid : mid;
- *bptr++ = sign ? ~mid : mid;
+ if (wps->wphdr.flags & HYBRID_BITRATE)
+ c->slow_level = c->slow_level - ((c->slow_level + SLO) >> SLS) + mylog2 (mid);
}
return nchans == 1 ? (bptr - buffer) : ((bptr - buffer) / 2);