diff options
author | Dave Bryant <bryant@rockbox.org> | 2007-01-08 04:24:32 +0000 |
---|---|---|
committer | Dave Bryant <bryant@rockbox.org> | 2007-01-08 04:24:32 +0000 |
commit | 2446b22db971668f8d6ba5cb2361aabbda286da1 (patch) | |
tree | 3b9bcf9c273783a1ee0b273f7f56d72f92077754 | |
parent | 5693622cd4de1d3dff162295690ecb25d29a2937 (diff) |
Update libwavpack with latest changes from the tiny_encoder. This allows
playback of floating-point audio files, fixes a obscure decoding bug, and
improves encoding speed somewhat.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@11944 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | apps/codecs/libwavpack/float.c | 70 | ||||
-rw-r--r-- | apps/codecs/libwavpack/unpack.c | 4 | ||||
-rw-r--r-- | apps/codecs/libwavpack/wavpack.h | 41 | ||||
-rw-r--r-- | apps/metadata.c | 8 |
4 files changed, 43 insertions, 80 deletions
diff --git a/apps/codecs/libwavpack/float.c b/apps/codecs/libwavpack/float.c index 9d3a82c001..6e5c4e4f61 100644 --- a/apps/codecs/libwavpack/float.c +++ b/apps/codecs/libwavpack/float.c @@ -25,59 +25,23 @@ int read_float_info (WavpackStream *wps, WavpackMetadata *wpmd) return TRUE; } -void float_values (WavpackStream *wps, int32_t *values, int32_t num_values) -{ - while (num_values--) { - int shift_count = 0, exp = wps->float_max_exp; - f32 outval = { 0, 0, 0 }; - - if (*values) { - *values <<= wps->float_shift; - - if (*values < 0) { - *values = -*values; - outval.sign = 1; - } - - if (*values == 0x1000000) - 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; - } - } +/* This function converts WavPack floating point data into standard Rockbox + * 28-bit integers. It is assumed that clipping will be taken care of later. + */ - * (f32 *) values++ = outval; - } -} - -void float_normalize (int32_t *values, int32_t num_values, int delta_exp) +void float_values (WavpackStream *wps, int32_t *values, int32_t num_values) { - f32 *fvalues = (f32 *) values, fzero = { 0, 0, 0 }; - int exp; - - if (!delta_exp) - return; - - while (num_values--) { - if ((exp = fvalues->exponent) == 0 || exp + delta_exp <= 0) - *fvalues = fzero; - else if (exp == 255 || (exp += delta_exp) >= 255) { - fvalues->exponent = 255; - fvalues->mantissa = 0; - } - else - fvalues->exponent = exp; - - fvalues++; - } + int shift = wps->float_max_exp - wps->float_norm_exp + wps->float_shift + 5; + + if (shift > 32) + shift = 32; + else if (shift < -32) + shift = -32; + + if (shift > 0) + while (num_values--) + *values++ <<= shift; + else if (shift < 0) + while (num_values--) + *values++ >>= -shift; } diff --git a/apps/codecs/libwavpack/unpack.c b/apps/codecs/libwavpack/unpack.c index 5bb4467440..daf88718c8 100644 --- a/apps/codecs/libwavpack/unpack.c +++ b/apps/codecs/libwavpack/unpack.c @@ -393,10 +393,6 @@ int32_t unpack_samples (WavpackContext *wpc, int32_t *buffer, uint32_t sample_co fixup_samples (wps, buffer, i); - if (flags & FLOAT_DATA) - float_normalize (buffer, (flags & MONO_DATA) ? i : i * 2, - 127 - wps->float_norm_exp + wpc->norm_offset); - if (flags & FALSE_STEREO) { int32_t *dptr = buffer + i * 2; int32_t *sptr = buffer + i; diff --git a/apps/codecs/libwavpack/wavpack.h b/apps/codecs/libwavpack/wavpack.h index 3128328e49..a000438081 100644 --- a/apps/codecs/libwavpack/wavpack.h +++ b/apps/codecs/libwavpack/wavpack.h @@ -18,17 +18,6 @@ typedef unsigned char uchar; typedef unsigned short ushort; 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 -// allocate bit fields from the most significant bits, although I'm not sure -// how common that is. - -typedef struct { - unsigned mantissa : 23; - unsigned exponent : 8; - unsigned sign : 1; -} f32; - #include <stdio.h> #define FALSE 0 @@ -281,8 +270,14 @@ uint32_t bs_close_write (Bitstream *bs); (bs)->bc += 8; \ } \ *(value) = (bs)->sr; \ - (bs)->sr >>= (nbits); \ - (bs)->bc -= (nbits); \ + if ((bs)->bc > 32) { \ + (bs)->bc -= (nbits); \ + (bs)->sr = *((bs)->ptr) >> (8 - (bs)->bc); \ + } \ + else { \ + (bs)->bc -= (nbits); \ + (bs)->sr >>= (nbits); \ + } \ } #define putbit(bit, bs) { if (bit) (bs)->sr |= (1 << (bs)->bc); \ @@ -319,10 +314,15 @@ uint32_t bs_close_write (Bitstream *bs); 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 +// These macros implement the weight application and update operations +// that are at the heart of the decorrelation loops. Note that when there +// are several alternative versions of the same macro (marked with PERFCOND) +// then the versions are functionally equivalent with respect to WavPack +// decoding and the user should choose the one that provides the best +// performance. This may be easier to check when NOT using the assembly +// language optimizations. -#if 0 // PERFCOND +#if 1 // PERFCOND #define apply_weight_i(weight, sample) ((weight * sample + 512) >> 10) #else #define apply_weight_i(weight, sample) ((((weight * sample) >> 8) + 2) >> 2) @@ -340,15 +340,18 @@ void native_to_little_endian (void *data, char *format); #if 0 // PERFCOND #define update_weight(weight, delta, source, result) \ - if (source && result) weight -= ((((source ^ result) >> 30) & 2) - 1) * delta; + if (source && result) { int32_t s = (int32_t) (source ^ result) >> 31; weight = (delta ^ s) + (weight - s); } +#elif 1 +#define update_weight(weight, delta, source, result) \ + if (source && result) weight += (((source ^ result) >> 30) | 1) * delta #else #define update_weight(weight, delta, source, result) \ - if (source && result) (source ^ result) < 0 ? (weight -= delta) : (weight += delta); + 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; + weight = weight < 0 ? -1024 : 1024 // unpack.c diff --git a/apps/metadata.c b/apps/metadata.c index 1f61e98498..acd8de38e3 100644 --- a/apps/metadata.c +++ b/apps/metadata.c @@ -1867,9 +1867,9 @@ bool get_metadata(struct track_info* track, int fd, const char* trackname, case AFMT_WAVPACK: /* A simple parser to read basic information from a WavPack file. This - * now works with self-extrating WavPack files and also will fail on - * WavPack files containing floating-point audio data (although these - * should be possible to play in theory). + * now works with self-extrating WavPack files. This no longer fails on + * WavPack files containing floating-point audio data because these are + * now converted to standard Rockbox format in the decoder. */ /* Use the trackname part of the id3 structure as a temporary buffer */ @@ -1887,7 +1887,7 @@ bool get_metadata(struct track_info* track, int fd, const char* trackname, /* if valid WavPack 4 header version & not floating data, break */ if (memcmp (buf, "wvpk", 4) == 0 && buf [9] == 4 && - (buf [8] >= 2 && buf [8] <= 0x10) && !(buf [24] & 0x80)) + (buf [8] >= 2 && buf [8] <= 0x10)) { break; } |