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
This commit is contained in:
parent
5693622cd4
commit
2446b22db9
4 changed files with 41 additions and 78 deletions
|
@ -25,59 +25,23 @@ int read_float_info (WavpackStream *wps, WavpackMetadata *wpmd)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/* This function converts WavPack floating point data into standard Rockbox
|
||||
* 28-bit integers. It is assumed that clipping will be taken care of later.
|
||||
*/
|
||||
|
||||
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 };
|
||||
int shift = wps->float_max_exp - wps->float_norm_exp + wps->float_shift + 5;
|
||||
|
||||
if (*values) {
|
||||
*values <<= wps->float_shift;
|
||||
if (shift > 32)
|
||||
shift = 32;
|
||||
else if (shift < -32)
|
||||
shift = -32;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
void float_normalize (int32_t *values, int32_t num_values, int delta_exp)
|
||||
{
|
||||
f32 *fvalues = (f32 *) values, fzero = { 0, 0, 0 };
|
||||
int exp;
|
||||
|
||||
if (!delta_exp)
|
||||
return;
|
||||
|
||||
while (num_values--) {
|
||||
if ((exp = fvalues->exponent) == 0 || exp + delta_exp <= 0)
|
||||
*fvalues = fzero;
|
||||
else if (exp == 255 || (exp += delta_exp) >= 255) {
|
||||
fvalues->exponent = 255;
|
||||
fvalues->mantissa = 0;
|
||||
}
|
||||
else
|
||||
fvalues->exponent = exp;
|
||||
|
||||
fvalues++;
|
||||
}
|
||||
if (shift > 0)
|
||||
while (num_values--)
|
||||
*values++ <<= shift;
|
||||
else if (shift < 0)
|
||||
while (num_values--)
|
||||
*values++ >>= -shift;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue