Fix endian issues for intel

CQTexperiment
vspader 2006-04-21 20:43:47 +00:00
parent c63f495f33
commit e1eabaea4b
32 changed files with 16209 additions and 15017 deletions

View File

@ -1,6 +1,7 @@
0.05 alpha 4 0.05 alpha 4
------------ ------------
Volume slider now gravitates to 100%, in the middle. Volume slider now gravitates to 100%, in the middle.
Fixes endian issues for intel?
0.05 alpha 3 0.05 alpha 3
------------ ------------

View File

@ -157,7 +157,7 @@
29B97325FDCFA39411CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; }; 29B97325FDCFA39411CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; };
32CA4F630368D1EE00C91783 /* Cog_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Cog_Prefix.pch; sourceTree = "<group>"; }; 32CA4F630368D1EE00C91783 /* Cog_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Cog_Prefix.pch; sourceTree = "<group>"; };
8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; }; 8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
8D1107320486CEB800E47090 /* Cog.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = Cog.app; sourceTree = BUILT_PRODUCTS_DIR; }; 8D1107320486CEB800E47090 /* Cog.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Cog.app; sourceTree = BUILT_PRODUCTS_DIR; };
8E75751309F31D130080F1EE /* French */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = French; path = French.lproj/MainMenu.nib; sourceTree = "<group>"; }; 8E75751309F31D130080F1EE /* French */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = French; path = French.lproj/MainMenu.nib; sourceTree = "<group>"; };
8E75751809F31D5A0080F1EE /* AppController.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = AppController.h; sourceTree = "<group>"; }; 8E75751809F31D5A0080F1EE /* AppController.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = AppController.h; sourceTree = "<group>"; };
8E75751909F31D5A0080F1EE /* AppController.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = AppController.m; sourceTree = "<group>"; }; 8E75751909F31D5A0080F1EE /* AppController.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = AppController.m; sourceTree = "<group>"; };

Binary file not shown.

View File

@ -1,3 +1,107 @@
----------------------
Update - April 5, 2006
----------------------
WavPack Library Source Code - 4.32
-----------------------------------------
fixed: generating RIFF headers on big-endian machines caused crash
--------------------------
Update - December 10, 2005
--------------------------
wavpack.exe (command-line encoder) - 4.31
wvunpack.exe (command-line decoder) - 4.31
------------------------------------------
fixed: detect debug mode in all cases (win32 only)
improved: use latest service pack and SDK for building (win32 only)
improved: better directory choice for logging file (win32 only)
improved: allow shell to expand wildcards (*nix only)
added: option (-o) to specify output directory or path (*nix only)
added: option (-t) to copy timestamp (*nix only)
wvgain.exe (command-line ReplayGain scanner) - 4.31
---------------------------------------------------
new
WavPack Library Source Code - 4.31
----------------------------------
fixed: failing seek with some files that had been played to the end
fixed: small memory leak when opening hybrid lossless files
improved: signed characters no longer must be default
improved: APEv2 tags are read even if followed by ID3v1 tag
improved: limited APEv2 tag editing capability
------------------------------
Release 4.3 - November 1, 2005
------------------------------
wavpack.exe (command-line encoder) - 4.3
----------------------------------------
fixed: bug causing termination error with very wide screen widths
added: command-line option (-l) to use low priority for batch operation
added: command-line option (-r) to generate a fresh RIFF header
added: debug mode (rename to wavpack_debug.exe)
added: automatically detect lower resolution data even without -x1
added: src and dst dirs are searched also for tag source files (handy for EAC)
added: wildcard accepted for tag source files (handy for EAC)
added: handle non-standard sampling rates
improved: returns error status for any error
improved: use longer blocks in multichannel files (better "high" compression)
wvunpack.exe (command-line decoder) - 4.3
-----------------------------------------
fixed: very rare decoding bug causing overflow with hi-res files
fixed: bug causing termination error with very wide screen widths
fixed: formatting error in duration display
added: command-line option (-ss) to include tags in summary dump
added: command-line option (-l) to use low priority for batch operation
added: debug mode (rename to wvunpack_debug.exe)
improved: returns error status for any error
improved: more robust decoding of damaged (or invalid) files
in_wv.dll (winamp plugin) - 2.3
nxWavPack.dll (Nero plugin) - 1.2
WavPack_Apollo.dll (Apollo plugin) - 1.3
cool_wv4.flt (CoolEdit / Audition filter) - 2.6
-----------------------------------------------
fixed: very rare decoding bug causing overflow with hi-res files
improved: handle ID3v1.1 tags (now includes track number)
improved: more robust decoding of damaged (or invalid) files
added: handle non-standard sampling rates
foo_wavpack.dll (foobar plugin) - 2.3
-----------------------------------------------
fixed: any error during WavPack file open caused crash if wvc file present
fixed: very rare decoding bug causing overflow with hi-res files
improved: more robust decoding of damaged (or invalid) files
added: handle non-standard sampling rates
WavPack Library Source Code - 4.3
---------------------------------
fixed: very rare decoding bug causing overflow with hi-res files
added: automatic generation of RIFF wav header during encoding
added: new functions to access tags by index (instead of item name)
added: automatically detect lower resolution data during encoding
added: handle non-standard sampling rates
improved: more robust decoding of damaged (or invalid) files
improved: use longer blocks in multichannel files (better "high" compression)
improved: two structures renamed to avoid namespace conflict
removed: legacy code for Borland compiler
--------------------------
Update - September 1, 2005
--------------------------
wavpack.exe (command-line encoder) - 4.22
cool_wv4.flt (CoolEdit / Audition filter) - 2.5
-----------------------------------------------
fixed: possible corrupt files written (24 or 32-bit + "extra" mode)
--------------------------- ---------------------------
Release 4.2 - April 2, 2005 Release 4.2 - April 2, 2005
--------------------------- ---------------------------

View File

@ -1,5 +1,5 @@
AUTOMAKE_OPTIONS = foreign AUTOMAKE_OPTIONS = foreign
bin_PROGRAMS = wavpack wvunpack bin_PROGRAMS = wavpack wvunpack wvgain
lib_LTLIBRARIES = libwavpack.la lib_LTLIBRARIES = libwavpack.la
@ -7,21 +7,26 @@ wpincludedir = $(prefix)/include/wavpack
wpinclude_HEADERS = md5.h wavpack.h wputils.h unpack3.h wpinclude_HEADERS = md5.h wavpack.h wputils.h unpack3.h
libwavpack_la_SOURCES = bits.c float.c metadata.c unpack.c unpack3.c utils.c \ libwavpack_la_SOURCES = bits.c float.c metadata.c unpack.c unpack3.c \
wputils.c words.c md5.c extra1.c extra2.c pack.c \ wputils.c words.c md5.c extra1.c extra2.c pack.c \
md5.h wavpack.h wputils.h unpack3.h md5.h wavpack.h wputils.h unpack3.h
libwavpack_la_CFLAGS = -DPACK -DUNPACK -DUSE_FSTREAMS -DTAGS -DSEEKING -DVER3 libwavpack_la_CFLAGS = -DPACK -DUNPACK -DUSE_FSTREAMS -DTAGS -DSEEKING -DVER3
libwavpack_la_LDFLAGS = -lm @ICONV_LIBS@ libwavpack_la_LDFLAGS = -lm @ICONV_LIBS@
wavpack_SOURCES = wavpack.c wavpack_SOURCES = wavpack.c utils.c
wavpack_CFLAGS = -DPACK wavpack_CFLAGS = -DPACK
wavpack_LDFLAGS = -lm -lcurses wavpack_LDFLAGS = -lm
wavpack_LDADD = libwavpack.la wavpack_LDADD = libwavpack.la
wvunpack_SOURCES = wvunpack.c wvunpack_SOURCES = wvunpack.c utils.c
wvunpack_CFLAGS = -DUNPACK -DUSE_FSTREAMS wvunpack_CFLAGS = -DUNPACK -DUSE_FSTREAMS
wvunpack_LDFLAGS = -lm -lcurses wvunpack_LDFLAGS = -lm
wvunpack_LDADD = libwavpack.la wvunpack_LDADD = libwavpack.la
wvgain_SOURCES = wvgain.c utils.c
wvgain_CFLAGS = -DUNPACK -DUSE_FSTREAMS
wvgain_LDFLAGS = -lm
wvgain_LDADD = libwavpack.la
pkgconfigdir = $(libdir)/pkgconfig pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = wavpack.pc pkgconfig_DATA = wavpack.pc

View File

@ -13,10 +13,9 @@ of the plugin sources in the Windows source release.
To build everything, type: To build everything, type:
1. ./autogen.sh 1. ./configure
2. ./configure 2. make
3. make 3. make install (optionally, to install into /usr/local/bin)
4. make install (optionally, to install into /usr/local/bin)
Notes: Notes:
@ -31,10 +30,10 @@ Notes:
a "short" must be 16-bits a "short" must be 16-bits
an "int" must be at least 16-bits, but may be larger an "int" must be at least 16-bits, but may be larger
a "char" must default to signed (Watcom users take note!)
For version 4.2 references to "long" variables were eliminated to allow For version 4.2 references to "long" variables were eliminated to allow
compilation on 64-bit machines. compilation on 64-bit machines. For version 4.3 "char" types may default
to signed or unsigned.
2. For WavPack file decoding, a library interface in "wputils.c" provides all 2. For WavPack file decoding, a library interface in "wputils.c" provides all
the functionality required for both the winamp plugin and the "wvunpack" the functionality required for both the winamp plugin and the "wvunpack"

View File

@ -1,7 +1,7 @@
# wavpack 4.2 configure.ac # wavpack 4.32 configure.ac
AC_INIT(wavpack, 4.2, bryant@wavpack.com) AC_INIT(wavpack, 4.32, bryant@wavpack.com)
AM_INIT_AUTOMAKE(wavpack, 4.2, bryant@wavpack.com) AM_INIT_AUTOMAKE(wavpack, 4.32, bryant@wavpack.com)
AC_CONFIG_SRCDIR([pack.c]) AC_CONFIG_SRCDIR([pack.c])
# Check for os version # Check for os version

View File

@ -17,6 +17,7 @@
#include <string.h> #include <string.h>
#include <math.h> #include <math.h>
#define LOG_LIMIT 6912
// #define EXTRA_DUMP // #define EXTRA_DUMP
#ifdef DEBUG_ALLOC #ifdef DEBUG_ALLOC
@ -31,25 +32,21 @@ int32_t dump_alloc (void);
//////////////////////////////// local tables /////////////////////////////// //////////////////////////////// local tables ///////////////////////////////
extern const char default_terms [], high_terms [], fast_terms []; typedef struct {
int32_t *sampleptrs [MAX_NTERMS+2];
struct decorr_pass dps [MAX_NTERMS];
int nterms, log_limit;
uint32_t best_bits;
} WavpackExtraInfo;
// #define MINMAX_WEIGHTS extern const signed char default_terms [], high_terms [], fast_terms [];
#ifdef MINMAX_WEIGHTS
static int32_t min_weight, max_weight;
static int min_term, max_term;
#endif
static void decorr_mono_pass (int32_t *in_samples, int32_t *out_samples, uint32_t num_samples, struct decorr_pass *dpp, int dir) static void decorr_mono_pass (int32_t *in_samples, int32_t *out_samples, uint32_t num_samples, struct decorr_pass *dpp, int dir)
{ {
int m = 0; int m = 0, i;
dpp->sum_A = 0; dpp->sum_A = 0;
#ifdef MINMAX_WEIGHTS
dpp->min = dpp->max = 0;
#endif
if (dir < 0) { if (dir < 0) {
out_samples += (num_samples - 1); out_samples += (num_samples - 1);
in_samples += (num_samples - 1); in_samples += (num_samples - 1);
@ -58,6 +55,11 @@ static void decorr_mono_pass (int32_t *in_samples, int32_t *out_samples, uint32_
else else
dir = 1; dir = 1;
dpp->weight_A = restore_weight (store_weight (dpp->weight_A));
for (i = 0; i < 8; ++i)
dpp->samples_A [i] = exp2s (log2s (dpp->samples_A [i]));
if (dpp->term > MAX_TERM) { if (dpp->term > MAX_TERM) {
while (num_samples--) { while (num_samples--) {
int32_t left, sam_A; int32_t left, sam_A;
@ -73,10 +75,6 @@ static void decorr_mono_pass (int32_t *in_samples, int32_t *out_samples, uint32_
left -= apply_weight (dpp->weight_A, sam_A); left -= apply_weight (dpp->weight_A, sam_A);
update_weight (dpp->weight_A, dpp->delta, sam_A, left); update_weight (dpp->weight_A, dpp->delta, sam_A, left);
dpp->sum_A += dpp->weight_A; dpp->sum_A += dpp->weight_A;
#ifdef MINMAX_WEIGHTS
if (dpp->weight_A > dpp->max) dpp->max = dpp->weight_A;
if (dpp->weight_A < dpp->min) dpp->min = dpp->weight_A;
#endif
out_samples [0] = left; out_samples [0] = left;
in_samples += dir; in_samples += dir;
out_samples += dir; out_samples += dir;
@ -94,23 +92,12 @@ static void decorr_mono_pass (int32_t *in_samples, int32_t *out_samples, uint32_
left -= apply_weight (dpp->weight_A, sam_A); left -= apply_weight (dpp->weight_A, sam_A);
update_weight (dpp->weight_A, dpp->delta, sam_A, left); update_weight (dpp->weight_A, dpp->delta, sam_A, left);
dpp->sum_A += dpp->weight_A; dpp->sum_A += dpp->weight_A;
#ifdef MINMAX_WEIGHTS
if (dpp->weight_A > dpp->max) dpp->max = dpp->weight_A;
if (dpp->weight_A < dpp->min) dpp->min = dpp->weight_A;
#endif
out_samples [0] = left; out_samples [0] = left;
in_samples += dir; in_samples += dir;
out_samples += dir; out_samples += dir;
} }
} }
#ifdef MINMAX_WEIGHTS
if (dpp->term != 0) {
if (dpp->max > max_weight) { max_weight = dpp->max; max_term = dpp->term; }
if (dpp->min < min_weight) { min_weight = dpp->min; min_term = dpp->term; }
}
#endif
if (m && dpp->term > 0 && dpp->term <= MAX_TERM) { if (m && dpp->term > 0 && dpp->term <= MAX_TERM) {
int32_t temp_A [MAX_TERM]; int32_t temp_A [MAX_TERM];
int k; int k;
@ -155,14 +142,14 @@ static void reverse_mono_decorr (struct decorr_pass *dpp)
dpp->samples_A [i++] ^= dpp->samples_A [j--]; dpp->samples_A [i++] ^= dpp->samples_A [j--];
} }
CLEAR (dpp->samples_A); // CLEAR (dpp->samples_A);
} }
} }
static void decorr_mono_buffer (int32_t *samples, int32_t *outsamples, uint32_t num_samples, struct decorr_pass *dpp) static void decorr_mono_buffer (int32_t *samples, int32_t *outsamples, uint32_t num_samples, struct decorr_pass *dpp, int tindex)
{ {
int delta = dpp->delta, pre_delta, term = dpp->term; struct decorr_pass dp, *dppi = dpp + tindex;
struct decorr_pass dp; int delta = dppi->delta, pre_delta, term = dppi->term;
if (delta == 7) if (delta == 7)
pre_delta = 7; pre_delta = 7;
@ -176,41 +163,45 @@ static void decorr_mono_buffer (int32_t *samples, int32_t *outsamples, uint32_t
dp.delta = pre_delta; dp.delta = pre_delta;
decorr_mono_pass (samples, outsamples, num_samples > 2048 ? 2048 : num_samples, &dp, -1); decorr_mono_pass (samples, outsamples, num_samples > 2048 ? 2048 : num_samples, &dp, -1);
dp.delta = delta; dp.delta = delta;
reverse_mono_decorr (&dp);
memcpy (dpp->samples_A, dp.samples_A, sizeof (dp.samples_A)); if (tindex == 0)
dpp->weight_A = dp.weight_A; reverse_mono_decorr (&dp);
else
CLEAR (dp.samples_A);
memcpy (dppi->samples_A, dp.samples_A, sizeof (dp.samples_A));
dppi->weight_A = dp.weight_A;
if (delta == 0) { if (delta == 0) {
dp.delta = 1; dp.delta = 1;
decorr_mono_pass (samples, outsamples, num_samples, &dp, 1); decorr_mono_pass (samples, outsamples, num_samples, &dp, 1);
dp.delta = 0; dp.delta = 0;
memcpy (dp.samples_A, dpp->samples_A, sizeof (dp.samples_A)); memcpy (dp.samples_A, dppi->samples_A, sizeof (dp.samples_A));
dpp->weight_A = dp.weight_A = dp.sum_A / num_samples; dppi->weight_A = dp.weight_A = dp.sum_A / num_samples;
} }
// if (memcmp (dpp, &dp, sizeof (dp))) // if (memcmp (dppi, &dp, sizeof (dp)))
// error_line ("decorr_passes don't match, delta = %d", delta); // error_line ("decorr_passes don't match, delta = %d", delta);
decorr_mono_pass (samples, outsamples, num_samples, &dp, 1); decorr_mono_pass (samples, outsamples, num_samples, &dp, 1);
} }
static void recurse_mono (WavpackContext *wpc, int32_t *sampleptrs[], struct decorr_pass dps[], static void recurse_mono (WavpackContext *wpc, WavpackExtraInfo *info, int depth, int delta, uint32_t input_bits)
int depth, int nterms, int delta, uint32_t input_bits, uint32_t *best_bits)
{ {
WavpackStream *wps = wpc->streams [wpc->current_stream]; WavpackStream *wps = wpc->streams [wpc->current_stream];
int term, branches = ((wpc->config.extra_flags & EXTRA_BRANCHES) >> 6) - depth; int term, branches = ((wpc->config.extra_flags & EXTRA_BRANCHES) >> 6) - depth;
int32_t *samples, *outsamples; int32_t *samples, *outsamples;
uint32_t term_bits [22], bits; uint32_t term_bits [22], bits;
if (branches < 1 || depth + 1 == nterms) if (branches < 1 || depth + 1 == info->nterms)
branches = 1; branches = 1;
CLEAR (term_bits); CLEAR (term_bits);
samples = sampleptrs [depth]; samples = info->sampleptrs [depth];
outsamples = sampleptrs [depth + 1]; outsamples = info->sampleptrs [depth + 1];
for (term = 1; term <= 18; ++term) { for (term = 1; term <= 18; ++term) {
if (term == 17 && branches == 1 && depth + 1 < nterms) if (term == 17 && branches == 1 && depth + 1 < info->nterms)
continue; continue;
if (term >= 9 && term <= 16) if (term >= 9 && term <= 16)
@ -220,22 +211,22 @@ static void recurse_mono (WavpackContext *wpc, int32_t *sampleptrs[], struct dec
if ((wpc->config.flags & CONFIG_FAST_FLAG) && (term >= 5 && term <= 16)) if ((wpc->config.flags & CONFIG_FAST_FLAG) && (term >= 5 && term <= 16))
continue; continue;
dps [depth].term = term; info->dps [depth].term = term;
dps [depth].delta = delta; info->dps [depth].delta = delta;
decorr_mono_buffer (samples, outsamples, wps->wphdr.block_samples, &dps [depth]); decorr_mono_buffer (samples, outsamples, wps->wphdr.block_samples, info->dps, depth);
bits = log2buffer (outsamples, wps->wphdr.block_samples); bits = log2buffer (outsamples, wps->wphdr.block_samples, info->log_limit);
if (bits < *best_bits) { if (bits < info->best_bits) {
*best_bits = bits; info->best_bits = bits;
CLEAR (wps->decorr_passes); CLEAR (wps->decorr_passes);
memcpy (wps->decorr_passes, dps, sizeof (dps [0]) * (depth + 1)); memcpy (wps->decorr_passes, info->dps, sizeof (info->dps [0]) * (depth + 1));
memcpy (sampleptrs [nterms + 1], sampleptrs [depth + 1], wps->wphdr.block_samples * 4); memcpy (info->sampleptrs [info->nterms + 1], info->sampleptrs [depth + 1], wps->wphdr.block_samples * 4);
} }
term_bits [term + 3] = bits; term_bits [term + 3] = bits;
} }
while (depth + 1 < nterms && branches--) { while (depth + 1 < info->nterms && branches--) {
uint32_t local_best_bits = input_bits; uint32_t local_best_bits = input_bits;
int best_term = 0, i; int best_term = 0, i;
@ -249,19 +240,18 @@ static void recurse_mono (WavpackContext *wpc, int32_t *sampleptrs[], struct dec
if (!best_term) if (!best_term)
break; break;
dps [depth].term = best_term; info->dps [depth].term = best_term;
dps [depth].delta = delta; info->dps [depth].delta = delta;
decorr_mono_buffer (samples, outsamples, wps->wphdr.block_samples, &dps [depth]); decorr_mono_buffer (samples, outsamples, wps->wphdr.block_samples, info->dps, depth);
// if (log2buffer (outsamples, wps->wphdr.block_samples * 2) != local_best_bits) // if (log2buffer (outsamples, wps->wphdr.block_samples * 2, 0) != local_best_bits)
// error_line ("data doesn't match!"); // error_line ("data doesn't match!");
recurse_mono (wpc, sampleptrs, dps, depth + 1, nterms, delta, local_best_bits, best_bits); recurse_mono (wpc, info, depth + 1, delta, local_best_bits);
} }
} }
static void delta_mono (WavpackContext *wpc, int32_t *sampleptrs[], struct decorr_pass dps[], static void delta_mono (WavpackContext *wpc, WavpackExtraInfo *info)
int nterms, uint32_t *best_bits)
{ {
WavpackStream *wps = wpc->streams [wpc->current_stream]; WavpackStream *wps = wpc->streams [wpc->current_stream];
int lower = FALSE, delta, d; int lower = FALSE, delta, d;
@ -278,20 +268,20 @@ static void delta_mono (WavpackContext *wpc, int32_t *sampleptrs[], struct decor
if (!d && (wps->wphdr.flags & HYBRID_FLAG)) if (!d && (wps->wphdr.flags & HYBRID_FLAG))
break; break;
for (i = 0; i < nterms && wps->decorr_passes [i].term; ++i) { for (i = 0; i < info->nterms && wps->decorr_passes [i].term; ++i) {
dps [i].term = wps->decorr_passes [i].term; info->dps [i].term = wps->decorr_passes [i].term;
dps [i].delta = d; info->dps [i].delta = d;
decorr_mono_buffer (sampleptrs [i], sampleptrs [i+1], wps->wphdr.block_samples, &dps [i]); decorr_mono_buffer (info->sampleptrs [i], info->sampleptrs [i+1], wps->wphdr.block_samples, info->dps, i);
} }
bits = log2buffer (sampleptrs [i], wps->wphdr.block_samples); bits = log2buffer (info->sampleptrs [i], wps->wphdr.block_samples, info->log_limit);
if (bits < *best_bits) { if (bits < info->best_bits) {
lower = TRUE; lower = TRUE;
*best_bits = bits; info->best_bits = bits;
CLEAR (wps->decorr_passes); CLEAR (wps->decorr_passes);
memcpy (wps->decorr_passes, dps, sizeof (dps [0]) * i); memcpy (wps->decorr_passes, info->dps, sizeof (info->dps [0]) * i);
memcpy (sampleptrs [nterms + 1], sampleptrs [i], wps->wphdr.block_samples * 4); memcpy (info->sampleptrs [info->nterms + 1], info->sampleptrs [i], wps->wphdr.block_samples * 4);
} }
else else
break; break;
@ -300,27 +290,26 @@ static void delta_mono (WavpackContext *wpc, int32_t *sampleptrs[], struct decor
for (d = delta + 1; !lower && d <= 7; ++d) { for (d = delta + 1; !lower && d <= 7; ++d) {
int i; int i;
for (i = 0; i < nterms && wps->decorr_passes [i].term; ++i) { for (i = 0; i < info->nterms && wps->decorr_passes [i].term; ++i) {
dps [i].term = wps->decorr_passes [i].term; info->dps [i].term = wps->decorr_passes [i].term;
dps [i].delta = d; info->dps [i].delta = d;
decorr_mono_buffer (sampleptrs [i], sampleptrs [i+1], wps->wphdr.block_samples, &dps [i]); decorr_mono_buffer (info->sampleptrs [i], info->sampleptrs [i+1], wps->wphdr.block_samples, info->dps, i);
} }
bits = log2buffer (sampleptrs [i], wps->wphdr.block_samples); bits = log2buffer (info->sampleptrs [i], wps->wphdr.block_samples, info->log_limit);
if (bits < *best_bits) { if (bits < info->best_bits) {
*best_bits = bits; info->best_bits = bits;
CLEAR (wps->decorr_passes); CLEAR (wps->decorr_passes);
memcpy (wps->decorr_passes, dps, sizeof (dps [0]) * i); memcpy (wps->decorr_passes, info->dps, sizeof (info->dps [0]) * i);
memcpy (sampleptrs [nterms + 1], sampleptrs [i], wps->wphdr.block_samples * 4); memcpy (info->sampleptrs [info->nterms + 1], info->sampleptrs [i], wps->wphdr.block_samples * 4);
} }
else else
break; break;
} }
} }
static void sort_mono (WavpackContext *wpc, int32_t *sampleptrs[], struct decorr_pass dps[], static void sort_mono (WavpackContext *wpc, WavpackExtraInfo *info)
int nterms, uint32_t *best_bits)
{ {
WavpackStream *wps = wpc->streams [wpc->current_stream]; WavpackStream *wps = wpc->streams [wpc->current_stream];
int reversed = TRUE; int reversed = TRUE;
@ -329,38 +318,38 @@ static void sort_mono (WavpackContext *wpc, int32_t *sampleptrs[], struct decorr
while (reversed) { while (reversed) {
int ri, i; int ri, i;
memcpy (dps, wps->decorr_passes, sizeof (wps->decorr_passes)); memcpy (info->dps, wps->decorr_passes, sizeof (wps->decorr_passes));
reversed = FALSE; reversed = FALSE;
for (ri = 0; ri < nterms && wps->decorr_passes [ri].term; ++ri) { for (ri = 0; ri < info->nterms && wps->decorr_passes [ri].term; ++ri) {
if (ri + 1 >= nterms || !wps->decorr_passes [ri+1].term) if (ri + 1 >= info->nterms || !wps->decorr_passes [ri+1].term)
break; break;
if (wps->decorr_passes [ri].term == wps->decorr_passes [ri+1].term) { if (wps->decorr_passes [ri].term == wps->decorr_passes [ri+1].term) {
decorr_mono_buffer (sampleptrs [ri], sampleptrs [ri+1], wps->wphdr.block_samples, &dps [ri]); decorr_mono_buffer (info->sampleptrs [ri], info->sampleptrs [ri+1], wps->wphdr.block_samples, info->dps, ri);
continue; continue;
} }
dps [ri] = wps->decorr_passes [ri+1]; info->dps [ri] = wps->decorr_passes [ri+1];
dps [ri+1] = wps->decorr_passes [ri]; info->dps [ri+1] = wps->decorr_passes [ri];
for (i = ri; i < nterms && wps->decorr_passes [i].term; ++i) for (i = ri; i < info->nterms && wps->decorr_passes [i].term; ++i)
decorr_mono_buffer (sampleptrs [i], sampleptrs [i+1], wps->wphdr.block_samples, &dps [i]); decorr_mono_buffer (info->sampleptrs [i], info->sampleptrs [i+1], wps->wphdr.block_samples, info->dps, i);
bits = log2buffer (sampleptrs [i], wps->wphdr.block_samples); bits = log2buffer (info->sampleptrs [i], wps->wphdr.block_samples, info->log_limit);
if (bits < *best_bits) { if (bits < info->best_bits) {
reversed = TRUE; reversed = TRUE;
*best_bits = bits; info->best_bits = bits;
CLEAR (wps->decorr_passes); CLEAR (wps->decorr_passes);
memcpy (wps->decorr_passes, dps, sizeof (dps [0]) * i); memcpy (wps->decorr_passes, info->dps, sizeof (info->dps [0]) * i);
memcpy (sampleptrs [nterms + 1], sampleptrs [i], wps->wphdr.block_samples * 4); memcpy (info->sampleptrs [info->nterms + 1], info->sampleptrs [i], wps->wphdr.block_samples * 4);
} }
else { else {
dps [ri] = wps->decorr_passes [ri]; info->dps [ri] = wps->decorr_passes [ri];
dps [ri+1] = wps->decorr_passes [ri+1]; info->dps [ri+1] = wps->decorr_passes [ri+1];
decorr_mono_buffer (sampleptrs [ri], sampleptrs [ri+1], wps->wphdr.block_samples, &dps [ri]); decorr_mono_buffer (info->sampleptrs [ri], info->sampleptrs [ri+1], wps->wphdr.block_samples, info->dps, ri);
} }
} }
} }
@ -368,18 +357,29 @@ static void sort_mono (WavpackContext *wpc, int32_t *sampleptrs[], struct decorr
#define EXTRA_ADVANCED (EXTRA_BRANCHES | EXTRA_SORT_FIRST | EXTRA_SORT_LAST | EXTRA_TRY_DELTAS) #define EXTRA_ADVANCED (EXTRA_BRANCHES | EXTRA_SORT_FIRST | EXTRA_SORT_LAST | EXTRA_TRY_DELTAS)
//extern uint32_t crc3;
void analyze_mono (WavpackContext *wpc, int32_t *samples) void analyze_mono (WavpackContext *wpc, int32_t *samples)
{ {
WavpackStream *wps = wpc->streams [wpc->current_stream]; WavpackStream *wps = wpc->streams [wpc->current_stream];
#ifdef EXTRA_DUMP #ifdef EXTRA_DUMP
uint32_t bits, best_bits, default_bits, cnt; uint32_t bits, default_bits, cnt;
#else #else
uint32_t bits, best_bits, cnt; uint32_t bits, cnt;
#endif
const signed char *decorr_terms = default_terms, *tp;
WavpackExtraInfo info;
int32_t *lptr;
int i;
#ifdef LOG_LIMIT
info.log_limit = (((wps->wphdr.flags & MAG_MASK) >> MAG_LSB) + 4) * 256;
if (info.log_limit > LOG_LIMIT)
info.log_limit = LOG_LIMIT;
#else
info.log_limit = 0;
#endif #endif
const char *decorr_terms = default_terms, *tp;
int32_t *sampleptrs [MAX_NTERMS+2], *lptr;
struct decorr_pass dps [MAX_NTERMS];
int nterms, i;
CLEAR (wps->decorr_passes); CLEAR (wps->decorr_passes);
cnt = wps->wphdr.block_samples; cnt = wps->wphdr.block_samples;
@ -400,50 +400,50 @@ void analyze_mono (WavpackContext *wpc, int32_t *samples)
else if (wpc->config.flags & CONFIG_FAST_FLAG) else if (wpc->config.flags & CONFIG_FAST_FLAG)
decorr_terms = fast_terms; decorr_terms = fast_terms;
for (nterms = 0, tp = decorr_terms; *tp; tp++) for (info.nterms = 0, tp = decorr_terms; *tp; tp++)
if (*tp > 0) if (*tp > 0)
++nterms; ++info.nterms;
if (wpc->config.extra_flags & EXTRA_TERMS) if (wpc->config.extra_flags & EXTRA_TERMS)
if ((nterms += (wpc->config.extra_flags & EXTRA_TERMS) >> 10) > MAX_NTERMS) if ((info.nterms += (wpc->config.extra_flags & EXTRA_TERMS) >> 10) > MAX_NTERMS)
nterms = MAX_NTERMS; info.nterms = MAX_NTERMS;
for (i = 0; i < nterms + 2; ++i) for (i = 0; i < info.nterms + 2; ++i)
sampleptrs [i] = malloc (wps->wphdr.block_samples * 4); info.sampleptrs [i] = malloc (wps->wphdr.block_samples * 4);
memcpy (sampleptrs [nterms + 1], samples, wps->wphdr.block_samples * 4); memcpy (info.sampleptrs [info.nterms + 1], samples, wps->wphdr.block_samples * 4);
best_bits = log2buffer (sampleptrs [nterms + 1], wps->wphdr.block_samples); info.best_bits = log2buffer (info.sampleptrs [info.nterms + 1], wps->wphdr.block_samples, 0);
memcpy (sampleptrs [0], samples, wps->wphdr.block_samples * 4); memcpy (info.sampleptrs [0], samples, wps->wphdr.block_samples * 4);
CLEAR (dps); CLEAR (info.dps);
for (tp = decorr_terms, i = 0; *tp; tp++) for (tp = decorr_terms, i = 0; *tp; tp++)
if (*tp > 0) { if (*tp > 0) {
dps [i].term = *tp; info.dps [i].term = *tp;
dps [i].delta = 2; info.dps [i].delta = 2;
decorr_mono_buffer (sampleptrs [i], sampleptrs [i+1], wps->wphdr.block_samples, &dps [i]); decorr_mono_buffer (info.sampleptrs [i], info.sampleptrs [i+1], wps->wphdr.block_samples, info.dps, i);
++i; ++i;
} }
#ifdef EXTRA_DUMP #ifdef EXTRA_DUMP
default_bits = bits = log2buffer (sampleptrs [i], wps->wphdr.block_samples); default_bits = bits = log2buffer (info.sampleptrs [i], wps->wphdr.block_samples, 0);
#else #else
bits = log2buffer (sampleptrs [i], wps->wphdr.block_samples); bits = log2buffer (info.sampleptrs [i], wps->wphdr.block_samples, 0);
#endif #endif
if (bits < best_bits) { if (bits < info.best_bits) {
best_bits = bits; info.best_bits = bits;
CLEAR (wps->decorr_passes); CLEAR (wps->decorr_passes);
memcpy (wps->decorr_passes, dps, sizeof (dps [0]) * i); memcpy (wps->decorr_passes, info.dps, sizeof (info.dps [0]) * i);
memcpy (sampleptrs [nterms + 1], sampleptrs [i], wps->wphdr.block_samples * 4); memcpy (info.sampleptrs [info.nterms + 1], info.sampleptrs [i], wps->wphdr.block_samples * 4);
} }
if ((wps->wphdr.flags & HYBRID_FLAG) && (wpc->config.extra_flags & EXTRA_ADVANCED)) { if ((wps->wphdr.flags & HYBRID_FLAG) && (wpc->config.extra_flags & EXTRA_ADVANCED)) {
int shaping_weight, new = wps->wphdr.flags & NEW_SHAPING; int shaping_weight, new = wps->wphdr.flags & NEW_SHAPING;
int32_t *rptr = sampleptrs [nterms + 1], error = 0, temp; int32_t *rptr = info.sampleptrs [info.nterms + 1], error = 0, temp;
scan_word (wps, rptr, wps->wphdr.block_samples, -1); scan_word (wps, rptr, wps->wphdr.block_samples, -1);
cnt = wps->wphdr.block_samples; cnt = wps->wphdr.block_samples;
lptr = sampleptrs [0]; lptr = info.sampleptrs [0];
if (wps->wphdr.flags & HYBRID_SHAPE) { if (wps->wphdr.flags & HYBRID_SHAPE) {
while (cnt--) { while (cnt--) {
@ -472,31 +472,31 @@ void analyze_mono (WavpackContext *wpc, int32_t *samples)
rptr++; rptr++;
} }
memcpy (dps, wps->decorr_passes, sizeof (dps)); memcpy (info.dps, wps->decorr_passes, sizeof (info.dps));
for (i = 0; i < nterms && dps [i].term; ++i) for (i = 0; i < info.nterms && info.dps [i].term; ++i)
decorr_mono_buffer (sampleptrs [i], sampleptrs [i + 1], wps->wphdr.block_samples, dps + i); decorr_mono_buffer (info.sampleptrs [i], info.sampleptrs [i + 1], wps->wphdr.block_samples, info.dps, i);
#ifdef EXTRA_DUMP #ifdef EXTRA_DUMP
best_bits = default_bits = log2buffer (sampleptrs [i], wps->wphdr.block_samples); info.best_bits = default_bits = log2buffer (info.sampleptrs [i], wps->wphdr.block_samples, 0);
#else #else
best_bits = log2buffer (sampleptrs [i], wps->wphdr.block_samples); info.best_bits = log2buffer (info.sampleptrs [i], wps->wphdr.block_samples, 0);
#endif #endif
CLEAR (wps->decorr_passes); CLEAR (wps->decorr_passes);
memcpy (wps->decorr_passes, dps, sizeof (dps [0]) * i); memcpy (wps->decorr_passes, info.dps, sizeof (info.dps [0]) * i);
memcpy (sampleptrs [nterms + 1], sampleptrs [i], wps->wphdr.block_samples * 4); memcpy (info.sampleptrs [info.nterms + 1], info.sampleptrs [i], wps->wphdr.block_samples * 4);
} }
if (wpc->config.extra_flags & EXTRA_BRANCHES) if (wpc->config.extra_flags & EXTRA_BRANCHES)
recurse_mono (wpc, sampleptrs, dps, 0, nterms, (int) floor (wps->delta_decay + 0.5), recurse_mono (wpc, &info, 0, (int) floor (wps->delta_decay + 0.5),
log2buffer (sampleptrs [0], wps->wphdr.block_samples), &best_bits); log2buffer (info.sampleptrs [0], wps->wphdr.block_samples, 0));
if (wpc->config.extra_flags & EXTRA_SORT_FIRST) if (wpc->config.extra_flags & EXTRA_SORT_FIRST)
sort_mono (wpc, sampleptrs, dps, nterms, &best_bits); sort_mono (wpc, &info);
if (wpc->config.extra_flags & EXTRA_TRY_DELTAS) { if (wpc->config.extra_flags & EXTRA_TRY_DELTAS) {
delta_mono (wpc, sampleptrs, dps, nterms, &best_bits); delta_mono (wpc, &info);
if ((wpc->config.extra_flags & EXTRA_ADJUST_DELTAS) && wps->decorr_passes [0].term) if ((wpc->config.extra_flags & EXTRA_ADJUST_DELTAS) && wps->decorr_passes [0].term)
wps->delta_decay = (wps->delta_decay * 2.0 + wps->decorr_passes [0].delta) / 3.0; wps->delta_decay = (wps->delta_decay * 2.0 + wps->decorr_passes [0].delta) / 3.0;
@ -505,32 +505,32 @@ void analyze_mono (WavpackContext *wpc, int32_t *samples)
} }
if (wpc->config.extra_flags & EXTRA_SORT_LAST) if (wpc->config.extra_flags & EXTRA_SORT_LAST)
sort_mono (wpc, sampleptrs, dps, nterms, &best_bits); sort_mono (wpc, &info);
#if 0 #if 0
memcpy (dps, wps->decorr_passes, sizeof (dps)); memcpy (info.dps, wps->decorr_passes, sizeof (info.dps));
for (i = 0; i < nterms && dps [i].term; ++i) for (i = 0; i < info.nterms && info.dps [i].term; ++i)
decorr_mono_pass (sampleptrs [i], sampleptrs [i + 1], wps->wphdr.block_samples, dps + i, 1); decorr_mono_pass (info.sampleptrs [i], info.sampleptrs [i + 1], wps->wphdr.block_samples, info.dps + i, 1);
if (log2buffer (sampleptrs [i], wps->wphdr.block_samples) != best_bits) if (log2buffer (info.sampleptrs [i], wps->wphdr.block_samples, 0) != info.best_bits)
error_line ("(1) samples do not match!"); error_line ("(1) samples do not match!");
if (log2buffer (sampleptrs [nterms + 1], wps->wphdr.block_samples) != best_bits) if (log2buffer (info.sampleptrs [info.nterms + 1], wps->wphdr.block_samples, 0) != info.best_bits)
error_line ("(2) samples do not match!"); error_line ("(2) samples do not match!");
#endif #endif
scan_word (wps, sampleptrs [nterms + 1], wps->wphdr.block_samples, -1); scan_word (wps, info.sampleptrs [info.nterms + 1], wps->wphdr.block_samples, -1);
#ifdef EXTRA_DUMP #ifdef EXTRA_DUMP
if (wpc->config.extra_flags & EXTRA_DUMP_TERMS) { if (1) {
char string [256], substring [20]; char string [256], substring [20];
int i; int i;
sprintf (string, "M: delta = %.4f%%, terms =", sprintf (string, "M: delta = %.4f%%, terms =",
((double) best_bits - default_bits) / 256.0 / wps->wphdr.block_samples / 32.0 * 100.0); ((double) info.best_bits - default_bits) / 256.0 / wps->wphdr.block_samples / 32.0 * 100.0);
for (i = 0; i < nterms; ++i) { for (i = 0; i < info.nterms; ++i) {
if (wps->decorr_passes [i].term) { if (wps->decorr_passes [i].term) {
if (i && wps->decorr_passes [i-1].delta == wps->decorr_passes [i].delta) if (i && wps->decorr_passes [i-1].delta == wps->decorr_passes [i].delta)
sprintf (substring, " %d", wps->decorr_passes [i].term); sprintf (substring, " %d", wps->decorr_passes [i].term);
@ -548,16 +548,12 @@ void analyze_mono (WavpackContext *wpc, int32_t *samples)
} }
#endif #endif
for (i = 0; i < nterms; ++i) for (i = 0; i < info.nterms; ++i)
if (!wps->decorr_passes [i].term) if (!wps->decorr_passes [i].term)
break; break;
wps->num_terms = i; wps->num_terms = i;
for (i = 0; i < nterms + 2; ++i) for (i = 0; i < info.nterms + 2; ++i)
free (sampleptrs [i]); free (info.sampleptrs [i]);
#ifdef MINMAX_WEIGHTS
error_line ("weight range = %ld (%d) to %ld (%d)", min_weight, min_term, max_weight, max_term);
#endif
} }

View File

@ -17,7 +17,8 @@
#include <string.h> #include <string.h>
#include <math.h> #include <math.h>
// #define EXTRA_DUMP #define LOG_LIMIT 6912
//#define EXTRA_DUMP
#ifdef DEBUG_ALLOC #ifdef DEBUG_ALLOC
#define malloc malloc_db #define malloc malloc_db
@ -29,25 +30,23 @@ void free_db (void *ptr);
int32_t dump_alloc (void); int32_t dump_alloc (void);
#endif #endif
extern const char default_terms [], high_terms [], fast_terms []; //////////////////////////////// local tables ///////////////////////////////
// #define MINMAX_WEIGHTS typedef struct {
int32_t *sampleptrs [MAX_NTERMS+2];
struct decorr_pass dps [MAX_NTERMS];
int nterms, log_limit;
uint32_t best_bits;
} WavpackExtraInfo;
#ifdef MINMAX_WEIGHTS extern const signed char default_terms [], high_terms [], fast_terms [];
static int32_t min_weight, max_weight;
static int min_term, max_term;
#endif
static void decorr_stereo_pass (int32_t *in_samples, int32_t *out_samples, int32_t num_samples, struct decorr_pass *dpp, int dir) static void decorr_stereo_pass (int32_t *in_samples, int32_t *out_samples, int32_t num_samples, struct decorr_pass *dpp, int dir)
{ {
int m = 0; int m = 0, i;
dpp->sum_A = dpp->sum_B = 0; dpp->sum_A = dpp->sum_B = 0;
#ifdef MINMAX_WEIGHTS
dpp->min = dpp->max = 0;
#endif
if (dir < 0) { if (dir < 0) {
out_samples += (num_samples - 1) * 2; out_samples += (num_samples - 1) * 2;
in_samples += (num_samples - 1) * 2; in_samples += (num_samples - 1) * 2;
@ -56,6 +55,14 @@ static void decorr_stereo_pass (int32_t *in_samples, int32_t *out_samples, int32
else else
dir = 2; dir = 2;
dpp->weight_A = restore_weight (store_weight (dpp->weight_A));
dpp->weight_B = restore_weight (store_weight (dpp->weight_B));
for (i = 0; i < 8; ++i) {
dpp->samples_A [i] = exp2s (log2s (dpp->samples_A [i]));
dpp->samples_B [i] = exp2s (log2s (dpp->samples_B [i]));
}
if (dpp->term == 17) { if (dpp->term == 17) {
while (num_samples--) { while (num_samples--) {
int32_t left, right; int32_t left, right;
@ -76,13 +83,6 @@ static void decorr_stereo_pass (int32_t *in_samples, int32_t *out_samples, int32
update_weight (dpp->weight_B, dpp->delta, sam_B, right); update_weight (dpp->weight_B, dpp->delta, sam_B, right);
dpp->sum_B += dpp->weight_B; dpp->sum_B += dpp->weight_B;
out_samples [1] = right; out_samples [1] = right;
#ifdef MINMAX_WEIGHTS
if (dpp->weight_A > dpp->max) dpp->max = dpp->weight_A;
if (dpp->weight_B > dpp->max) dpp->max = dpp->weight_B;
if (dpp->weight_A < dpp->min) dpp->min = dpp->weight_A;
if (dpp->weight_B < dpp->min) dpp->min = dpp->weight_B;
#endif
in_samples += dir; in_samples += dir;
out_samples += dir; out_samples += dir;
} }
@ -107,13 +107,6 @@ static void decorr_stereo_pass (int32_t *in_samples, int32_t *out_samples, int32
update_weight (dpp->weight_B, dpp->delta, sam_B, right); update_weight (dpp->weight_B, dpp->delta, sam_B, right);
dpp->sum_B += dpp->weight_B; dpp->sum_B += dpp->weight_B;
out_samples [1] = right; out_samples [1] = right;
#ifdef MINMAX_WEIGHTS
if (dpp->weight_A > dpp->max) dpp->max = dpp->weight_A;
if (dpp->weight_B > dpp->max) dpp->max = dpp->weight_B;
if (dpp->weight_A < dpp->min) dpp->min = dpp->weight_A;
if (dpp->weight_B < dpp->min) dpp->min = dpp->weight_B;
#endif
in_samples += dir; in_samples += dir;
out_samples += dir; out_samples += dir;
} }
@ -137,13 +130,6 @@ static void decorr_stereo_pass (int32_t *in_samples, int32_t *out_samples, int32
update_weight (dpp->weight_B, dpp->delta, sam_B, right); update_weight (dpp->weight_B, dpp->delta, sam_B, right);
dpp->sum_B += dpp->weight_B; dpp->sum_B += dpp->weight_B;
out_samples [1] = right; out_samples [1] = right;
#ifdef MINMAX_WEIGHTS
if (dpp->weight_A > dpp->max) dpp->max = dpp->weight_A;
if (dpp->weight_B > dpp->max) dpp->max = dpp->weight_B;
if (dpp->weight_A < dpp->min) dpp->min = dpp->weight_A;
if (dpp->weight_B < dpp->min) dpp->min = dpp->weight_B;
#endif
in_samples += dir; in_samples += dir;
out_samples += dir; out_samples += dir;
m = (m + 1) & (MAX_TERM - 1); m = (m + 1) & (MAX_TERM - 1);
@ -162,12 +148,6 @@ static void decorr_stereo_pass (int32_t *in_samples, int32_t *out_samples, int32
update_weight_clip (dpp->weight_A, dpp->delta, sam_A, left); update_weight_clip (dpp->weight_A, dpp->delta, sam_A, left);
dpp->sum_A += dpp->weight_A; dpp->sum_A += dpp->weight_A;
dpp->sum_B += dpp->weight_B; dpp->sum_B += dpp->weight_B;
#ifdef MINMAX_WEIGHTS
if (dpp->weight_A > dpp->max) dpp->max = dpp->weight_A;
if (dpp->weight_B > dpp->max) dpp->max = dpp->weight_B;
if (dpp->weight_A < dpp->min) dpp->min = dpp->weight_A;
if (dpp->weight_B < dpp->min) dpp->min = dpp->weight_B;
#endif
out_samples [0] = left; out_samples [0] = left;
out_samples [1] = right; out_samples [1] = right;
in_samples += dir; in_samples += dir;
@ -187,12 +167,6 @@ static void decorr_stereo_pass (int32_t *in_samples, int32_t *out_samples, int32
update_weight_clip (dpp->weight_B, dpp->delta, sam_B, right); update_weight_clip (dpp->weight_B, dpp->delta, sam_B, right);
dpp->sum_A += dpp->weight_A; dpp->sum_A += dpp->weight_A;
dpp->sum_B += dpp->weight_B; dpp->sum_B += dpp->weight_B;
#ifdef MINMAX_WEIGHTS
if (dpp->weight_A > dpp->max) dpp->max = dpp->weight_A;
if (dpp->weight_B > dpp->max) dpp->max = dpp->weight_B;
if (dpp->weight_A < dpp->min) dpp->min = dpp->weight_A;
if (dpp->weight_B < dpp->min) dpp->min = dpp->weight_B;
#endif
out_samples [0] = left; out_samples [0] = left;
out_samples [1] = right; out_samples [1] = right;
in_samples += dir; in_samples += dir;
@ -213,12 +187,6 @@ static void decorr_stereo_pass (int32_t *in_samples, int32_t *out_samples, int32
update_weight_clip (dpp->weight_B, dpp->delta, sam_B, right); update_weight_clip (dpp->weight_B, dpp->delta, sam_B, right);
dpp->sum_A += dpp->weight_A; dpp->sum_A += dpp->weight_A;
dpp->sum_B += dpp->weight_B; dpp->sum_B += dpp->weight_B;
#ifdef MINMAX_WEIGHTS
if (dpp->weight_A > dpp->max) dpp->max = dpp->weight_A;
if (dpp->weight_B > dpp->max) dpp->max = dpp->weight_B;
if (dpp->weight_A < dpp->min) dpp->min = dpp->weight_A;
if (dpp->weight_B < dpp->min) dpp->min = dpp->weight_B;
#endif
out_samples [0] = left; out_samples [0] = left;
out_samples [1] = right; out_samples [1] = right;
in_samples += dir; in_samples += dir;
@ -226,13 +194,6 @@ static void decorr_stereo_pass (int32_t *in_samples, int32_t *out_samples, int32
} }
} }
#ifdef MINMAX_WEIGHTS
if (dpp->term != 0) {
if (dpp->max > max_weight) { max_weight = dpp->max; max_term = dpp->term; }
if (dpp->min < min_weight) { min_weight = dpp->min; min_term = dpp->term; }
}
#endif
if (m && dpp->term > 0 && dpp->term <= MAX_TERM) { if (m && dpp->term > 0 && dpp->term <= MAX_TERM) {
int32_t temp_A [MAX_TERM], temp_B [MAX_TERM]; int32_t temp_A [MAX_TERM], temp_B [MAX_TERM];
int k; int k;
@ -292,9 +253,6 @@ static void reverse_decorr (struct decorr_pass *dpp)
dpp->samples_B [j] ^= dpp->samples_B [i]; dpp->samples_B [j] ^= dpp->samples_B [i];
dpp->samples_B [i++] ^= dpp->samples_B [j--]; dpp->samples_B [i++] ^= dpp->samples_B [j--];
} }
// CLEAR (dpp->samples_A);
// CLEAR (dpp->samples_B);
} }
else if (dpp->term == -1) { else if (dpp->term == -1) {
} }
@ -304,11 +262,11 @@ static void reverse_decorr (struct decorr_pass *dpp)
} }
} }
static void decorr_stereo_buffer (int32_t *samples, int32_t *outsamples, int32_t num_samples, struct decorr_pass *dpp) static void decorr_stereo_buffer (int32_t *samples, int32_t *outsamples, int32_t num_samples, struct decorr_pass *dpp, int tindex)
{ {
int delta = dpp->delta, pre_delta; struct decorr_pass dp, *dppi = dpp + tindex;
int term = dpp->term; int delta = dppi->delta, pre_delta;
struct decorr_pass dp; int term = dppi->term;
if (delta == 7) if (delta == 7)
pre_delta = 7; pre_delta = 7;
@ -322,48 +280,54 @@ static void decorr_stereo_buffer (int32_t *samples, int32_t *outsamples, int32_t
dp.delta = pre_delta; dp.delta = pre_delta;
decorr_stereo_pass (samples, outsamples, num_samples > 2048 ? 2048 : num_samples, &dp, -1); decorr_stereo_pass (samples, outsamples, num_samples > 2048 ? 2048 : num_samples, &dp, -1);
dp.delta = delta; dp.delta = delta;
reverse_decorr (&dp);
memcpy (dpp->samples_A, dp.samples_A, sizeof (dp.samples_A)); if (tindex == 0)
memcpy (dpp->samples_B, dp.samples_B, sizeof (dp.samples_B)); reverse_decorr (&dp);
dpp->weight_A = dp.weight_A; else {
dpp->weight_B = dp.weight_B; CLEAR (dp.samples_A);
CLEAR (dp.samples_B);
}
memcpy (dppi->samples_A, dp.samples_A, sizeof (dp.samples_A));
memcpy (dppi->samples_B, dp.samples_B, sizeof (dp.samples_B));
dppi->weight_A = dp.weight_A;
dppi->weight_B = dp.weight_B;
if (delta == 0) { if (delta == 0) {
dp.delta = 1; dp.delta = 1;
decorr_stereo_pass (samples, outsamples, num_samples, &dp, 1); decorr_stereo_pass (samples, outsamples, num_samples, &dp, 1);
dp.delta = 0; dp.delta = 0;
memcpy (dp.samples_A, dpp->samples_A, sizeof (dp.samples_A)); memcpy (dp.samples_A, dppi->samples_A, sizeof (dp.samples_A));
memcpy (dp.samples_B, dpp->samples_B, sizeof (dp.samples_B)); memcpy (dp.samples_B, dppi->samples_B, sizeof (dp.samples_B));
dpp->weight_A = dp.weight_A = dp.sum_A / num_samples; dppi->weight_A = dp.weight_A = dp.sum_A / num_samples;
dpp->weight_B = dp.weight_B = dp.sum_B / num_samples; dppi->weight_B = dp.weight_B = dp.sum_B / num_samples;
} }
// if (memcmp (dpp, &dp, sizeof (dp))) // if (memcmp (dppi, &dp, sizeof (dp)))
// error_line ("decorr_passes don't match, delta = %d", delta); // error_line ("decorr_passes don't match, delta = %d", delta);
decorr_stereo_pass (samples, outsamples, num_samples, &dp, 1); decorr_stereo_pass (samples, outsamples, num_samples, &dp, 1);
} }
static void recurse_stereo (WavpackContext *wpc, int32_t *sampleptrs[], struct decorr_pass dps[], static void recurse_stereo (WavpackContext *wpc, WavpackExtraInfo *info, int depth, int delta, uint32_t input_bits)
int depth, int nterms, int delta, uint32_t input_bits, uint32_t *best_bits)
{ {
WavpackStream *wps = wpc->streams [wpc->current_stream]; WavpackStream *wps = wpc->streams [wpc->current_stream];
int term, branches = ((wpc->config.extra_flags & EXTRA_BRANCHES) >> 6) - depth; int term, branches = ((wpc->config.extra_flags & EXTRA_BRANCHES) >> 6) - depth;
int32_t *samples, *outsamples; int32_t *samples, *outsamples;
uint32_t term_bits [22], bits; uint32_t term_bits [22], bits;
if (branches < 1 || depth + 1 == nterms) if (branches < 1 || depth + 1 == info->nterms)
branches = 1; branches = 1;
CLEAR (term_bits); CLEAR (term_bits);
samples = sampleptrs [depth]; samples = info->sampleptrs [depth];
outsamples = sampleptrs [depth + 1]; outsamples = info->sampleptrs [depth + 1];
for (term = -3; term <= 18; ++term) { for (term = -3; term <= 18; ++term) {
if (!term) if (!term)
continue; continue;
if (term == 17 && branches == 1 && depth + 1 < nterms) if (term == 17 && branches == 1 && depth + 1 < info->nterms)
continue; continue;
if (term == -1 || term == -2) if (term == -1 || term == -2)
@ -377,22 +341,22 @@ static void recurse_stereo (WavpackContext *wpc, int32_t *sampleptrs[], struct d
if ((wpc->config.flags & CONFIG_FAST_FLAG) && (term >= 5 && term <= 16)) if ((wpc->config.flags & CONFIG_FAST_FLAG) && (term >= 5 && term <= 16))
continue; continue;
dps [depth].term = term; info->dps [depth].term = term;
dps [depth].delta = delta; info->dps [depth].delta = delta;
decorr_stereo_buffer (samples, outsamples, wps->wphdr.block_samples, &dps [depth]); decorr_stereo_buffer (samples, outsamples, wps->wphdr.block_samples, info->dps, depth);
bits = log2buffer (outsamples, wps->wphdr.block_samples * 2); bits = log2buffer (outsamples, wps->wphdr.block_samples * 2, info->log_limit);
if (bits < *best_bits) { if (bits < info->best_bits) {
*best_bits = bits; info->best_bits = bits;
CLEAR (wps->decorr_passes); CLEAR (wps->decorr_passes);
memcpy (wps->decorr_passes, dps, sizeof (dps [0]) * (depth + 1)); memcpy (wps->decorr_passes, info->dps, sizeof (info->dps [0]) * (depth + 1));
memcpy (sampleptrs [nterms + 1], sampleptrs [depth + 1], wps->wphdr.block_samples * 8); memcpy (info->sampleptrs [info->nterms + 1], info->sampleptrs [depth + 1], wps->wphdr.block_samples * 8);
} }
term_bits [term + 3] = bits; term_bits [term + 3] = bits;
} }
while (depth + 1 < nterms && branches--) { while (depth + 1 < info->nterms && branches--) {
uint32_t local_best_bits = input_bits; uint32_t local_best_bits = input_bits;
int best_term = 0, i; int best_term = 0, i;
@ -406,19 +370,18 @@ static void recurse_stereo (WavpackContext *wpc, int32_t *sampleptrs[], struct d
if (!best_term) if (!best_term)
break; break;
dps [depth].term = best_term; info->dps [depth].term = best_term;
dps [depth].delta = delta; info->dps [depth].delta = delta;
decorr_stereo_buffer (samples, outsamples, wps->wphdr.block_samples, &dps [depth]); decorr_stereo_buffer (samples, outsamples, wps->wphdr.block_samples, info->dps, depth);
// if (log2buffer (outsamples, wps->wphdr.block_samples * 2) != local_best_bits) // if (log2buffer (outsamples, wps->wphdr.block_samples * 2, 0) != local_best_bits)
// error_line ("data doesn't match!"); // error_line ("data doesn't match!");
recurse_stereo (wpc, sampleptrs, dps, depth + 1, nterms, delta, local_best_bits, best_bits); recurse_stereo (wpc, info, depth + 1, delta, local_best_bits);
} }
} }
static void delta_stereo (WavpackContext *wpc, int32_t *sampleptrs[], struct decorr_pass dps[], static void delta_stereo (WavpackContext *wpc, WavpackExtraInfo *info)
int nterms, uint32_t *best_bits)
{ {
WavpackStream *wps = wpc->streams [wpc->current_stream]; WavpackStream *wps = wpc->streams [wpc->current_stream];
int lower = FALSE; int lower = FALSE;
@ -436,20 +399,20 @@ static void delta_stereo (WavpackContext *wpc, int32_t *sampleptrs[], struct dec
if (!d && (wps->wphdr.flags & HYBRID_FLAG)) if (!d && (wps->wphdr.flags & HYBRID_FLAG))
break; break;
for (i = 0; i < nterms && wps->decorr_passes [i].term; ++i) { for (i = 0; i < info->nterms && wps->decorr_passes [i].term; ++i) {
dps [i].term = wps->decorr_passes [i].term; info->dps [i].term = wps->decorr_passes [i].term;
dps [i].delta = d; info->dps [i].delta = d;
decorr_stereo_buffer (sampleptrs [i], sampleptrs [i+1], wps->wphdr.block_samples, &dps [i]); decorr_stereo_buffer (info->sampleptrs [i], info->sampleptrs [i+1], wps->wphdr.block_samples, info->dps, i);
} }
bits = log2buffer (sampleptrs [i], wps->wphdr.block_samples * 2); bits = log2buffer (info->sampleptrs [i], wps->wphdr.block_samples * 2, info->log_limit);
if (bits < *best_bits) { if (bits < info->best_bits) {
lower = TRUE; lower = TRUE;
*best_bits = bits; info->best_bits = bits;
CLEAR (wps->decorr_passes); CLEAR (wps->decorr_passes);
memcpy (wps->decorr_passes, dps, sizeof (dps [0]) * i); memcpy (wps->decorr_passes, info->dps, sizeof (info->dps [0]) * i);
memcpy (sampleptrs [nterms + 1], sampleptrs [i], wps->wphdr.block_samples * 8); memcpy (info->sampleptrs [info->nterms + 1], info->sampleptrs [i], wps->wphdr.block_samples * 8);
} }
else else
break; break;
@ -458,27 +421,26 @@ static void delta_stereo (WavpackContext *wpc, int32_t *sampleptrs[], struct dec
for (d = delta + 1; !lower && d <= 7; ++d) { for (d = delta + 1; !lower && d <= 7; ++d) {
int i; int i;
for (i = 0; i < nterms && wps->decorr_passes [i].term; ++i) { for (i = 0; i < info->nterms && wps->decorr_passes [i].term; ++i) {
dps [i].term = wps->decorr_passes [i].term; info->dps [i].term = wps->decorr_passes [i].term;
dps [i].delta = d; info->dps [i].delta = d;
decorr_stereo_buffer (sampleptrs [i], sampleptrs [i+1], wps->wphdr.block_samples, &dps [i]); decorr_stereo_buffer (info->sampleptrs [i], info->sampleptrs [i+1], wps->wphdr.block_samples, info->dps, i);
} }
bits = log2buffer (sampleptrs [i], wps->wphdr.block_samples * 2); bits = log2buffer (info->sampleptrs [i], wps->wphdr.block_samples * 2, info->log_limit);
if (bits < *best_bits) { if (bits < info->best_bits) {
*best_bits = bits; info->best_bits = bits;
CLEAR (wps->decorr_passes); CLEAR (wps->decorr_passes);
memcpy (wps->decorr_passes, dps, sizeof (dps [0]) * i); memcpy (wps->decorr_passes, info->dps, sizeof (info->dps [0]) * i);
memcpy (sampleptrs [nterms + 1], sampleptrs [i], wps->wphdr.block_samples * 8); memcpy (info->sampleptrs [info->nterms + 1], info->sampleptrs [i], wps->wphdr.block_samples * 8);
} }
else else
break; break;
} }
} }
static void sort_stereo (WavpackContext *wpc, int32_t *sampleptrs[], struct decorr_pass dps[], static void sort_stereo (WavpackContext *wpc, WavpackExtraInfo *info)
int nterms, uint32_t *best_bits)
{ {
WavpackStream *wps = wpc->streams [wpc->current_stream]; WavpackStream *wps = wpc->streams [wpc->current_stream];
int reversed = TRUE; int reversed = TRUE;
@ -487,38 +449,38 @@ static void sort_stereo (WavpackContext *wpc, int32_t *sampleptrs[], struct deco
while (reversed) { while (reversed) {
int ri, i; int ri, i;
memcpy (dps, wps->decorr_passes, sizeof (wps->decorr_passes)); memcpy (info->dps, wps->decorr_passes, sizeof (wps->decorr_passes));
reversed = FALSE; reversed = FALSE;
for (ri = 0; ri < nterms && wps->decorr_passes [ri].term; ++ri) { for (ri = 0; ri < info->nterms && wps->decorr_passes [ri].term; ++ri) {
if (ri + 1 >= nterms || !wps->decorr_passes [ri+1].term) if (ri + 1 >= info->nterms || !wps->decorr_passes [ri+1].term)
break; break;
if (wps->decorr_passes [ri].term == wps->decorr_passes [ri+1].term) { if (wps->decorr_passes [ri].term == wps->decorr_passes [ri+1].term) {
decorr_stereo_buffer (sampleptrs [ri], sampleptrs [ri+1], wps->wphdr.block_samples, &dps [ri]); decorr_stereo_buffer (info->sampleptrs [ri], info->sampleptrs [ri+1], wps->wphdr.block_samples, info->dps, ri);
continue; continue;
} }
dps [ri] = wps->decorr_passes [ri+1]; info->dps [ri] = wps->decorr_passes [ri+1];
dps [ri+1] = wps->decorr_passes [ri]; info->dps [ri+1] = wps->decorr_passes [ri];
for (i = ri; i < nterms && wps->decorr_passes [i].term; ++i) for (i = ri; i < info->nterms && wps->decorr_passes [i].term; ++i)
decorr_stereo_buffer (sampleptrs [i], sampleptrs [i+1], wps->wphdr.block_samples, &dps [i]); decorr_stereo_buffer (info->sampleptrs [i], info->sampleptrs [i+1], wps->wphdr.block_samples, info->dps, i);
bits = log2buffer (sampleptrs [i], wps->wphdr.block_samples * 2); bits = log2buffer (info->sampleptrs [i], wps->wphdr.block_samples * 2, info->log_limit);
if (bits < *best_bits) { if (bits < info->best_bits) {
reversed = TRUE; reversed = TRUE;
*best_bits = bits; info->best_bits = bits;
CLEAR (wps->decorr_passes); CLEAR (wps->decorr_passes);
memcpy (wps->decorr_passes, dps, sizeof (dps [0]) * i); memcpy (wps->decorr_passes, info->dps, sizeof (info->dps [0]) * i);
memcpy (sampleptrs [nterms + 1], sampleptrs [i], wps->wphdr.block_samples * 8); memcpy (info->sampleptrs [info->nterms + 1], info->sampleptrs [i], wps->wphdr.block_samples * 8);
} }
else { else {
dps [ri] = wps->decorr_passes [ri]; info->dps [ri] = wps->decorr_passes [ri];
dps [ri+1] = wps->decorr_passes [ri+1]; info->dps [ri+1] = wps->decorr_passes [ri+1];
decorr_stereo_buffer (sampleptrs [ri], sampleptrs [ri+1], wps->wphdr.block_samples, &dps [ri]); decorr_stereo_buffer (info->sampleptrs [ri], info->sampleptrs [ri+1], wps->wphdr.block_samples, info->dps, ri);
} }
} }
} }
@ -530,15 +492,23 @@ void analyze_stereo (WavpackContext *wpc, int32_t *samples)
{ {
WavpackStream *wps = wpc->streams [wpc->current_stream]; WavpackStream *wps = wpc->streams [wpc->current_stream];
#ifdef EXTRA_DUMP #ifdef EXTRA_DUMP
uint32_t bits, best_bits, default_bits, cnt; uint32_t bits, default_bits, cnt;
#else #else
uint32_t bits, best_bits, cnt; uint32_t bits, cnt;
#endif #endif
const char *decorr_terms = default_terms, *tp; const signed char *decorr_terms = default_terms, *tp;
int32_t *sampleptrs [MAX_NTERMS+2], *lptr; WavpackExtraInfo info;
struct decorr_pass dps [MAX_NTERMS]; int32_t *lptr;
int nterms, i; int i;
#ifdef LOG_LIMIT
info.log_limit = (((wps->wphdr.flags & MAG_MASK) >> MAG_LSB) + 4) * 256;
if (info.log_limit > LOG_LIMIT)
info.log_limit = LOG_LIMIT;
#else
info.log_limit = 0;
#endif
CLEAR (wps->decorr_passes); CLEAR (wps->decorr_passes);
cnt = wps->wphdr.block_samples * 2; cnt = wps->wphdr.block_samples * 2;
@ -559,104 +529,104 @@ void analyze_stereo (WavpackContext *wpc, int32_t *samples)
else if (wpc->config.flags & CONFIG_FAST_FLAG) else if (wpc->config.flags & CONFIG_FAST_FLAG)
decorr_terms = fast_terms; decorr_terms = fast_terms;
nterms = strlen (decorr_terms); info.nterms = strlen (decorr_terms);
if (wpc->config.extra_flags & EXTRA_TERMS) if (wpc->config.extra_flags & EXTRA_TERMS)
if ((nterms += (wpc->config.extra_flags & EXTRA_TERMS) >> 10) > MAX_NTERMS) if ((info.nterms += (wpc->config.extra_flags & EXTRA_TERMS) >> 10) > MAX_NTERMS)
nterms = MAX_NTERMS; info.nterms = MAX_NTERMS;
for (i = 0; i < nterms + 2; ++i) for (i = 0; i < info.nterms + 2; ++i)
sampleptrs [i] = malloc (wps->wphdr.block_samples * 8); info.sampleptrs [i] = malloc (wps->wphdr.block_samples * 8);
memcpy (sampleptrs [nterms + 1], samples, wps->wphdr.block_samples * 8); memcpy (info.sampleptrs [info.nterms + 1], samples, wps->wphdr.block_samples * 8);
best_bits = log2buffer (sampleptrs [nterms + 1], wps->wphdr.block_samples * 2); info.best_bits = log2buffer (info.sampleptrs [info.nterms + 1], wps->wphdr.block_samples * 2, 0);
if ((wpc->config.extra_flags & EXTRA_STEREO_MODES) || !(wps->wphdr.flags & JOINT_STEREO)) { if ((wpc->config.extra_flags & EXTRA_STEREO_MODES) || !(wps->wphdr.flags & JOINT_STEREO)) {
memcpy (sampleptrs [0], samples, wps->wphdr.block_samples * 8); memcpy (info.sampleptrs [0], samples, wps->wphdr.block_samples * 8);
CLEAR (dps); CLEAR (info.dps);
for (tp = decorr_terms, i = 0; *tp;) { for (tp = decorr_terms, i = 0; *tp;) {
if (*tp > 0 || (wps->wphdr.flags & CROSS_DECORR)) if (*tp > 0 || (wps->wphdr.flags & CROSS_DECORR))
dps [i].term = *tp++; info.dps [i].term = *tp++;
else { else {
dps [i].term = -3; info.dps [i].term = -3;
tp++; tp++;
} }
dps [i].delta = 2; info.dps [i].delta = 2;
decorr_stereo_buffer (sampleptrs [i], sampleptrs [i+1], wps->wphdr.block_samples, &dps [i]); decorr_stereo_buffer (info.sampleptrs [i], info.sampleptrs [i+1], wps->wphdr.block_samples, info.dps, i);
++i; ++i;
} }
#ifdef EXTRA_DUMP #ifdef EXTRA_DUMP
default_bits = bits = log2buffer (sampleptrs [i], wps->wphdr.block_samples * 2); default_bits = bits = log2buffer (info.sampleptrs [i], wps->wphdr.block_samples * 2, 0);
#else #else
bits = log2buffer (sampleptrs [i], wps->wphdr.block_samples * 2); bits = log2buffer (info.sampleptrs [i], wps->wphdr.block_samples * 2, 0);
#endif #endif
wps->wphdr.flags &= ~JOINT_STEREO; wps->wphdr.flags &= ~JOINT_STEREO;
if (bits < best_bits) { if (bits < info.best_bits) {
best_bits = bits; info.best_bits = bits;
CLEAR (wps->decorr_passes); CLEAR (wps->decorr_passes);
memcpy (wps->decorr_passes, dps, sizeof (dps [0]) * i); memcpy (wps->decorr_passes, info.dps, sizeof (info.dps [0]) * i);
memcpy (sampleptrs [nterms + 1], sampleptrs [i], wps->wphdr.block_samples * 8); memcpy (info.sampleptrs [info.nterms + 1], info.sampleptrs [i], wps->wphdr.block_samples * 8);
} }
} }
if ((wpc->config.extra_flags & EXTRA_STEREO_MODES) || (wps->wphdr.flags & JOINT_STEREO)) { if ((wpc->config.extra_flags & EXTRA_STEREO_MODES) || (wps->wphdr.flags & JOINT_STEREO)) {
memcpy (sampleptrs [0], samples, wps->wphdr.block_samples * 8); memcpy (info.sampleptrs [0], samples, wps->wphdr.block_samples * 8);
cnt = wps->wphdr.block_samples; cnt = wps->wphdr.block_samples;
lptr = sampleptrs [0]; lptr = info.sampleptrs [0];
while (cnt--) { while (cnt--) {
lptr [1] += ((lptr [0] -= lptr [1]) >> 1); lptr [1] += ((lptr [0] -= lptr [1]) >> 1);
lptr += 2; lptr += 2;
} }
CLEAR (dps); CLEAR (info.dps);
for (tp = decorr_terms, i = 0; *tp;) { for (tp = decorr_terms, i = 0; *tp;) {
if (*tp > 0 || (wps->wphdr.flags & CROSS_DECORR)) if (*tp > 0 || (wps->wphdr.flags & CROSS_DECORR))
dps [i].term = *tp++; info.dps [i].term = *tp++;
else { else {
dps [i].term = -3; info.dps [i].term = -3;
tp++; tp++;
} }
dps [i].delta = 2; info.dps [i].delta = 2;
decorr_stereo_buffer (sampleptrs [i], sampleptrs [i+1], wps->wphdr.block_samples, &dps [i]); decorr_stereo_buffer (info.sampleptrs [i], info.sampleptrs [i+1], wps->wphdr.block_samples, info.dps, i);
++i; ++i;
} }
#ifdef EXTRA_DUMP #ifdef EXTRA_DUMP
default_bits = bits = log2buffer (sampleptrs [i], wps->wphdr.block_samples * 2); default_bits = bits = log2buffer (info.sampleptrs [i], wps->wphdr.block_samples * 2, 0);
#else #else
bits = log2buffer (sampleptrs [i], wps->wphdr.block_samples * 2); bits = log2buffer (info.sampleptrs [i], wps->wphdr.block_samples * 2, 0);
#endif #endif
wps->wphdr.flags |= JOINT_STEREO; wps->wphdr.flags |= JOINT_STEREO;
if (bits < best_bits) { if (bits < info.best_bits) {
best_bits = bits; info.best_bits = bits;
CLEAR (wps->decorr_passes); CLEAR (wps->decorr_passes);
memcpy (wps->decorr_passes, dps, sizeof (dps [0]) * i); memcpy (wps->decorr_passes, info.dps, sizeof (info.dps [0]) * i);
memcpy (sampleptrs [nterms + 1], sampleptrs [i], wps->wphdr.block_samples * 8); memcpy (info.sampleptrs [info.nterms + 1], info.sampleptrs [i], wps->wphdr.block_samples * 8);
} }
else { else {
memcpy (sampleptrs [0], samples, wps->wphdr.block_samples * 8); memcpy (info.sampleptrs [0], samples, wps->wphdr.block_samples * 8);
wps->wphdr.flags &= ~JOINT_STEREO; wps->wphdr.flags &= ~JOINT_STEREO;
} }
} }
if ((wps->wphdr.flags & HYBRID_FLAG) && (wpc->config.extra_flags & EXTRA_ADVANCED)) { if ((wps->wphdr.flags & HYBRID_FLAG) && (wpc->config.extra_flags & EXTRA_ADVANCED)) {
int shaping_weight, new = wps->wphdr.flags & NEW_SHAPING; int shaping_weight, new = wps->wphdr.flags & NEW_SHAPING;
int32_t *rptr = sampleptrs [nterms + 1], error [2], temp; int32_t *rptr = info.sampleptrs [info.nterms + 1], error [2], temp;
scan_word (wps, rptr, wps->wphdr.block_samples, -1); scan_word (wps, rptr, wps->wphdr.block_samples, -1);
cnt = wps->wphdr.block_samples; cnt = wps->wphdr.block_samples;
lptr = sampleptrs [0]; lptr = info.sampleptrs [0];
CLEAR (error); CLEAR (error);
if (wps->wphdr.flags & HYBRID_SHAPE) { if (wps->wphdr.flags & HYBRID_SHAPE) {
@ -700,31 +670,31 @@ void analyze_stereo (WavpackContext *wpc, int32_t *samples)
rptr += 2; rptr += 2;
} }
memcpy (dps, wps->decorr_passes, sizeof (dps)); memcpy (info.dps, wps->decorr_passes, sizeof (info.dps));
for (i = 0; i < nterms && dps [i].term; ++i) for (i = 0; i < info.nterms && info.dps [i].term; ++i)
decorr_stereo_buffer (sampleptrs [i], sampleptrs [i + 1], wps->wphdr.block_samples, dps + i); decorr_stereo_buffer (info.sampleptrs [i], info.sampleptrs [i + 1], wps->wphdr.block_samples, info.dps, i);
#ifdef EXTRA_DUMP #ifdef EXTRA_DUMP
best_bits = default_bits = log2buffer (sampleptrs [i], wps->wphdr.block_samples * 2); info.best_bits = default_bits = log2buffer (info.sampleptrs [i], wps->wphdr.block_samples * 2, 0);
#else #else
best_bits = log2buffer (sampleptrs [i], wps->wphdr.block_samples * 2); info.best_bits = log2buffer (info.sampleptrs [i], wps->wphdr.block_samples * 2, 0);
#endif #endif
CLEAR (wps->decorr_passes); CLEAR (wps->decorr_passes);
memcpy (wps->decorr_passes, dps, sizeof (dps [0]) * i); memcpy (wps->decorr_passes, info.dps, sizeof (info.dps [0]) * i);
memcpy (sampleptrs [nterms + 1], sampleptrs [i], wps->wphdr.block_samples * 8); memcpy (info.sampleptrs [info.nterms + 1], info.sampleptrs [i], wps->wphdr.block_samples * 8);
} }
if (wpc->config.extra_flags & EXTRA_BRANCHES) if (wpc->config.extra_flags & EXTRA_BRANCHES)
recurse_stereo (wpc, sampleptrs, dps, 0, nterms, (int) floor (wps->delta_decay + 0.5), recurse_stereo (wpc, &info, 0, (int) floor (wps->delta_decay + 0.5),
log2buffer (sampleptrs [0], wps->wphdr.block_samples * 2), &best_bits); log2buffer (info.sampleptrs [0], wps->wphdr.block_samples * 2, 0));
if (wpc->config.extra_flags & EXTRA_SORT_FIRST) if (wpc->config.extra_flags & EXTRA_SORT_FIRST)
sort_stereo (wpc, sampleptrs, dps, nterms, &best_bits); sort_stereo (wpc, &info);
if (wpc->config.extra_flags & EXTRA_TRY_DELTAS) { if (wpc->config.extra_flags & EXTRA_TRY_DELTAS) {
delta_stereo (wpc, sampleptrs, dps, nterms, &best_bits); delta_stereo (wpc, &info);
if ((wpc->config.extra_flags & EXTRA_ADJUST_DELTAS) && wps->decorr_passes [0].term) if ((wpc->config.extra_flags & EXTRA_ADJUST_DELTAS) && wps->decorr_passes [0].term)
wps->delta_decay = (wps->delta_decay * 2.0 + wps->decorr_passes [0].delta) / 3.0; wps->delta_decay = (wps->delta_decay * 2.0 + wps->decorr_passes [0].delta) / 3.0;
@ -733,22 +703,22 @@ void analyze_stereo (WavpackContext *wpc, int32_t *samples)
} }
if (wpc->config.extra_flags & EXTRA_SORT_LAST) if (wpc->config.extra_flags & EXTRA_SORT_LAST)
sort_stereo (wpc, sampleptrs, dps, nterms, &best_bits); sort_stereo (wpc, &info);
#if 0 #if 0
memcpy (dps, wps->decorr_passes, sizeof (dps)); memcpy (info.dps, wps->decorr_passes, sizeof (info.dps));
for (i = 0; i < nterms && dps [i].term; ++i) for (i = 0; i < info.nterms && info.dps [i].term; ++i)
decorr_stereo_pass (sampleptrs [i], sampleptrs [i + 1], wps->wphdr.block_samples, dps + i, 1); decorr_stereo_pass (info.sampleptrs [i], info.sampleptrs [i + 1], wps->wphdr.block_samples, info.dps + i, 1);
if (log2buffer (sampleptrs [i], wps->wphdr.block_samples * 2) != best_bits) if (log2buffer (info.sampleptrs [i], wps->wphdr.block_samples * 2, 0) != info.best_bits)
error_line ("(1) samples do not match!"); error_line ("(1) samples do not match!");
if (log2buffer (sampleptrs [nterms + 1], wps->wphdr.block_samples * 2) != best_bits) if (log2buffer (info.sampleptrs [info.nterms + 1], wps->wphdr.block_samples * 2, 0) != info.best_bits)
error_line ("(2) samples do not match!"); error_line ("(2) samples do not match!");
#endif #endif
scan_word (wps, sampleptrs [nterms + 1], wps->wphdr.block_samples, -1); scan_word (wps, info.sampleptrs [info.nterms + 1], wps->wphdr.block_samples, -1);
#ifdef EXTRA_DUMP #ifdef EXTRA_DUMP
if (1) { if (1) {
@ -757,9 +727,9 @@ void analyze_stereo (WavpackContext *wpc, int32_t *samples)
sprintf (string, "%s: delta = %.4f%%, terms =", sprintf (string, "%s: delta = %.4f%%, terms =",
(wps->wphdr.flags & JOINT_STEREO) ? "JS" : "TS", (wps->wphdr.flags & JOINT_STEREO) ? "JS" : "TS",
((double) best_bits - default_bits) / 256.0 / wps->wphdr.block_samples / 32.0 * 100.0); ((double) info.best_bits - default_bits) / 256.0 / wps->wphdr.block_samples / 32.0 * 100.0);
for (i = 0; i < nterms; ++i) { for (i = 0; i < info.nterms; ++i) {
if (wps->decorr_passes [i].term) { if (wps->decorr_passes [i].term) {
if (i && wps->decorr_passes [i-1].delta == wps->decorr_passes [i].delta) if (i && wps->decorr_passes [i-1].delta == wps->decorr_passes [i].delta)
sprintf (substring, " %d", wps->decorr_passes [i].term); sprintf (substring, " %d", wps->decorr_passes [i].term);
@ -777,16 +747,12 @@ void analyze_stereo (WavpackContext *wpc, int32_t *samples)
} }
#endif #endif
for (i = 0; i < nterms; ++i) for (i = 0; i < info.nterms; ++i)
if (!wps->decorr_passes [i].term) if (!wps->decorr_passes [i].term)
break; break;
wps->num_terms = i; wps->num_terms = i;
for (i = 0; i < nterms + 2; ++i) for (i = 0; i < info.nterms + 2; ++i)
free (sampleptrs [i]); free (info.sampleptrs [i]);
#ifdef MINMAX_WEIGHTS
error_line ("weight range = %ld (%d) to %ld (%d)", min_weight, min_term, max_weight, max_term);
#endif
} }

View File

@ -346,6 +346,8 @@ static void float_values_nowvx (WavpackStream *wps, int32_t *values, int32_t num
} }
} }
#endif
void float_normalize (int32_t *values, int32_t num_values, int delta_exp) void float_normalize (int32_t *values, int32_t num_values, int delta_exp)
{ {
f32 *fvalues = (f32 *) values, fzero = { 0, 0, 0 }; f32 *fvalues = (f32 *) values, fzero = { 0, 0, 0 };
@ -367,5 +369,3 @@ void float_normalize (int32_t *values, int32_t num_values, int delta_exp)
fvalues++; fvalues++;
} }
} }
#endif

View File

@ -13,10 +13,10 @@ struct MD5Context {
unsigned char in[64]; unsigned char in[64];
}; };
extern void MD5Init(); extern void MD5Init (struct MD5Context *ctx);
extern void MD5Update(); extern void MD5Update (struct MD5Context *ctx, unsigned char *buf, unsigned len);
extern void MD5Final(); extern void MD5Final (unsigned char digest[16], struct MD5Context *ctx);
extern void MD5Transform(); extern void MD5Transform (uint32 buf[4], uint32 in[16]);
/* /*
* This is needed to make RSAREF happy on some MS-DOS compilers. * This is needed to make RSAREF happy on some MS-DOS compilers.

View File

@ -106,6 +106,9 @@ int process_metadata (WavpackContext *wpc, WavpackMetadata *wpmd)
case ID_CONFIG_BLOCK: case ID_CONFIG_BLOCK:
return read_config_info (wpc, wpmd); return read_config_info (wpc, wpmd);
case ID_SAMPLE_RATE:
return read_sample_rate (wpc, wpmd);
case ID_WV_BITSTREAM: case ID_WV_BITSTREAM:
return init_wv_bitstream (wps, wpmd); return init_wv_bitstream (wps, wpmd);
@ -268,7 +271,7 @@ int write_metadata_block (WavpackContext *wpc)
CLEAR (*wphdr); CLEAR (*wphdr);
memcpy (wphdr->ckID, "wvpk", 4); memcpy (wphdr->ckID, "wvpk", 4);
wphdr->total_samples = wpc->total_samples; wphdr->total_samples = wpc->total_samples;
wphdr->version = 0x403; wphdr->version = wpc->stream_version;
wphdr->ckSize = block_size - 8; wphdr->ckSize = block_size - 8;
wphdr->block_samples = 0; wphdr->block_samples = 0;

View File

@ -42,9 +42,9 @@ int32_t dump_alloc (void);
// 17 & 18 are special functions using the previous 2 samples, and negative // 17 & 18 are special functions using the previous 2 samples, and negative
// values indicate cross channel decorrelation (in stereo only). // values indicate cross channel decorrelation (in stereo only).
const char default_terms [] = { 18,18,2,3,-2,0 }; const signed char default_terms [] = { 18,18,2,3,-2,0 };
const char high_terms [] = { 18,18,2,3,-2,18,2,4,7,5,3,6,8,-1,18,2,0 }; const signed char high_terms [] = { 18,18,2,3,-2,18,2,4,7,5,3,6,8,-1,18,2,0 };
const char fast_terms [] = { 17,17,0 }; const signed char fast_terms [] = { 17,17,0 };
///////////////////////////// executable code //////////////////////////////// ///////////////////////////// executable code ////////////////////////////////
@ -55,9 +55,6 @@ void pack_init (WavpackContext *wpc)
{ {
WavpackStream *wps = wpc->streams [wpc->current_stream]; WavpackStream *wps = wpc->streams [wpc->current_stream];
uint32_t flags = wps->wphdr.flags; uint32_t flags = wps->wphdr.flags;
struct decorr_pass *dpp;
const char *term_string;
int ti;
wps->sample_index = 0; wps->sample_index = 0;
wps->delta_decay = 2.0; wps->delta_decay = 2.0;
@ -76,24 +73,6 @@ void pack_init (WavpackContext *wpc)
wps->dc.shaping_acc [0] = wps->dc.shaping_acc [1] = weight << 16; wps->dc.shaping_acc [0] = wps->dc.shaping_acc [1] = weight << 16;
} }
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; ti < strlen (term_string); 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); init_words (wps);
} }
@ -123,18 +102,29 @@ void write_decorr_terms (WavpackStream *wps, WavpackMetadata *wpmd)
void write_decorr_weights (WavpackStream *wps, WavpackMetadata *wpmd) void write_decorr_weights (WavpackStream *wps, WavpackMetadata *wpmd)
{ {
int tcount = wps->num_terms; struct decorr_pass *dpp = wps->decorr_passes;
struct decorr_pass *dpp; int tcount = wps->num_terms, i;
char *byteptr; char *byteptr;
byteptr = wpmd->data = malloc ((tcount * 2) + 1); byteptr = wpmd->data = malloc ((tcount * 2) + 1);
wpmd->id = ID_DECORR_WEIGHTS; wpmd->id = ID_DECORR_WEIGHTS;
for (dpp = wps->decorr_passes; tcount--; ++dpp) { for (i = wps->num_terms - 1; i >= 0; --i)
dpp->weight_A = restore_weight (*byteptr++ = store_weight (dpp->weight_A)); if (store_weight (dpp [i].weight_A) ||
(!(wps->wphdr.flags & MONO_DATA) && store_weight (dpp [i].weight_B)))
break;
if (!(wps->wphdr.flags & MONO_FLAG)) tcount = i + 1;
dpp->weight_B = restore_weight (*byteptr++ = store_weight (dpp->weight_B));
for (i = 0; i < wps->num_terms; ++i) {
if (i < tcount) {
dpp [i].weight_A = restore_weight (*byteptr++ = store_weight (dpp [i].weight_A));
if (!(wps->wphdr.flags & MONO_DATA))
dpp [i].weight_B = restore_weight (*byteptr++ = store_weight (dpp [i].weight_B));
}
else
dpp [i].weight_A = dpp [i].weight_B = 0;
} }
wpmd->byte_length = byteptr - (char *) wpmd->data; wpmd->byte_length = byteptr - (char *) wpmd->data;
@ -170,7 +160,7 @@ void write_decorr_samples (WavpackStream *wps, WavpackMetadata *wpmd)
*byteptr++ = temp; *byteptr++ = temp;
*byteptr++ = temp >> 8; *byteptr++ = temp >> 8;
if (!(wps->wphdr.flags & MONO_FLAG)) { if (!(wps->wphdr.flags & MONO_DATA)) {
dpp->samples_B [0] = exp2s (temp = log2s (dpp->samples_B [0])); dpp->samples_B [0] = exp2s (temp = log2s (dpp->samples_B [0]));
*byteptr++ = temp; *byteptr++ = temp;
*byteptr++ = temp >> 8; *byteptr++ = temp >> 8;
@ -195,7 +185,7 @@ void write_decorr_samples (WavpackStream *wps, WavpackMetadata *wpmd)
*byteptr++ = temp; *byteptr++ = temp;
*byteptr++ = temp >> 8; *byteptr++ = temp >> 8;
if (!(wps->wphdr.flags & MONO_FLAG)) { if (!(wps->wphdr.flags & MONO_DATA)) {
dpp->samples_B [m] = exp2s (temp = log2s (dpp->samples_B [m])); dpp->samples_B [m] = exp2s (temp = log2s (dpp->samples_B [m]));
*byteptr++ = temp; *byteptr++ = temp;
*byteptr++ = temp >> 8; *byteptr++ = temp >> 8;
@ -226,13 +216,6 @@ void write_shaping_info (WavpackStream *wps, WavpackMetadata *wpmd)
char *byteptr; char *byteptr;
int temp; int temp;
#if 0
if (wps->wphdr.block_samples) {
wps->dc.shaping_delta [0] = (-wps->dc.shaping_acc [0] - wps->dc.shaping_acc [0]) / (int32_t) wps->wphdr.block_samples;
wps->dc.shaping_delta [1] = (-wps->dc.shaping_acc [1] - wps->dc.shaping_acc [1]) / (int32_t) wps->wphdr.block_samples;
}
#endif
byteptr = wpmd->data = malloc (12); byteptr = wpmd->data = malloc (12);
wpmd->id = ID_SHAPING_WEIGHTS; wpmd->id = ID_SHAPING_WEIGHTS;
@ -243,7 +226,7 @@ void write_shaping_info (WavpackStream *wps, WavpackMetadata *wpmd)
*byteptr++ = temp; *byteptr++ = temp;
*byteptr++ = temp >> 8; *byteptr++ = temp >> 8;
if (!(wps->wphdr.flags & MONO_FLAG)) { if (!(wps->wphdr.flags & MONO_DATA)) {
wps->dc.error [1] = exp2s (temp = log2s (wps->dc.error [1])); wps->dc.error [1] = exp2s (temp = log2s (wps->dc.error [1]));
*byteptr++ = temp; *byteptr++ = temp;
*byteptr++ = temp >> 8; *byteptr++ = temp >> 8;
@ -257,7 +240,7 @@ void write_shaping_info (WavpackStream *wps, WavpackMetadata *wpmd)
*byteptr++ = temp; *byteptr++ = temp;
*byteptr++ = temp >> 8; *byteptr++ = temp >> 8;
if (!(wps->wphdr.flags & MONO_FLAG)) { if (!(wps->wphdr.flags & MONO_DATA)) {
wps->dc.shaping_delta [1] = exp2s (temp = log2s (wps->dc.shaping_delta [1])); wps->dc.shaping_delta [1] = exp2s (temp = log2s (wps->dc.shaping_delta [1]));
*byteptr++ = temp; *byteptr++ = temp;
*byteptr++ = temp >> 8; *byteptr++ = temp >> 8;
@ -325,6 +308,24 @@ void write_config_info (WavpackContext *wpc, WavpackMetadata *wpmd)
wpmd->byte_length = byteptr - (char *) wpmd->data; wpmd->byte_length = byteptr - (char *) wpmd->data;
} }
// Allocate room for and copy the non-standard sampling rateinto the specified
// metadata structure. We just store the lower 3 bytes of the sampling rate.
// Note that this would only be used when the sampling rate was not included
// in the table of 15 "standard" values.
void write_sample_rate (WavpackContext *wpc, WavpackMetadata *wpmd)
{
char *byteptr;
byteptr = wpmd->data = malloc (4);
wpmd->id = ID_SAMPLE_RATE;
*byteptr++ = (char) (wpc->config.sample_rate);
*byteptr++ = (char) (wpc->config.sample_rate >> 8);
*byteptr++ = (char) (wpc->config.sample_rate >> 16);
wpmd->byte_length = byteptr - (char *) wpmd->data;
}
// Pack an entire block of samples (either mono or stereo) into a completed // 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 // WavPack block. This function is actually a shell for pack_samples() and
// performs tasks like handling any shift required by the format, preprocessing // performs tasks like handling any shift required by the format, preprocessing
@ -335,6 +336,7 @@ void write_config_info (WavpackContext *wpc, WavpackMetadata *wpmd)
// FALSE indicates an error. // FALSE indicates an error.
static int scan_int32_data (WavpackStream *wps, int32_t *values, int32_t num_values); static int scan_int32_data (WavpackStream *wps, int32_t *values, int32_t num_values);
static void scan_int32_quick (WavpackStream *wps, int32_t *values, int32_t num_values);
static void send_int32_data (WavpackStream *wps, int32_t *values, int32_t num_values); static void send_int32_data (WavpackStream *wps, int32_t *values, int32_t num_values);
static int pack_samples (WavpackContext *wpc, int32_t *buffer); static int pack_samples (WavpackContext *wpc, int32_t *buffer);
@ -351,7 +353,7 @@ int pack_block (WavpackContext *wpc, int32_t *buffer)
uint32_t cnt = sample_count; uint32_t cnt = sample_count;
int32_t *ptr = buffer; int32_t *ptr = buffer;
if (flags & MONO_FLAG) if (flags & MONO_DATA)
while (cnt--) while (cnt--)
*ptr++ >>= shift; *ptr++ >>= shift;
else else
@ -370,19 +372,19 @@ int pack_block (WavpackContext *wpc, int32_t *buffer)
if ((flags & FLOAT_DATA) || (flags & MAG_MASK) >> MAG_LSB >= 24) { if ((flags & FLOAT_DATA) || (flags & MAG_MASK) >> MAG_LSB >= 24) {
if ((!(flags & HYBRID_FLAG) || wpc->wvc_flag) && !(wpc->config.flags & CONFIG_SKIP_WVX)) { if ((!(flags & HYBRID_FLAG) || wpc->wvc_flag) && !(wpc->config.flags & CONFIG_SKIP_WVX)) {
orig_data = malloc (sizeof (f32) * ((flags & MONO_FLAG) ? sample_count : sample_count * 2)); orig_data = malloc (sizeof (f32) * ((flags & MONO_DATA) ? sample_count : sample_count * 2));
memcpy (orig_data, buffer, sizeof (f32) * ((flags & MONO_FLAG) ? sample_count : sample_count * 2)); memcpy (orig_data, buffer, sizeof (f32) * ((flags & MONO_DATA) ? sample_count : sample_count * 2));
if (flags & FLOAT_DATA) { if (flags & FLOAT_DATA) {
wps->float_norm_exp = wpc->config.float_norm_exp; wps->float_norm_exp = wpc->config.float_norm_exp;
if (!scan_float_data (wps, (f32 *) buffer, (flags & MONO_FLAG) ? sample_count : sample_count * 2)) { if (!scan_float_data (wps, (f32 *) buffer, (flags & MONO_DATA) ? sample_count : sample_count * 2)) {
free (orig_data); free (orig_data);
orig_data = NULL; orig_data = NULL;
} }
} }
else { else {
if (!scan_int32_data (wps, buffer, (flags & MONO_FLAG) ? sample_count : sample_count * 2)) { if (!scan_int32_data (wps, buffer, (flags & MONO_DATA) ? sample_count : sample_count * 2)) {
free (orig_data); free (orig_data);
orig_data = NULL; orig_data = NULL;
} }
@ -392,20 +394,28 @@ int pack_block (WavpackContext *wpc, int32_t *buffer)
if (flags & FLOAT_DATA) { if (flags & FLOAT_DATA) {
wps->float_norm_exp = wpc->config.float_norm_exp; wps->float_norm_exp = wpc->config.float_norm_exp;
if (scan_float_data (wps, (f32 *) buffer, (flags & MONO_FLAG) ? sample_count : sample_count * 2)) if (scan_float_data (wps, (f32 *) buffer, (flags & MONO_DATA) ? sample_count : sample_count * 2))
wpc->lossy_blocks = TRUE; wpc->lossy_blocks = TRUE;
} }
else if (scan_int32_data (wps, buffer, (flags & MONO_FLAG) ? sample_count : sample_count * 2)) else if (scan_int32_data (wps, buffer, (flags & MONO_DATA) ? sample_count : sample_count * 2))
wpc->lossy_blocks = TRUE; wpc->lossy_blocks = TRUE;
} }
wpc->config.extra_flags |= EXTRA_SCAN_ONLY; wpc->config.extra_flags |= EXTRA_SCAN_ONLY;
} }
else if (wpc->config.extra_flags) else if (wpc->config.extra_flags)
scan_int32_data (wps, buffer, (flags & MONO_FLAG) ? sample_count : sample_count * 2); scan_int32_data (wps, buffer, (flags & MONO_DATA) ? sample_count : sample_count * 2);
else {
scan_int32_quick (wps, buffer, (flags & MONO_DATA) ? sample_count : sample_count * 2);
if (wps->shift != wps->int32_zeros + wps->int32_ones + wps->int32_dups) {
wps->shift = wps->int32_zeros + wps->int32_ones + wps->int32_dups;
wps->num_terms = 0;
}
}
if (wpc->config.extra_flags) { if (wpc->config.extra_flags) {
if (flags & MONO_FLAG) if (flags & MONO_DATA)
analyze_mono (wpc, buffer); analyze_mono (wpc, buffer);
else else
analyze_stereo (wpc, buffer); analyze_stereo (wpc, buffer);
@ -413,7 +423,7 @@ int pack_block (WavpackContext *wpc, int32_t *buffer)
else if (!wps->sample_index || !wps->num_terms) { else if (!wps->sample_index || !wps->num_terms) {
wpc->config.extra_flags = EXTRA_SCAN_ONLY; wpc->config.extra_flags = EXTRA_SCAN_ONLY;
if (flags & MONO_FLAG) if (flags & MONO_DATA)
analyze_mono (wpc, buffer); analyze_mono (wpc, buffer);
else else
analyze_stereo (wpc, buffer); analyze_stereo (wpc, buffer);
@ -444,9 +454,9 @@ int pack_block (WavpackContext *wpc, int32_t *buffer)
bs_open_write (&wps->wvxbits, cptr + 8, wpc->wvc_flag ? wps->block2end : wps->blockend); bs_open_write (&wps->wvxbits, cptr + 8, wpc->wvc_flag ? wps->block2end : wps->blockend);
if (flags & FLOAT_DATA) if (flags & FLOAT_DATA)
send_float_data (wps, (f32*) orig_data, (flags & MONO_FLAG) ? sample_count : sample_count * 2); send_float_data (wps, (f32*) orig_data, (flags & MONO_DATA) ? sample_count : sample_count * 2);
else else
send_int32_data (wps, orig_data, (flags & MONO_FLAG) ? sample_count : sample_count * 2); send_int32_data (wps, orig_data, (flags & MONO_DATA) ? sample_count : sample_count * 2);
data_count = bs_close_write (&wps->wvxbits); data_count = bs_close_write (&wps->wvxbits);
free (orig_data); free (orig_data);
@ -475,6 +485,70 @@ int pack_block (WavpackContext *wpc, int32_t *buffer)
return TRUE; return TRUE;
} }
// Quickly scan a buffer of long integer data and determine whether any
// redundancy in the LSBs can be used to reduce the data's magnitude. If yes,
// then the INT32_DATA flag is set and the int32 parameters are set. This
// version is designed to terminate as soon as it figures out that no
// redundancy is available so that it can be used for all files.
static void scan_int32_quick (WavpackStream *wps, int32_t *values, int32_t num_values)
{
uint32_t magdata = 0, ordata = 0, xordata = 0, anddata = ~0;
int total_shift = 0;
int32_t *dp, count;
wps->int32_sent_bits = wps->int32_zeros = wps->int32_ones = wps->int32_dups = 0;
for (dp = values, count = num_values; count--; dp++) {
magdata |= (*dp < 0) ? ~*dp : *dp;
xordata |= *dp ^ -(*dp & 1);
anddata &= *dp;
ordata |= *dp;
if ((ordata & 1) && !(anddata & 1) && (xordata & 2))
return;
}
wps->wphdr.flags &= ~MAG_MASK;
while (magdata) {
wps->wphdr.flags += 1 << MAG_LSB;
magdata >>= 1;
}
if (!(wps->wphdr.flags & MAG_MASK))
return;
if (!(ordata & 1))
while (!(ordata & 1)) {
wps->wphdr.flags -= 1 << MAG_LSB;
wps->int32_zeros++;
total_shift++;
ordata >>= 1;
}
else if (anddata & 1)
while (anddata & 1) {
wps->wphdr.flags -= 1 << MAG_LSB;
wps->int32_ones++;
total_shift++;
anddata >>= 1;
}
else if (!(xordata & 2))
while (!(xordata & 2)) {
wps->wphdr.flags -= 1 << MAG_LSB;
wps->int32_dups++;
total_shift++;
xordata >>= 1;
}
if (total_shift) {
wps->wphdr.flags |= INT32_DATA;
for (dp = values, count = num_values; count--; dp++)
*dp >>= total_shift;
}
}
// Scan a buffer of long integer data and determine whether any redundancy in // Scan a buffer of long integer data and determine whether any redundancy in
// the LSBs can be used to reduce the data's magnitude. If yes, then the // the LSBs can be used to reduce the data's magnitude. If yes, then the
// INT32_DATA flag is set and the int32 parameters are set. If bits must still // INT32_DATA flag is set and the int32 parameters are set. If bits must still
@ -548,12 +622,6 @@ static int scan_int32_data (WavpackStream *wps, int32_t *values, int32_t num_val
*dp >>= total_shift; *dp >>= total_shift;
} }
#if 0
if (wps->int32_sent_bits + wps->int32_zeros + wps->int32_ones + wps->int32_dups)
error_line ("sent bits = %d, zeros/ones/dups = %d/%d/%d", wps->int32_sent_bits,
wps->int32_zeros, wps->int32_ones, wps->int32_dups);
#endif
return wps->int32_sent_bits; return wps->int32_sent_bits;
} }
@ -641,6 +709,12 @@ static int pack_samples (WavpackContext *wpc, int32_t *buffer)
copy_metadata (&wpmd, wps->blockbuff, wps->blockend); copy_metadata (&wpmd, wps->blockbuff, wps->blockend);
free_metadata (&wpmd); free_metadata (&wpmd);
if ((flags & SRATE_MASK) == SRATE_MASK && wpc->config.sample_rate != 44100) {
write_sample_rate (wpc, &wpmd);
copy_metadata (&wpmd, wps->blockbuff, wps->blockend);
free_metadata (&wpmd);
}
if (flags & HYBRID_FLAG) { if (flags & HYBRID_FLAG) {
write_hybrid_profile (wps, &wpmd); write_hybrid_profile (wps, &wpmd);
copy_metadata (&wpmd, wps->blockbuff, wps->blockend); copy_metadata (&wpmd, wps->blockbuff, wps->blockend);
@ -690,7 +764,7 @@ static int pack_samples (WavpackContext *wpc, int32_t *buffer)
/////////////////////// handle lossless mono mode ///////////////////////// /////////////////////// handle lossless mono mode /////////////////////////
if (!(flags & HYBRID_FLAG) && (flags & MONO_FLAG)) if (!(flags & HYBRID_FLAG) && (flags & MONO_DATA))
for (bptr = buffer, i = 0; i < sample_count; ++i) { for (bptr = buffer, i = 0; i < sample_count; ++i) {
int32_t code; int32_t code;
@ -724,8 +798,8 @@ static int pack_samples (WavpackContext *wpc, int32_t *buffer)
//////////////////// handle the lossless stereo mode ////////////////////// //////////////////// handle the lossless stereo mode //////////////////////
#ifdef FAST_ENCODE #ifdef FAST_ENCODE
else if (!(flags & HYBRID_FLAG) && !(flags & MONO_FLAG)) { else if (!(flags & HYBRID_FLAG) && !(flags & MONO_DATA)) {
int32_t *eptr = buffer + (sample_count * 2), sam_A, sam_B; int32_t *eptr = buffer + (sample_count * 2);
if (flags & JOINT_STEREO) if (flags & JOINT_STEREO)
for (bptr = buffer; bptr < eptr; bptr += 2) { for (bptr = buffer; bptr < eptr; bptr += 2) {
@ -752,7 +826,7 @@ static int pack_samples (WavpackContext *wpc, int32_t *buffer)
m = sample_count & (MAX_TERM - 1); m = sample_count & (MAX_TERM - 1);
} }
#else #else
else if (!(flags & HYBRID_FLAG) && !(flags & MONO_FLAG)) else if (!(flags & HYBRID_FLAG) && !(flags & MONO_DATA))
for (bptr = buffer, i = 0; i < sample_count; ++i, bptr += 2) { for (bptr = buffer, i = 0; i < sample_count; ++i, bptr += 2) {
int32_t left, right, sam_A, sam_B; int32_t left, right, sam_A, sam_B;
@ -813,7 +887,7 @@ static int pack_samples (WavpackContext *wpc, int32_t *buffer)
/////////////////// handle the lossy/hybrid mono mode ///////////////////// /////////////////// handle the lossy/hybrid mono mode /////////////////////
else if ((flags & HYBRID_FLAG) && (flags & MONO_FLAG)) else if ((flags & HYBRID_FLAG) && (flags & MONO_DATA))
for (bptr = buffer, i = 0; i < sample_count; ++i) { for (bptr = buffer, i = 0; i < sample_count; ++i) {
int32_t code, temp; int32_t code, temp;
@ -881,7 +955,7 @@ static int pack_samples (WavpackContext *wpc, int32_t *buffer)
/////////////////// handle the lossy/hybrid stereo mode /////////////////// /////////////////// handle the lossy/hybrid stereo mode ///////////////////
else if ((flags & HYBRID_FLAG) && !(flags & MONO_FLAG)) else if ((flags & HYBRID_FLAG) && !(flags & MONO_DATA))
for (bptr = buffer, i = 0; i < sample_count; ++i) { for (bptr = buffer, i = 0; i < sample_count; ++i) {
int32_t left, right, temp; int32_t left, right, temp;
int shaping_weight; int shaping_weight;
@ -947,10 +1021,7 @@ static int pack_samples (WavpackContext *wpc, int32_t *buffer)
left -= (dpp->aweight_A = apply_weight (dpp->weight_A, dpp->samples_A [0])); left -= (dpp->aweight_A = apply_weight (dpp->weight_A, dpp->samples_A [0]));
right -= (dpp->aweight_B = apply_weight (dpp->weight_B, dpp->samples_B [0])); right -= (dpp->aweight_B = apply_weight (dpp->weight_B, dpp->samples_B [0]));
} }
#if 0
if (labs (left) > 60000000 || labs (right) > 60000000)
error_line ("sending %d, %d; samples = %d, %d", left, right, bptr [-2], bptr [-1]);
#endif
left = send_word (wps, left, 0); left = send_word (wps, left, 0);
right = send_word (wps, right, 1); right = send_word (wps, right, 1);

View File

@ -70,18 +70,14 @@ int unpack_init (WavpackContext *wpc)
blockptr = wps->blockbuff + sizeof (WavpackHeader); blockptr = wps->blockbuff + sizeof (WavpackHeader);
while (read_metadata_buff (&wpmd, wps->blockbuff, &blockptr)) while (read_metadata_buff (&wpmd, wps->blockbuff, &blockptr))
if (!process_metadata (wpc, &wpmd)) { if (!process_metadata (wpc, &wpmd))
sprintf (wpc->error_message, "invalid metadata %2x!", wpmd.id);
return FALSE; return FALSE;
}
block2ptr = wps->block2buff + sizeof (WavpackHeader); block2ptr = wps->block2buff + sizeof (WavpackHeader);
while (wpc->wvc_flag && wps->wphdr.block_samples && read_metadata_buff (&wpmd, wps->block2buff, &block2ptr)) while (wpc->wvc_flag && wps->wphdr.block_samples && read_metadata_buff (&wpmd, wps->block2buff, &block2ptr))
if (!process_metadata (wpc, &wpmd)) { if (!process_metadata (wpc, &wpmd))
sprintf (wpc->error_message, "invalid metadata %2x in wvc file!", wpmd.id);
return FALSE; return FALSE;
}
if (wps->wphdr.block_samples && !bs_is_open (&wps->wvbits)) { if (wps->wphdr.block_samples && !bs_is_open (&wps->wvbits)) {
if (bs_is_open (&wps->wvcbits)) if (bs_is_open (&wps->wvcbits))
@ -181,7 +177,7 @@ int read_decorr_weights (WavpackStream *wps, WavpackMetadata *wpmd)
char *byteptr = wpmd->data; char *byteptr = wpmd->data;
struct decorr_pass *dpp; struct decorr_pass *dpp;
if (!(wps->wphdr.flags & MONO_FLAG)) if (!(wps->wphdr.flags & MONO_DATA))
termcnt /= 2; termcnt /= 2;
if (termcnt > wps->num_terms) if (termcnt > wps->num_terms)
@ -193,7 +189,7 @@ int read_decorr_weights (WavpackStream *wps, WavpackMetadata *wpmd)
while (--dpp >= wps->decorr_passes && termcnt--) { while (--dpp >= wps->decorr_passes && termcnt--) {
dpp->weight_A = restore_weight (*byteptr++); dpp->weight_A = restore_weight (*byteptr++);
if (!(wps->wphdr.flags & MONO_FLAG)) if (!(wps->wphdr.flags & MONO_DATA))
dpp->weight_B = restore_weight (*byteptr++); dpp->weight_B = restore_weight (*byteptr++);
} }
@ -224,7 +220,7 @@ int read_decorr_samples (WavpackStream *wps, WavpackMetadata *wpmd)
wps->dc.error [0] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8))); wps->dc.error [0] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8)));
byteptr += 2; byteptr += 2;
if (!(wps->wphdr.flags & MONO_FLAG)) { if (!(wps->wphdr.flags & MONO_DATA)) {
wps->dc.error [1] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8))); wps->dc.error [1] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8)));
byteptr += 2; byteptr += 2;
} }
@ -236,7 +232,7 @@ int read_decorr_samples (WavpackStream *wps, WavpackMetadata *wpmd)
dpp->samples_A [1] = exp2s ((short)(byteptr [2] + (byteptr [3] << 8))); dpp->samples_A [1] = exp2s ((short)(byteptr [2] + (byteptr [3] << 8)));
byteptr += 4; byteptr += 4;
if (!(wps->wphdr.flags & MONO_FLAG)) { if (!(wps->wphdr.flags & MONO_DATA)) {
dpp->samples_B [0] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8))); dpp->samples_B [0] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8)));
dpp->samples_B [1] = exp2s ((short)(byteptr [2] + (byteptr [3] << 8))); dpp->samples_B [1] = exp2s ((short)(byteptr [2] + (byteptr [3] << 8)));
byteptr += 4; byteptr += 4;
@ -254,7 +250,7 @@ int read_decorr_samples (WavpackStream *wps, WavpackMetadata *wpmd)
dpp->samples_A [m] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8))); dpp->samples_A [m] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8)));
byteptr += 2; byteptr += 2;
if (!(wps->wphdr.flags & MONO_FLAG)) { if (!(wps->wphdr.flags & MONO_DATA)) {
dpp->samples_B [m] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8))); dpp->samples_B [m] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8)));
byteptr += 2; byteptr += 2;
} }
@ -282,23 +278,23 @@ int read_shaping_info (WavpackStream *wps, WavpackMetadata *wpmd)
wps->dc.shaping_acc [1] = (int32_t) restore_weight (*byteptr++) << 16; wps->dc.shaping_acc [1] = (int32_t) restore_weight (*byteptr++) << 16;
return TRUE; return TRUE;
} }
else if (wpmd->byte_length >= (wps->wphdr.flags & MONO_FLAG ? 4 : 8)) { else if (wpmd->byte_length >= (wps->wphdr.flags & MONO_DATA ? 4 : 8)) {
uchar *byteptr = wpmd->data; uchar *byteptr = wpmd->data;
wps->dc.error [0] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8))); wps->dc.error [0] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8)));
wps->dc.shaping_acc [0] = exp2s ((short)(byteptr [2] + (byteptr [3] << 8))); wps->dc.shaping_acc [0] = exp2s ((short)(byteptr [2] + (byteptr [3] << 8)));
byteptr += 4; byteptr += 4;
if (!(wps->wphdr.flags & MONO_FLAG)) { if (!(wps->wphdr.flags & MONO_DATA)) {
wps->dc.error [1] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8))); wps->dc.error [1] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8)));
wps->dc.shaping_acc [1] = exp2s ((short)(byteptr [2] + (byteptr [3] << 8))); wps->dc.shaping_acc [1] = exp2s ((short)(byteptr [2] + (byteptr [3] << 8)));
byteptr += 4; byteptr += 4;
} }
if (wpmd->byte_length == (wps->wphdr.flags & MONO_FLAG ? 6 : 12)) { if (wpmd->byte_length == (wps->wphdr.flags & MONO_DATA ? 6 : 12)) {
wps->dc.shaping_delta [0] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8))); wps->dc.shaping_delta [0] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8)));
if (!(wps->wphdr.flags & MONO_FLAG)) if (!(wps->wphdr.flags & MONO_DATA))
wps->dc.shaping_delta [1] = exp2s ((short)(byteptr [2] + (byteptr [3] << 8))); wps->dc.shaping_delta [1] = exp2s ((short)(byteptr [2] + (byteptr [3] << 8)));
} }
@ -369,6 +365,22 @@ int read_config_info (WavpackContext *wpc, WavpackMetadata *wpmd)
return TRUE; return TRUE;
} }
// Read non-standard sampling rate from metadata.
int read_sample_rate (WavpackContext *wpc, WavpackMetadata *wpmd)
{
int bytecnt = wpmd->byte_length;
uchar *byteptr = wpmd->data;
if (bytecnt == 3) {
wpc->config.sample_rate = (int32_t) *byteptr++;
wpc->config.sample_rate |= (int32_t) *byteptr++ << 8;
wpc->config.sample_rate |= (int32_t) *byteptr++ << 16;
}
return TRUE;
}
// Read wrapper data from metadata. Currently, this consists of the RIFF // Read wrapper data from metadata. Currently, this consists of the RIFF
// header and trailer that wav files contain around the audio data but could // header and trailer that wav files contain around the audio data but could
// be used for other formats as well. Because WavPack files contain all the // be used for other formats as well. Because WavPack files contain all the
@ -435,7 +447,7 @@ int32_t unpack_samples (WavpackContext *wpc, int32_t *buffer, uint32_t sample_co
///////////////// handle version 4 lossless mono data ///////////////////// ///////////////// handle version 4 lossless mono data /////////////////////
if (!(flags & HYBRID_FLAG) && (flags & MONO_FLAG)) if (!(flags & HYBRID_FLAG) && (flags & MONO_DATA))
for (bptr = buffer, i = 0; i < sample_count; ++i) { for (bptr = buffer, i = 0; i < sample_count; ++i) {
if ((read_word = get_word_lossless (wps, 0)) == WORD_EOF) if ((read_word = get_word_lossless (wps, 0)) == WORD_EOF)
break; break;
@ -473,7 +485,7 @@ int32_t unpack_samples (WavpackContext *wpc, int32_t *buffer, uint32_t sample_co
//////////////// handle version 4 lossless stereo data //////////////////// //////////////// handle version 4 lossless stereo data ////////////////////
else if (!wpc->wvc_flag && !(flags & MONO_FLAG)) { else if (!wpc->wvc_flag && !(flags & MONO_DATA)) {
int32_t *eptr = buffer + (sample_count * 2); int32_t *eptr = buffer + (sample_count * 2);
i = sample_count; i = sample_count;
@ -537,7 +549,7 @@ int32_t unpack_samples (WavpackContext *wpc, int32_t *buffer, uint32_t sample_co
//////////////// handle version 4 lossy/hybrid mono data ////////////////// //////////////// handle version 4 lossy/hybrid mono data //////////////////
else if ((flags & HYBRID_FLAG) && (flags & MONO_FLAG)) else if ((flags & HYBRID_FLAG) && (flags & MONO_DATA))
for (bptr = buffer, i = 0; i < sample_count; ++i) { for (bptr = buffer, i = 0; i < sample_count; ++i) {
if ((read_word = get_word (wps, 0, correction)) == WORD_EOF) if ((read_word = get_word (wps, 0, correction)) == WORD_EOF)
@ -599,7 +611,7 @@ int32_t unpack_samples (WavpackContext *wpc, int32_t *buffer, uint32_t sample_co
//////////////// handle version 4 lossy/hybrid stereo data //////////////// //////////////// handle version 4 lossy/hybrid stereo data ////////////////
else if (wpc->wvc_flag && !(flags & MONO_FLAG)) else if (wpc->wvc_flag && !(flags & MONO_DATA))
for (bptr = buffer, i = 0; i < sample_count; ++i) { for (bptr = buffer, i = 0; i < sample_count; ++i) {
int32_t left, right, left_c, right_c, left2, right2; int32_t left, right, left_c, right_c, left2, right2;
@ -798,9 +810,20 @@ int32_t unpack_samples (WavpackContext *wpc, int32_t *buffer, uint32_t sample_co
fixup_samples (wpc, buffer, i); fixup_samples (wpc, buffer, i);
if ((flags & FLOAT_DATA) && (wpc->open_flags & OPEN_NORMALIZE)) if ((flags & FLOAT_DATA) && (wpc->open_flags & OPEN_NORMALIZE))
float_normalize (buffer, (flags & MONO_FLAG) ? i : i * 2, float_normalize (buffer, (flags & MONO_DATA) ? i : i * 2,
127 - wps->float_norm_exp + wpc->norm_offset); 127 - wps->float_norm_exp + wpc->norm_offset);
if (flags & FALSE_STEREO) {
int32_t *dptr = buffer + i * 2;
int32_t *sptr = buffer + i;
int32_t c = i;
while (c--) {
*--dptr = *--sptr;
*--dptr = *sptr;
}
}
wps->sample_index += i; wps->sample_index += i;
wps->crc = crc; wps->crc = crc;
@ -1319,12 +1342,12 @@ static void fixup_samples (WavpackContext *wpc, int32_t *buffer, uint32_t sample
int shift = (flags & SHIFT_MASK) >> SHIFT_LSB; int shift = (flags & SHIFT_MASK) >> SHIFT_LSB;
if (flags & FLOAT_DATA) { if (flags & FLOAT_DATA) {
float_values (wps, buffer, (flags & MONO_FLAG) ? sample_count : sample_count * 2); float_values (wps, buffer, (flags & MONO_DATA) ? sample_count : sample_count * 2);
return; return;
} }
if (flags & INT32_DATA) { if (flags & INT32_DATA) {
uint32_t count = (flags & MONO_FLAG) ? sample_count : sample_count * 2; uint32_t count = (flags & MONO_DATA) ? sample_count : sample_count * 2;
int sent_bits = wps->int32_sent_bits, zeros = wps->int32_zeros; int sent_bits = wps->int32_sent_bits, zeros = wps->int32_zeros;
int ones = wps->int32_ones, dups = wps->int32_dups; int ones = wps->int32_ones, dups = wps->int32_dups;
uint32_t data, mask = (1 << sent_bits) - 1; uint32_t data, mask = (1 << sent_bits) - 1;
@ -1406,7 +1429,7 @@ static void fixup_samples (WavpackContext *wpc, int32_t *buffer, uint32_t sample
break; break;
} }
if (!(flags & MONO_FLAG)) if (!(flags & MONO_DATA))
sample_count *= 2; sample_count *= 2;
while (sample_count--) { while (sample_count--) {
@ -1419,7 +1442,7 @@ static void fixup_samples (WavpackContext *wpc, int32_t *buffer, uint32_t sample
} }
} }
else if (shift) { else if (shift) {
if (!(flags & MONO_FLAG)) if (!(flags & MONO_DATA))
sample_count *= 2; sample_count *= 2;
while (sample_count--) while (sample_count--)

View File

@ -33,7 +33,7 @@ int32_t dump_alloc (void);
#endif #endif
static void unpack_init3 (WavpackStream3 *wps); static void unpack_init3 (WavpackStream3 *wps);
static int bs_open_read3 (Bitstream3 *bs, stream_reader *reader, void *id); static int bs_open_read3 (Bitstream3 *bs, WavpackStreamReader *reader, void *id);
static void bs_close_read3 (Bitstream3 *bs); static void bs_close_read3 (Bitstream3 *bs);
#ifdef SEEKING #ifdef SEEKING
static void bs_restore3 (Bitstream3 *bs); static void bs_restore3 (Bitstream3 *bs);
@ -301,7 +301,7 @@ static void bs_read3 (Bitstream3 *bs)
// data is located. A return value of TRUE indicates an error in // data is located. A return value of TRUE indicates an error in
// allocating buffer space. // allocating buffer space.
static int bs_open_read3 (Bitstream3 *bs, stream_reader *reader, void *id) static int bs_open_read3 (Bitstream3 *bs, WavpackStreamReader *reader, void *id)
{ {
bs->fpos = (bs->reader = reader)->get_pos (bs->id = id); bs->fpos = (bs->reader = reader)->get_pos (bs->id = id);
@ -401,9 +401,9 @@ static uchar *bs_unused_data (Bitstream3 *bs)
// "simple_terms" table is no longer used for writing, but is kept for older // "simple_terms" table is no longer used for writing, but is kept for older
// file decoding. // file decoding.
static const char extreme_terms [] = { 1,1,1,2,4,-1,1,2,3,6,-2,8,5,7,4,1,2,3 }; static const signed char extreme_terms [] = { 1,1,1,2,4,-1,1,2,3,6,-2,8,5,7,4,1,2,3 };
static const char default_terms [] = { 1,1,1,-1,2,1,-2 }; static const signed char default_terms [] = { 1,1,1,-1,2,1,-2 };
static const char simple_terms [] = { 1,1,1,1 }; static const signed char simple_terms [] = { 1,1,1,1 };
// This function initializes everything required to unpack WavPack // This function initializes everything required to unpack WavPack
// bitstreams and must be called before any unpacking is performed. Note // bitstreams and must be called before any unpacking is performed. Note

View File

@ -63,7 +63,7 @@ typedef struct bs3 {
void (*wrap)(struct bs3 *bs); void (*wrap)(struct bs3 *bs);
uchar *buf, *end, *ptr; uchar *buf, *end, *ptr;
uint32_t bufsiz, fpos, sr; uint32_t bufsiz, fpos, sr;
stream_reader *reader; WavpackStreamReader *reader;
int error, bc; int error, bc;
void *id; void *id;
} Bitstream3; } Bitstream3;

View File

@ -15,15 +15,11 @@
#include <windows.h> #include <windows.h>
#include <io.h> #include <io.h>
#include <conio.h> #include <conio.h>
#include <shlobj.h>
#elif defined(__GNUC__) #elif defined(__GNUC__)
#include <glob.h> #include <glob.h>
#endif #endif
#ifndef WIN32
#include <locale.h>
#include <iconv.h>
#endif
#include <sys/stat.h> #include <sys/stat.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdarg.h> #include <stdarg.h>
@ -63,6 +59,34 @@ int copy_timestamp (const char *src_filename, const char *dst_filename)
return res; return res;
} }
#else
#include <sys/time.h>
#include <sys/types.h>
int copy_timestamp(const char *src_filename, const char *dst_filename)
{
struct stat fileinfo;
struct timeval times[2];
if (strcmp(src_filename, "-") == 0 || strcmp(dst_filename, "-") == 0)
return TRUE;
if (stat(src_filename, &fileinfo))
return FALSE; /* stat failed */
times[0].tv_sec = fileinfo.st_atime;
times[0].tv_usec = 0;
times[1].tv_sec = fileinfo.st_mtime;
times[1].tv_usec = 0;
if (utimes(dst_filename, times))
return FALSE; /* utimes failed */
return TRUE;
}
#endif #endif
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
@ -107,7 +131,7 @@ char *filespec_ext (char *filespec)
while (--cp >= filespec) { while (--cp >= filespec) {
if (*cp == '\\' || *cp == ':') if (*cp == '/' || *cp == ':')
return NULL; return NULL;
if (*cp == '.') { if (*cp == '.') {
@ -143,20 +167,21 @@ char *filespec_path (char *filespec)
if (cp == filespec || filespec_wild (filespec)) if (cp == filespec || filespec_wild (filespec))
return NULL; return NULL;
if (*--cp == '\\' || *cp == ':') if (*--cp == '/' || *cp == ':')
return filespec; return filespec;
if (*cp == '.' && cp == filespec) if (*cp == '.' && cp == filespec)
return strcat (filespec, "\\"); return strcat (filespec, "/");
if (glob (filespec, GLOB_MARK|GLOB_NOSORT, NULL, &globs) == 0 && if (glob (filespec, GLOB_MARK|GLOB_NOSORT, NULL, &globs) == 0 &&
globs.gl_pathc > 0) globs.gl_pathc > 0)
{ {
/* test if the file is a directory */ /* test if the file is a directory */
if (stat(globs.gl_pathv[0], &fstats) == 0 && (fstats.st_mode & S_IFDIR)) { if (stat(globs.gl_pathv[0], &fstats) == 0 && (fstats.st_mode & S_IFDIR)) {
globfree(&globs);
filespec[0] = '\0'; filespec[0] = '\0';
return strcat (filespec, globs.gl_pathv[0]); strcat (filespec, globs.gl_pathv[0]);
globfree(&globs);
return filespec;
} }
} }
globfree(&globs); globfree(&globs);
@ -243,7 +268,7 @@ char *filespec_name (char *filespec)
char *cp = filespec + strlen (filespec); char *cp = filespec + strlen (filespec);
while (--cp >= filespec) while (--cp >= filespec)
if (*cp == '\\' || *cp == ':') if (*cp == '/' || *cp == ':')
break; break;
if (strlen (cp + 1)) if (strlen (cp + 1))
@ -336,6 +361,62 @@ char yna (void)
// with printf strings and args. // // with printf strings and args. //
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
int debug_logging_mode = FALSE;
#ifdef WIN32
int get_app_path (char *app_path)
{
static char file_path [MAX_PATH], tried, result;
HINSTANCE hinstLib;
FARPROC ProcAdd;
if (tried) {
if (result)
strcpy (app_path, file_path);
return result;
}
tried = TRUE;
hinstLib = LoadLibrary ("shell32.dll");
if (hinstLib) {
ProcAdd = GetProcAddress (hinstLib, "SHGetFolderPathA");
if (ProcAdd && SUCCEEDED ((ProcAdd) (NULL, CSIDL_APPDATA | 0x8000, NULL, 0, file_path)))
result = TRUE;
if (!result) {
ProcAdd = GetProcAddress (hinstLib, "SHGetSpecialFolderPathA");
if (ProcAdd && SUCCEEDED ((ProcAdd) (NULL, file_path, CSIDL_APPDATA, TRUE)))
result = TRUE;
}
FreeLibrary (hinstLib);
}
if (!result) {
hinstLib = LoadLibrary ("shfolder.dll");
if (hinstLib) {
ProcAdd = GetProcAddress (hinstLib, "SHGetFolderPathA");
if (ProcAdd && SUCCEEDED ((ProcAdd) (NULL, CSIDL_APPDATA | 0x8000, NULL, 0, file_path)))
result = TRUE;
FreeLibrary (hinstLib);
}
}
if (result)
strcpy (app_path, file_path);
return result;
}
void error_line (char *error, ...) void error_line (char *error, ...)
{ {
char error_msg [512]; char error_msg [512];
@ -347,8 +428,70 @@ void error_line (char *error, ...)
va_end (argptr); va_end (argptr);
fputs (error_msg, stderr); fputs (error_msg, stderr);
finish_line (); finish_line ();
#if 0
{ if (debug_logging_mode) {
char file_path [MAX_PATH];
FILE *error_log = NULL;
if (get_app_path (file_path)) {
strcat (file_path, "\\WavPack\\wavpack.log");
error_log = fopen (file_path, "a+");
if (!error_log) {
get_app_path (file_path);
strcat (file_path, "\\WavPack");
if (CreateDirectory (file_path, NULL)) {
strcat (file_path, "\\wavpack.log");
error_log = fopen (file_path, "a+");
}
}
}
if (!error_log)
error_log = fopen ("c:\\wavpack.log", "a+");
if (error_log) {
fputs (error_msg + 1, error_log);
fputc ('\n', error_log);
fclose (error_log);
}
}
}
#else
void error_line (char *error, ...)
{
char error_msg [512];
va_list argptr;
error_msg [0] = '\r';
va_start (argptr, error);
vsprintf (error_msg + 1, error, argptr);
va_end (argptr);
fputs (error_msg, stderr);
finish_line ();
}
#endif
void debug_line (char *error, ...)
{
char error_msg [512];
va_list argptr;
if (!debug_logging_mode)
return;
error_msg [0] = '\r';
va_start (argptr, error);
vsprintf (error_msg + 1, error, argptr);
va_end (argptr);
fputs (error_msg, stderr);
finish_line ();
if (debug_logging_mode) {
FILE *error_log = fopen ("c:\\wavpack.log", "a+"); FILE *error_log = fopen ("c:\\wavpack.log", "a+");
if (error_log) { if (error_log) {
@ -357,7 +500,6 @@ void error_line (char *error, ...)
fclose (error_log); fclose (error_log);
} }
} }
#endif
} }
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
@ -376,9 +518,6 @@ BOOL WINAPI ctrl_handler (DWORD ctrl)
if (ctrl == CTRL_BREAK_EVENT) { if (ctrl == CTRL_BREAK_EVENT) {
if (waiting_input) { if (waiting_input) {
#ifdef __BORLANDC__
fprintf (stderr, "^C\n");
#endif
return FALSE; return FALSE;
} }
else { else {
@ -424,7 +563,7 @@ void finish_line (void)
CONSOLE_SCREEN_BUFFER_INFO coninfo; CONSOLE_SCREEN_BUFFER_INFO coninfo;
if (hConIn && GetConsoleScreenBufferInfo (hConIn, &coninfo)) { if (hConIn && GetConsoleScreenBufferInfo (hConIn, &coninfo)) {
char spaces = coninfo.dwSize.X - coninfo.dwCursorPosition.X; unsigned char spaces = coninfo.dwSize.X - coninfo.dwCursorPosition.X;
while (spaces--) while (spaces--)
fputc (' ', stderr); fputc (' ', stderr);
@ -440,12 +579,7 @@ void finish_line (void)
void finish_line (void) void finish_line (void)
{ {
/* char spaces = 1; fprintf (stderr, " \n");
while (spaces--)
putc (' ', stderr);
else*/
fputc ('\n', stderr);
} }
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
@ -566,75 +700,3 @@ int DoDeleteFile (char *filename)
return !remove (filename); return !remove (filename);
} }
// Convert the Unicode wide-format string into a UTF-8 string using no more
// than the specified buffer length. The wide-format string must be NULL
// terminated and the resulting string will be NULL terminated. The actual
// number of characters converted (not counting terminator) is returned, which
// may be less than the number of characters in the wide string if the buffer
// length is exceeded.
static int WideCharToUTF8 (const ushort *Wide, uchar *pUTF8, int len)
{
const ushort *pWide = Wide;
int outndx = 0;
while (*pWide) {
if (*pWide < 0x80 && outndx + 1 < len)
pUTF8 [outndx++] = (uchar) *pWide++;
else if (*pWide < 0x800 && outndx + 2 < len) {
pUTF8 [outndx++] = (uchar) (0xc0 | ((*pWide >> 6) & 0x1f));
pUTF8 [outndx++] = (uchar) (0x80 | (*pWide++ & 0x3f));
}
else if (outndx + 3 < len) {
pUTF8 [outndx++] = (uchar) (0xe0 | ((*pWide >> 12) & 0xf));
pUTF8 [outndx++] = (uchar) (0x80 | ((*pWide >> 6) & 0x3f));
pUTF8 [outndx++] = (uchar) (0x80 | (*pWide++ & 0x3f));
}
else
break;
}
pUTF8 [outndx] = 0;
return pWide - Wide;
}
// Convert a Ansi string into its Unicode UTF-8 format equivalent. The
// conversion is done in-place so the maximum length of the string buffer must
// be specified because the string may become longer or shorter. If the
// resulting string will not fit in the specified buffer size then it is
// truncated.
void AnsiToUTF8 (char *string, int len)
{
int max_chars = strlen (string);
#if defined(WIN32)
ushort *temp = (ushort *) malloc ((max_chars + 1) * 2);
MultiByteToWideChar (CP_ACP, 0, string, -1, temp, max_chars + 1);
WideCharToUTF8 (temp, (uchar *) string, len);
#else
char *temp = malloc (len);
// memset(temp, 0, len);
char *outp = temp;
const char *inp = string;
size_t insize = max_chars;
size_t outsize = len - 1;
int err = 0;
char *old_locale;
memset(temp, 0, len);
old_locale = setlocale (LC_CTYPE, "");
iconv_t converter = iconv_open ("UTF-8", "");
err = iconv (converter, &inp, &insize, &outp, &outsize);
iconv_close (converter);
setlocale (LC_CTYPE, old_locale);
if (err == -1) {
free(temp);
return;
}
memmove (string, temp, len);
#endif
free (temp);
}

File diff suppressed because it is too large Load Diff

View File

@ -74,8 +74,8 @@ typedef struct {
#undef VERSION_OS #undef VERSION_OS
#define VERSION_OS "Win32" #define VERSION_OS "Win32"
#endif #endif
#define VERSION_STR "4.2 " #define VERSION_STR "4.32"
#define DATE_STR "2005-04-02" #define DATE_STR "2006-04-05"
// ID3v1 and APEv2 TAG formats (may occur at the end of WavPack files) // ID3v1 and APEv2 TAG formats (may occur at the end of WavPack files)
@ -93,6 +93,7 @@ typedef struct {
#define APE_Tag_Hdr_Format "8LLLL" #define APE_Tag_Hdr_Format "8LLLL"
typedef struct { typedef struct {
int32_t tag_file_pos;
ID3_Tag id3_tag; ID3_Tag id3_tag;
APE_Tag_Hdr ape_tag_hdr; APE_Tag_Hdr ape_tag_hdr;
char *ape_tag_data; char *ape_tag_data;
@ -168,11 +169,20 @@ typedef struct {
#define SRATE_LSB 23 #define SRATE_LSB 23
#define SRATE_MASK (0xfL << SRATE_LSB) #define SRATE_MASK (0xfL << SRATE_LSB)
#define FALSE_STEREO 0x40000000 // block is stereo, but data is mono
#define IGNORED_FLAGS 0x18000000 // reserved, but ignore if encountered #define IGNORED_FLAGS 0x18000000 // reserved, but ignore if encountered
#define NEW_SHAPING 0x20000000 // use IIR filter for negative shaping #define NEW_SHAPING 0x20000000 // use IIR filter for negative shaping
#define UNKNOWN_FLAGS 0xC0000000 // also reserved, but refuse decode if #define UNKNOWN_FLAGS 0x80000000 // also reserved, but refuse decode if
// encountered // encountered
#define MONO_DATA (MONO_FLAG | FALSE_STEREO)
#define MIN_STREAM_VERS 0x402 // lowest stream version we'll decode
#define MAX_STREAM_VERS 0x410 // highest stream version we'll decode
#define CUR_STREAM_VERS 0x404 // stream version we are writing now
//////////////////////////// WavPack Metadata ///////////////////////////////// //////////////////////////// WavPack Metadata /////////////////////////////////
// This is an internal representation of metadata. // This is an internal representation of metadata.
@ -183,6 +193,7 @@ typedef struct {
uchar id; uchar id;
} WavpackMetadata; } WavpackMetadata;
#define ID_UNIQUE 0x3f
#define ID_OPTIONAL_DATA 0x20 #define ID_OPTIONAL_DATA 0x20
#define ID_ODD_SIZE 0x40 #define ID_ODD_SIZE 0x40
#define ID_LARGE 0x80 #define ID_LARGE 0x80
@ -208,6 +219,7 @@ typedef struct {
#define ID_CUESHEET (ID_OPTIONAL_DATA | 0x4) #define ID_CUESHEET (ID_OPTIONAL_DATA | 0x4)
#define ID_CONFIG_BLOCK (ID_OPTIONAL_DATA | 0x5) #define ID_CONFIG_BLOCK (ID_OPTIONAL_DATA | 0x5)
#define ID_MD5_CHECKSUM (ID_OPTIONAL_DATA | 0x6) #define ID_MD5_CHECKSUM (ID_OPTIONAL_DATA | 0x6)
#define ID_SAMPLE_RATE (ID_OPTIONAL_DATA | 0x7)
///////////////////////// WavPack Configuration /////////////////////////////// ///////////////////////// WavPack Configuration ///////////////////////////////
@ -255,10 +267,10 @@ typedef struct {
#define CONFIG_MD5_CHECKSUM 0x8000000 // compute & store MD5 signature #define CONFIG_MD5_CHECKSUM 0x8000000 // compute & store MD5 signature
#define CONFIG_QUIET_MODE 0x10000000 // don't report progress % #define CONFIG_QUIET_MODE 0x10000000 // don't report progress %
#define CONFIG_IGNORE_LENGTH 0x20000000 // ignore length in wav header #define CONFIG_IGNORE_LENGTH 0x20000000 // ignore length in wav header
#define CONFIG_NEW_RIFF_HEADER 0x40000000 // generate new RIFF wav header
#define EXTRA_SCAN_ONLY 1 #define EXTRA_SCAN_ONLY 1
#define EXTRA_STEREO_MODES 2 #define EXTRA_STEREO_MODES 2
//#define EXTRA_CHECK_TERMS 4
#define EXTRA_TRY_DELTAS 8 #define EXTRA_TRY_DELTAS 8
#define EXTRA_ADJUST_DELTAS 16 #define EXTRA_ADJUST_DELTAS 16
#define EXTRA_SORT_FIRST 32 #define EXTRA_SORT_FIRST 32
@ -291,9 +303,7 @@ struct decorr_pass {
int term, delta, weight_A, weight_B; int term, delta, weight_A, weight_B;
int32_t samples_A [MAX_TERM], samples_B [MAX_TERM]; int32_t samples_A [MAX_TERM], samples_B [MAX_TERM];
int32_t aweight_A, aweight_B; int32_t aweight_A, aweight_B;
#ifdef PACK int32_t sum_A, sum_B;
int32_t sum_A, sum_B, min, max;
#endif
}; };
typedef struct { typedef struct {
@ -303,9 +313,9 @@ typedef struct {
uchar *block2buff, *block2end; uchar *block2buff, *block2end;
int32_t *sample_buffer; int32_t *sample_buffer;
int bits, num_terms, mute_error, false_stereo, shift;
uint32_t sample_index, crc, crc_x, crc_wvx; uint32_t sample_index, crc, crc_x, crc_wvx;
Bitstream wvbits, wvcbits, wvxbits; Bitstream wvbits, wvcbits, wvxbits;
int bits, num_terms, mute_error;
float delta_decay; float delta_decay;
uchar int32_sent_bits, int32_zeros, int32_ones, int32_dups; uchar int32_sent_bits, int32_zeros, int32_ones, int32_dups;
@ -349,9 +359,12 @@ typedef struct {
int (*push_back_byte)(void *id, int c); int (*push_back_byte)(void *id, int c);
uint32_t (*get_length)(void *id); uint32_t (*get_length)(void *id);
int (*can_seek)(void *id); int (*can_seek)(void *id);
} stream_reader;
typedef int (*blockout)(void *id, void *data, int32_t bcount); // this callback is for writing edited tags only
int32_t (*write_bytes)(void *id, void *data, int32_t bcount);
} WavpackStreamReader;
typedef int (*WavpackBlockOutput)(void *id, void *data, int32_t bcount);
typedef struct { typedef struct {
WavpackConfig config; WavpackConfig config;
@ -363,18 +376,18 @@ typedef struct {
uchar *wrapper_data; uchar *wrapper_data;
uint32_t wrapper_bytes; uint32_t wrapper_bytes;
blockout blockout; WavpackBlockOutput blockout;
void *wv_out, *wvc_out; void *wv_out, *wvc_out;
stream_reader *reader; WavpackStreamReader *reader;
void *wv_in, *wvc_in; void *wv_in, *wvc_in;
uint32_t filelen, file2len, filepos, file2pos, total_samples, crc_errors, first_flags; uint32_t filelen, file2len, filepos, file2pos, total_samples, crc_errors, first_flags;
int wvc_flag, open_flags, norm_offset, reduced_channels, lossy_blocks, close_files; int wvc_flag, open_flags, norm_offset, reduced_channels, lossy_blocks, close_files;
int block_samples, max_samples, acc_samples; int block_samples, max_samples, acc_samples, riff_header_added, riff_header_created;
M_Tag m_tag; M_Tag m_tag;
int current_stream, num_streams; int current_stream, num_streams, stream_version;
WavpackStream *streams [8]; WavpackStream *streams [8];
void *stream3; void *stream3;
@ -459,8 +472,14 @@ int DoCloseHandle (FILE *hFile), DoTruncateFile (FILE *hFile);
(bs)->bc += 8; \ (bs)->bc += 8; \
} \ } \
*(value) = (bs)->sr; \ *(value) = (bs)->sr; \
(bs)->sr >>= (nbits); \ if ((bs)->bc > 32) { \
(bs)->bc -= (nbits); \ (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); \ #define putbit(bit, bs) { if (bit) (bs)->sr |= (1 << (bs)->bc); \
@ -490,8 +509,9 @@ int DoCloseHandle (FILE *hFile), DoTruncateFile (FILE *hFile);
do { \ do { \
*((bs)->ptr) = (bs)->sr; \ *((bs)->ptr) = (bs)->sr; \
(bs)->sr >>= 8; \ (bs)->sr >>= 8; \
if (((bs)->bc -= 8) > 24) (bs)->sr |= ((value) >> ((nbits) - (bs)->bc)); \
if (++((bs)->ptr) == (bs)->end) (bs)->wrap (bs); \ if (++((bs)->ptr) == (bs)->end) (bs)->wrap (bs); \
} while (((bs)->bc -= 8) >= 8); \ } while ((bs)->bc >= 8); \
} }
void little_endian_to_native (void *data, char *format); void little_endian_to_native (void *data, char *format);
@ -517,6 +537,7 @@ int read_float_info (WavpackStream *wps, WavpackMetadata *wpmd);
int read_int32_info (WavpackStream *wps, WavpackMetadata *wpmd); int read_int32_info (WavpackStream *wps, WavpackMetadata *wpmd);
int read_channel_info (WavpackContext *wpc, WavpackMetadata *wpmd); int read_channel_info (WavpackContext *wpc, WavpackMetadata *wpmd);
int read_config_info (WavpackContext *wpc, WavpackMetadata *wpmd); int read_config_info (WavpackContext *wpc, WavpackMetadata *wpmd);
int read_sample_rate (WavpackContext *wpc, WavpackMetadata *wpmd);
int read_wrapper_data (WavpackContext *wpc, WavpackMetadata *wpmd); int read_wrapper_data (WavpackContext *wpc, WavpackMetadata *wpmd);
int32_t unpack_samples (WavpackContext *wpc, int32_t *buffer, uint32_t sample_count); int32_t unpack_samples (WavpackContext *wpc, int32_t *buffer, uint32_t sample_count);
int check_crc_error (WavpackContext *wpc); int check_crc_error (WavpackContext *wpc);
@ -535,11 +556,10 @@ int get_version3 (WavpackContext *wpc);
int copy_timestamp (const char *src_filename, const char *dst_filename); int copy_timestamp (const char *src_filename, const char *dst_filename);
char *filespec_ext (char *filespec), *filespec_path (char *filespec); char *filespec_ext (char *filespec), *filespec_path (char *filespec);
char *filespec_name (char *filespec), *filespec_wild (char *filespec); char *filespec_name (char *filespec), *filespec_wild (char *filespec);
void error_line (char *error, ...), finish_line (void); void error_line (char *error, ...);
void setup_break (void); void setup_break (void), finish_line (void);
int check_break (void); int check_break (void);
char yna (void); char yna (void);
void AnsiToUTF8 (char *string, int len);
#define FN_FIT(fn) ((strlen (fn) > 30) ? filespec_name (fn) : fn) #define FN_FIT(fn) ((strlen (fn) > 30) ? filespec_name (fn) : fn)
@ -570,10 +590,10 @@ void scan_word (WavpackStream *wps, int32_t *samples, uint32_t num_samples, int
int log2s (int32_t value); int log2s (int32_t value);
int32_t exp2s (int log); int32_t exp2s (int log);
uint32_t log2buffer (int32_t *samples, uint32_t num_samples); uint32_t log2buffer (int32_t *samples, uint32_t num_samples, int limit);
char store_weight (int weight); signed char store_weight (int weight);
int restore_weight (char weight); int restore_weight (signed char weight);
#define WORD_EOF (1L << 31) #define WORD_EOF (1L << 31)
@ -593,7 +613,7 @@ void analyze_mono (WavpackContext *wpc, int32_t *samples);
// wputils.c // wputils.c
WavpackContext *WavpackOpenFileInputEx (stream_reader *reader, void *wv_id, void *wvc_id, char *error, int flags, int norm_offset); WavpackContext *WavpackOpenFileInputEx (WavpackStreamReader *reader, void *wv_id, void *wvc_id, char *error, int flags, int norm_offset);
WavpackContext *WavpackOpenFileInput (const char *infilename, char *error, int flags, int norm_offset); WavpackContext *WavpackOpenFileInput (const char *infilename, char *error, int flags, int norm_offset);
#define OPEN_WVC 0x1 // open/read "correction" file #define OPEN_WVC 0x1 // open/read "correction" file
@ -603,6 +623,7 @@ WavpackContext *WavpackOpenFileInput (const char *infilename, char *error, int f
#define OPEN_NORMALIZE 0x10 // normalize floating point data to +/- 1.0 #define OPEN_NORMALIZE 0x10 // normalize floating point data to +/- 1.0
#define OPEN_STREAMING 0x20 // "streaming" mode blindly unpacks blocks #define OPEN_STREAMING 0x20 // "streaming" mode blindly unpacks blocks
// w/o regard to header file position info // w/o regard to header file position info
#define OPEN_EDIT_TAGS 0x40 // allow editing of tags
int WavpackGetMode (WavpackContext *wpc); int WavpackGetMode (WavpackContext *wpc);
@ -639,11 +660,14 @@ uint32_t WavpackGetFileSize (WavpackContext *wpc);
double WavpackGetRatio (WavpackContext *wpc); double WavpackGetRatio (WavpackContext *wpc);
double WavpackGetAverageBitrate (WavpackContext *wpc, int count_wvc); double WavpackGetAverageBitrate (WavpackContext *wpc, int count_wvc);
double WavpackGetInstantBitrate (WavpackContext *wpc); double WavpackGetInstantBitrate (WavpackContext *wpc);
int WavpackGetNumTagItems (WavpackContext *wpc);
int WavpackGetTagItem (WavpackContext *wpc, const char *item, char *value, int size); int WavpackGetTagItem (WavpackContext *wpc, const char *item, char *value, int size);
int WavpackAppendTagItem (WavpackContext *wpc, const char *item, const char *value); int WavpackGetTagItemIndexed (WavpackContext *wpc, int index, char *item, int size);
int WavpackAppendTagItem (WavpackContext *wpc, const char *item, const char *value, int vsize);
int WavpackDeleteTagItem (WavpackContext *wpc, const char *item);
int WavpackWriteTag (WavpackContext *wpc); int WavpackWriteTag (WavpackContext *wpc);
WavpackContext *WavpackOpenFileOutput (blockout blockout, void *wv_id, void *wvc_id); WavpackContext *WavpackOpenFileOutput (WavpackBlockOutput blockout, void *wv_id, void *wvc_id);
int WavpackSetConfiguration (WavpackContext *wpc, WavpackConfig *config, uint32_t total_samples); int WavpackSetConfiguration (WavpackContext *wpc, WavpackConfig *config, uint32_t total_samples);
int WavpackAddWrapper (WavpackContext *wpc, void *data, uint32_t bcount); int WavpackAddWrapper (WavpackContext *wpc, void *data, uint32_t bcount);
int WavpackStoreMD5Sum (WavpackContext *wpc, uchar data [16]); int WavpackStoreMD5Sum (WavpackContext *wpc, uchar data [16]);
@ -651,6 +675,6 @@ int WavpackPackInit (WavpackContext *wpc);
int WavpackPackSamples (WavpackContext *wpc, int32_t *sample_buffer, uint32_t sample_count); int WavpackPackSamples (WavpackContext *wpc, int32_t *sample_buffer, uint32_t sample_count);
int WavpackFlushSamples (WavpackContext *wpc); int WavpackFlushSamples (WavpackContext *wpc);
void WavpackUpdateNumSamples (WavpackContext *wpc, void *first_block); void WavpackUpdateNumSamples (WavpackContext *wpc, void *first_block);
void *WavpackGetWrapperLocation (void *first_block); void *WavpackGetWrapperLocation (void *first_block, uint32_t *size);
#endif #endif

View File

@ -200,7 +200,7 @@ void word_set_bitrate (WavpackStream *wps)
if (wps->wphdr.flags & HYBRID_BITRATE) { if (wps->wphdr.flags & HYBRID_BITRATE) {
bitrate_0 = wps->bits < 568 ? 0 : wps->bits - 568; bitrate_0 = wps->bits < 568 ? 0 : wps->bits - 568;
if (!(wps->wphdr.flags & MONO_FLAG)) { if (!(wps->wphdr.flags & MONO_DATA)) {
if (wps->wphdr.flags & HYBRID_BALANCE) if (wps->wphdr.flags & HYBRID_BALANCE)
bitrate_1 = (wps->wphdr.flags & JOINT_STEREO) ? 256 : 0; bitrate_1 = (wps->wphdr.flags & JOINT_STEREO) ? 256 : 0;
@ -248,7 +248,7 @@ void write_entropy_vars (WavpackStream *wps, WavpackMetadata *wpmd)
*byteptr++ = temp = mylog2 (wps->w.median [2] [0]); *byteptr++ = temp = mylog2 (wps->w.median [2] [0]);
*byteptr++ = temp >> 8; *byteptr++ = temp >> 8;
if (!(wps->wphdr.flags & MONO_FLAG)) { if (!(wps->wphdr.flags & MONO_DATA)) {
*byteptr++ = temp = mylog2 (wps->w.median [0] [1]); *byteptr++ = temp = mylog2 (wps->w.median [0] [1]);
*byteptr++ = temp >> 8; *byteptr++ = temp >> 8;
*byteptr++ = temp = mylog2 (wps->w.median [1] [1]); *byteptr++ = temp = mylog2 (wps->w.median [1] [1]);
@ -281,7 +281,7 @@ void write_hybrid_profile (WavpackStream *wps, WavpackMetadata *wpmd)
*byteptr++ = temp = log2s (wps->w.slow_level [0]); *byteptr++ = temp = log2s (wps->w.slow_level [0]);
*byteptr++ = temp >> 8; *byteptr++ = temp >> 8;
if (!(wps->wphdr.flags & MONO_FLAG)) { if (!(wps->wphdr.flags & MONO_DATA)) {
*byteptr++ = temp = log2s (wps->w.slow_level [1]); *byteptr++ = temp = log2s (wps->w.slow_level [1]);
*byteptr++ = temp >> 8; *byteptr++ = temp >> 8;
} }
@ -290,7 +290,7 @@ void write_hybrid_profile (WavpackStream *wps, WavpackMetadata *wpmd)
*byteptr++ = temp = wps->w.bitrate_acc [0] >> 16; *byteptr++ = temp = wps->w.bitrate_acc [0] >> 16;
*byteptr++ = temp >> 8; *byteptr++ = temp >> 8;
if (!(wps->wphdr.flags & MONO_FLAG)) { if (!(wps->wphdr.flags & MONO_DATA)) {
*byteptr++ = temp = wps->w.bitrate_acc [1] >> 16; *byteptr++ = temp = wps->w.bitrate_acc [1] >> 16;
*byteptr++ = temp >> 8; *byteptr++ = temp >> 8;
} }
@ -299,7 +299,7 @@ void write_hybrid_profile (WavpackStream *wps, WavpackMetadata *wpmd)
*byteptr++ = temp = log2s (wps->w.bitrate_delta [0]); *byteptr++ = temp = log2s (wps->w.bitrate_delta [0]);
*byteptr++ = temp >> 8; *byteptr++ = temp >> 8;
if (!(wps->wphdr.flags & MONO_FLAG)) { if (!(wps->wphdr.flags & MONO_DATA)) {
*byteptr++ = temp = log2s (wps->w.bitrate_delta [1]); *byteptr++ = temp = log2s (wps->w.bitrate_delta [1]);
*byteptr++ = temp >> 8; *byteptr++ = temp >> 8;
} }
@ -319,14 +319,14 @@ int read_entropy_vars (WavpackStream *wps, WavpackMetadata *wpmd)
{ {
uchar *byteptr = wpmd->data; uchar *byteptr = wpmd->data;
if (wpmd->byte_length != ((wps->wphdr.flags & MONO_FLAG) ? 6 : 12)) if (wpmd->byte_length != ((wps->wphdr.flags & MONO_DATA) ? 6 : 12))
return FALSE; return FALSE;
wps->w.median [0] [0] = exp2s (byteptr [0] + (byteptr [1] << 8)); 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 [1] [0] = exp2s (byteptr [2] + (byteptr [3] << 8));
wps->w.median [2] [0] = exp2s (byteptr [4] + (byteptr [5] << 8)); wps->w.median [2] [0] = exp2s (byteptr [4] + (byteptr [5] << 8));
if (!(wps->wphdr.flags & MONO_FLAG)) { if (!(wps->wphdr.flags & MONO_DATA)) {
wps->w.median [0] [1] = exp2s (byteptr [6] + (byteptr [7] << 8)); 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 [1] [1] = exp2s (byteptr [8] + (byteptr [9] << 8));
wps->w.median [2] [1] = exp2s (byteptr [10] + (byteptr [11] << 8)); wps->w.median [2] [1] = exp2s (byteptr [10] + (byteptr [11] << 8));
@ -349,7 +349,7 @@ int read_hybrid_profile (WavpackStream *wps, WavpackMetadata *wpmd)
wps->w.slow_level [0] = exp2s (byteptr [0] + (byteptr [1] << 8)); wps->w.slow_level [0] = exp2s (byteptr [0] + (byteptr [1] << 8));
byteptr += 2; byteptr += 2;
if (!(wps->wphdr.flags & MONO_FLAG)) { if (!(wps->wphdr.flags & MONO_DATA)) {
wps->w.slow_level [1] = exp2s (byteptr [0] + (byteptr [1] << 8)); wps->w.slow_level [1] = exp2s (byteptr [0] + (byteptr [1] << 8));
byteptr += 2; byteptr += 2;
} }
@ -358,7 +358,7 @@ int read_hybrid_profile (WavpackStream *wps, WavpackMetadata *wpmd)
wps->w.bitrate_acc [0] = (int32_t)(byteptr [0] + (byteptr [1] << 8)) << 16; wps->w.bitrate_acc [0] = (int32_t)(byteptr [0] + (byteptr [1] << 8)) << 16;
byteptr += 2; byteptr += 2;
if (!(wps->wphdr.flags & MONO_FLAG)) { if (!(wps->wphdr.flags & MONO_DATA)) {
wps->w.bitrate_acc [1] = (int32_t)(byteptr [0] + (byteptr [1] << 8)) << 16; wps->w.bitrate_acc [1] = (int32_t)(byteptr [0] + (byteptr [1] << 8)) << 16;
byteptr += 2; byteptr += 2;
} }
@ -367,7 +367,7 @@ int read_hybrid_profile (WavpackStream *wps, WavpackMetadata *wpmd)
wps->w.bitrate_delta [0] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8))); wps->w.bitrate_delta [0] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8)));
byteptr += 2; byteptr += 2;
if (!(wps->wphdr.flags & MONO_FLAG)) { if (!(wps->wphdr.flags & MONO_DATA)) {
wps->w.bitrate_delta [1] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8))); wps->w.bitrate_delta [1] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8)));
byteptr += 2; byteptr += 2;
} }
@ -391,7 +391,7 @@ static void update_error_limit (WavpackStream *wps)
{ {
int bitrate_0 = (wps->w.bitrate_acc [0] += wps->w.bitrate_delta [0]) >> 16; int bitrate_0 = (wps->w.bitrate_acc [0] += wps->w.bitrate_delta [0]) >> 16;
if (wps->wphdr.flags & MONO_FLAG) { if (wps->wphdr.flags & MONO_DATA) {
if (wps->wphdr.flags & HYBRID_BITRATE) { if (wps->wphdr.flags & HYBRID_BITRATE) {
int slow_log_0 = (wps->w.slow_level [0] + SLO) >> SLS; int slow_log_0 = (wps->w.slow_level [0] + SLO) >> SLS;
@ -781,13 +781,6 @@ void flush_word (WavpackStream *wps)
} }
if (wps->w.pend_count) { 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); putbits (wps->w.pend_data, wps->w.pend_count, &wps->wvbits);
wps->w.pend_data = wps->w.pend_count = 0; wps->w.pend_data = wps->w.pend_count = 0;
} }
@ -872,7 +865,7 @@ void scan_word (WavpackStream *wps, int32_t *samples, uint32_t num_samples, int
CLEAR (wps->w.slow_level); CLEAR (wps->w.slow_level);
CLEAR (wps->w.median); CLEAR (wps->w.median);
if (flags & MONO_FLAG) { if (flags & MONO_DATA) {
if (dir < 0) { if (dir < 0) {
samples += (num_samples - 1); samples += (num_samples - 1);
dir = -1; dir = -1;
@ -921,7 +914,7 @@ void scan_word (WavpackStream *wps, int32_t *samples, uint32_t num_samples, int
} }
} }
if (!(flags & MONO_FLAG)) { if (!(flags & MONO_DATA)) {
value = labs (samples [chan = 1]); value = labs (samples [chan = 1]);
if (wps->wphdr.flags & HYBRID_BITRATE) { if (wps->wphdr.flags & HYBRID_BITRATE) {
@ -1353,7 +1346,7 @@ static int FASTCALL mylog2 (uint32_t avalue)
// because the bitstream storage required for entropy coding is proportional // because the bitstream storage required for entropy coding is proportional
// to the base 2 log of the samples. // to the base 2 log of the samples.
uint32_t log2buffer (int32_t *samples, uint32_t num_samples) uint32_t log2buffer (int32_t *samples, uint32_t num_samples, int limit)
{ {
uint32_t result = 0, avalue; uint32_t result = 0, avalue;
int dbits; int dbits;
@ -1373,7 +1366,10 @@ uint32_t log2buffer (int32_t *samples, uint32_t num_samples)
else else
dbits = nbits_table [avalue >> 24] + 24; dbits = nbits_table [avalue >> 24] + 24;
result += (dbits << 8) + log2_table [(avalue >> (dbits - 9)) & 0xff]; result += dbits = (dbits << 8) + log2_table [(avalue >> (dbits - 9)) & 0xff];
if (limit && dbits >= limit)
return (uint32_t) -1;
} }
} }
@ -1413,7 +1409,7 @@ int32_t exp2s (int log)
// to and from an 8-bit signed character version for storage in metadata. The // 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. // weights are clipped here in the case that they are outside that range.
char store_weight (int weight) signed char store_weight (int weight)
{ {
if (weight > 1024) if (weight > 1024)
weight = 1024; weight = 1024;
@ -1426,7 +1422,7 @@ char store_weight (int weight)
return (weight + 4) >> 3; return (weight + 4) >> 3;
} }
int restore_weight (char weight) int restore_weight (signed char weight)
{ {
int result; int result;

File diff suppressed because it is too large Load Diff

View File

@ -62,11 +62,13 @@ typedef struct {
#define CONFIG_BITRATE_KBPS 0x2000 // bitrate is kbps, not bits / sample #define CONFIG_BITRATE_KBPS 0x2000 // bitrate is kbps, not bits / sample
#define CONFIG_SHAPE_OVERRIDE 0x8000 // shaping mode specified #define CONFIG_SHAPE_OVERRIDE 0x8000 // shaping mode specified
#define CONFIG_JOINT_OVERRIDE 0x10000 // joint-stereo mode specified #define CONFIG_JOINT_OVERRIDE 0x10000 // joint-stereo mode specified
#define CONFIG_CREATE_EXE 0x40000 // create executable
#define CONFIG_CREATE_WVC 0x80000 // create correction file #define CONFIG_CREATE_WVC 0x80000 // create correction file
#define CONFIG_OPTIMIZE_WVC 0x100000 // maximize bybrid compression #define CONFIG_OPTIMIZE_WVC 0x100000 // maximize bybrid compression
#define CONFIG_CALC_NOISE 0x800000 // calc noise in hybrid mode #define CONFIG_CALC_NOISE 0x800000 // calc noise in hybrid mode
#define CONFIG_EXTRA_MODE 0x2000000 // extra processing mode #define CONFIG_EXTRA_MODE 0x2000000 // extra processing mode
#define CONFIG_SKIP_WVX 0x4000000 // no wvx stream w/ floats & big ints #define CONFIG_SKIP_WVX 0x4000000 // no wvx stream w/ floats & big ints
#define CONFIG_MD5_CHECKSUM 0x8000000 // store MD5 signature
////////////// Callbacks used for reading & writing WavPack streams ////////// ////////////// Callbacks used for reading & writing WavPack streams //////////
@ -78,9 +80,12 @@ typedef struct {
int (*push_back_byte)(void *id, int c); int (*push_back_byte)(void *id, int c);
uint32_t (*get_length)(void *id); uint32_t (*get_length)(void *id);
int (*can_seek)(void *id); int (*can_seek)(void *id);
} stream_reader;
typedef int (*blockout)(void *id, void *data, int32_t bcount); // this callback is for writing edited tags only
int32_t (*write_bytes)(void *id, void *data, int32_t bcount);
} WavpackStreamReader;
typedef int (*WavpackBlockOutput)(void *id, void *data, int32_t bcount);
//////////////////////// function prototypes and macros ////////////////////// //////////////////////// function prototypes and macros //////////////////////
@ -90,7 +95,7 @@ typedef void WavpackContext;
extern "C" { extern "C" {
#endif #endif
WavpackContext *WavpackOpenFileInputEx (stream_reader *reader, void *wv_id, void *wvc_id, char *error, int flags, int norm_offset); WavpackContext *WavpackOpenFileInputEx (WavpackStreamReader *reader, void *wv_id, void *wvc_id, char *error, int flags, int norm_offset);
WavpackContext *WavpackOpenFileInput (const char *infilename, char *error, int flags, int norm_offset); WavpackContext *WavpackOpenFileInput (const char *infilename, char *error, int flags, int norm_offset);
#define OPEN_WVC 0x1 // open/read "correction" file #define OPEN_WVC 0x1 // open/read "correction" file
@ -100,6 +105,7 @@ WavpackContext *WavpackOpenFileInput (const char *infilename, char *error, int f
#define OPEN_NORMALIZE 0x10 // normalize floating point data to +/- 1.0 #define OPEN_NORMALIZE 0x10 // normalize floating point data to +/- 1.0
#define OPEN_STREAMING 0x20 // "streaming" mode blindly unpacks blocks #define OPEN_STREAMING 0x20 // "streaming" mode blindly unpacks blocks
// w/o regard to header file position info // w/o regard to header file position info
#define OPEN_EDIT_TAGS 0x40 // allow editing of tags
int WavpackGetMode (WavpackContext *wpc); int WavpackGetMode (WavpackContext *wpc);
@ -137,12 +143,15 @@ uint32_t WavpackGetFileSize (WavpackContext *wpc);
double WavpackGetRatio (WavpackContext *wpc); double WavpackGetRatio (WavpackContext *wpc);
double WavpackGetAverageBitrate (WavpackContext *wpc, int count_wvc); double WavpackGetAverageBitrate (WavpackContext *wpc, int count_wvc);
double WavpackGetInstantBitrate (WavpackContext *wpc); double WavpackGetInstantBitrate (WavpackContext *wpc);
int WavpackGetNumTagItems (WavpackContext *wpc);
int WavpackGetTagItem (WavpackContext *wpc, const char *item, char *value, int size); int WavpackGetTagItem (WavpackContext *wpc, const char *item, char *value, int size);
int WavpackAppendTagItem (WavpackContext *wpc, const char *item, const char *value); int WavpackGetTagItemIndexed (WavpackContext *wpc, int index, char *item, int size);
int WavpackAppendTagItem (WavpackContext *wpc, const char *item, const char *value, int vsize);
int WavpackDeleteTagItem (WavpackContext *wpc, const char *item);
int WavpackWriteTag (WavpackContext *wpc); int WavpackWriteTag (WavpackContext *wpc);
WavpackContext *WavpackOpenFileOutput (blockout blockout, void *wv_id, void *wvc_id); WavpackContext *WavpackOpenFileOutput (WavpackBlockOutput blockout, void *wv_id, void *wvc_id);
int WavpackSetConfiguration (WavpackContext *wpc, WavpackConfig *config, uint32_t total_samples); int WavpackSetConfiguration (WavpackContext *wpc, WavpackConfig *config, uint32_t total_samples);
int WavpackAddWrapper (WavpackContext *wpc, void *data, uint32_t bcount); int WavpackAddWrapper (WavpackContext *wpc, void *data, uint32_t bcount);
int WavpackStoreMD5Sum (WavpackContext *wpc, uchar data [16]); int WavpackStoreMD5Sum (WavpackContext *wpc, uchar data [16]);
@ -150,7 +159,7 @@ int WavpackPackInit (WavpackContext *wpc);
int WavpackPackSamples (WavpackContext *wpc, int32_t *sample_buffer, uint32_t sample_count); int WavpackPackSamples (WavpackContext *wpc, int32_t *sample_buffer, uint32_t sample_count);
int WavpackFlushSamples (WavpackContext *wpc); int WavpackFlushSamples (WavpackContext *wpc);
void WavpackUpdateNumSamples (WavpackContext *wpc, void *first_block); void WavpackUpdateNumSamples (WavpackContext *wpc, void *first_block);
void *WavpackGetWrapperLocation (void *first_block); void *WavpackGetWrapperLocation (void *first_block, uint32_t *size);
// this function is not actually in wputils.c, but is generally useful // this function is not actually in wputils.c, but is generally useful

View File

@ -16,15 +16,15 @@
#else #else
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/param.h> #include <sys/param.h>
#include <locale.h>
#include <iconv.h>
#if defined (__GNUC__) #if defined (__GNUC__)
#include <unistd.h> #include <unistd.h>
#include <glob.h> #include <glob.h>
#endif #endif
#endif #endif
#ifdef __BORLANDC__ #if defined(__GNUC__) && !defined(WIN32)
#include <dir.h>
#elif defined(__GNUC__) && !defined(WIN32)
#include <sys/time.h> #include <sys/time.h>
#else #else
#include <sys/timeb.h> #include <sys/timeb.h>
@ -53,25 +53,39 @@ static char *strdup (const char *s)
///////////////////////////// local variable storage ////////////////////////// ///////////////////////////// local variable storage //////////////////////////
static const char *sign_on = "\n" static const char *sign_on = "\n"
" WVUNPACK Hybrid Lossless Wavefile Decompressor %s Version %s %s\n" " WVUNPACK Hybrid Lossless Audio Decompressor %s Version %s %s\n"
" Copyright (c) 1998 - 2005 Conifer Software. All Rights Reserved.\n\n"; " Copyright (c) 1998 - 2005 Conifer Software. All Rights Reserved.\n\n";
static const char *usage = static const char *usage =
#if defined (WIN32)
" Usage: WVUNPACK [-options] [@]infile[.wv]|- [[@]outfile[.wav]|outpath|-]\n" " Usage: WVUNPACK [-options] [@]infile[.wv]|- [[@]outfile[.wav]|outpath|-]\n"
#else
" Usage: WVUNPACK [-options] [@]infile[.wv]|- [...] [-o [@]outfile[.wav]|outpath|-]\n"
#endif
" (infile may contain wildcards: ?,*)\n\n" " (infile may contain wildcards: ?,*)\n\n"
" Options: -d = delete source file if successful (use with caution!)\n" " Options: -d = delete source file if successful (use with caution!)\n"
" -i = ignore .wvc file (forces hybrid lossy decompression)\n" " -i = ignore .wvc file (forces hybrid lossy decompression)\n"
#if defined (WIN32)
" -l = run at low priority (for smoother multitasking)\n"
#endif
" -m = calculate and display MD5 signature; verify if lossless\n" " -m = calculate and display MD5 signature; verify if lossless\n"
" -q = quiet (keep console output to a minimum)\n" " -q = quiet (keep console output to a minimum)\n"
#if !defined (WIN32)
" -o FILENAME | PATH = specify output filename or path\n"
#endif
" -r = force raw audio decode (skip RIFF headers & trailers)\n" " -r = force raw audio decode (skip RIFF headers & trailers)\n"
" -s = display summary information only to stdout (no decode)\n" " -s = display summary information only to stdout (no decode)\n"
#if defined (WIN32) " -ss = display super summary (including tags) to stdout (no decode)\n"
" -t = copy input file's time stamp to output file(s)\n" " -t = copy input file's time stamp to output file(s)\n"
#endif
" -v = verify source data only (no output file created)\n" " -v = verify source data only (no output file created)\n"
" -y = yes to overwrite warning (use with caution!)\n\n" " -y = yes to overwrite warning (use with caution!)\n\n"
" Web: Visit www.wavpack.com for latest version and info\n"; " Web: Visit www.wavpack.com for latest version and info\n";
// this global is used to indicate the special "debug" mode where extra debug messages
// are displayed and all messages are logged to the file \wavpack.log
int debug_logging_mode;
static char overwrite_all = 0, delete_source = 0, raw_decode = 0, summary = 0, static char overwrite_all = 0, delete_source = 0, raw_decode = 0, summary = 0,
ignore_wvc = 0, quiet_mode = 0, calc_md5 = 0, copy_time = 0; ignore_wvc = 0, quiet_mode = 0, calc_md5 = 0, copy_time = 0;
@ -92,18 +106,35 @@ static void display_progress (double file_progress);
int main (argc, argv) int argc; char **argv; int main (argc, argv) int argc; char **argv;
{ {
int verify_only = 0, usage_error = 0, filelist = 0, add_extension = 0; int verify_only = 0, error_count = 0, add_extension = 0, output_spec = 0;
char *infilename = NULL, *outfilename = NULL; char outpath, **matches = NULL, *outfilename = NULL;
char outpath, **matches = NULL;
int result, i; int result, i;
#ifdef __BORLANDC__ #if defined(WIN32)
struct ffblk ffblk;
#elif defined(WIN32)
struct _finddata_t _finddata_t; struct _finddata_t _finddata_t;
char selfname [MAX_PATH];
if (GetModuleFileName (NULL, selfname, sizeof (selfname)) && filespec_name (selfname) &&
strupr (filespec_name (selfname)) && strstr (filespec_name (selfname), "DEBUG")) {
char **argv_t = argv;
int argc_t = argc;
debug_logging_mode = TRUE;
while (--argc_t)
error_line ("arg %d: %s", argc - argc_t, *++argv_t);
}
#else #else
glob_t globs; if (filespec_name (*argv))
struct stat fstats; if (strstr (filespec_name (*argv), "ebug") || strstr (filespec_name (*argv), "DEBUG")) {
char **argv_t = argv;
int argc_t = argc;
debug_logging_mode = TRUE;
while (--argc_t)
error_line ("arg %d: %s", argc - argc_t, *++argv_t);
}
#endif #endif
// loop through command-line arguments // loop through command-line arguments
@ -123,17 +154,26 @@ int main (argc, argv) int argc; char **argv;
case 'D': case 'd': case 'D': case 'd':
delete_source = 1; delete_source = 1;
break; break;
#if defined (WIN32) #if defined (WIN32)
case 'L': case 'l':
SetPriorityClass (GetCurrentProcess(), IDLE_PRIORITY_CLASS);
break;
#else
case 'O': case 'o':
output_spec = 1;
break;
#endif
case 'T': case 't': case 'T': case 't':
copy_time = 1; copy_time = 1;
break; break;
#endif
case 'V': case 'v': case 'V': case 'v':
verify_only = 1; verify_only = 1;
break; break;
case 'S': case 's': case 'S': case 's':
summary = 1; ++summary;
break; break;
case 'K': case 'k': case 'K': case 'k':
@ -159,12 +199,20 @@ int main (argc, argv) int argc; char **argv;
default: default:
error_line ("illegal option: %c !", **argv); error_line ("illegal option: %c !", **argv);
usage_error = 1; ++error_count;
} }
else { else {
if (!infilename) { #if defined (WIN32)
infilename = malloc (strlen (*argv) + PATH_MAX); if (!num_files) {
strcpy (infilename, *argv); matches = realloc (matches, (num_files + 1) * sizeof (*matches));
matches [num_files] = malloc (strlen (*argv) + 10);
strcpy (matches [num_files], *argv);
if (*(matches [num_files]) != '-' && *(matches [num_files]) != '@' &&
!filespec_ext (matches [num_files]))
strcat (matches [num_files], ".wv");
num_files++;
} }
else if (!outfilename) { else if (!outfilename) {
outfilename = malloc (strlen (*argv) + PATH_MAX); outfilename = malloc (strlen (*argv) + PATH_MAX);
@ -172,8 +220,26 @@ int main (argc, argv) int argc; char **argv;
} }
else { else {
error_line ("extra unknown argument: %s !", *argv); error_line ("extra unknown argument: %s !", *argv);
usage_error = 1; ++error_count;
} }
#else
if (output_spec) {
outfilename = malloc (strlen (*argv) + PATH_MAX);
strcpy (outfilename, *argv);
output_spec = 0;
}
else {
matches = realloc (matches, (num_files + 1) * sizeof (*matches));
matches [num_files] = malloc (strlen (*argv) + 10);
strcpy (matches [num_files], *argv);
if (*(matches [num_files]) != '-' && *(matches [num_files]) != '@' &&
!filespec_ext (matches [num_files]))
strcat (matches [num_files], ".wv");
num_files++;
}
#endif
} }
} }
@ -186,109 +252,105 @@ int main (argc, argv) int argc; char **argv;
if (verify_only && outfilename) { if (verify_only && outfilename) {
error_line ("outfile specification and verify mode are incompatible!"); error_line ("outfile specification and verify mode are incompatible!");
usage_error = 1; ++error_count;
} }
if (!quiet_mode && !usage_error) if (!quiet_mode && !error_count)
fprintf (stderr, sign_on, VERSION_OS, VERSION_STR, DATE_STR); fprintf (stderr, sign_on, VERSION_OS, VERSION_STR, DATE_STR);
if (!infilename) { if (!num_files) {
printf ("%s", usage); printf ("%s", usage);
return 0; return 1;
} }
if (usage_error) { if (error_count)
free (infilename); return 1;
return 0;
}
setup_break (); setup_break ();
// If the infile specification begins with a '@', then it actually points for (file_index = 0; file_index < num_files; ++file_index) {
// to a file that contains the names of the files to be converted. This char *infilename = matches [file_index];
// was included for use by Wim Speekenbrink's frontends, but could be used
// for other purposes.
if (infilename [0] == '@') { // If the single infile specification begins with a '@', then it
FILE *list = fopen (infilename+1, "rt"); // actually points to a file that contains the names of the files
int c; // to be converted. This was included for use by Wim Speekenbrink's
// frontends, but could be used for other purposes.
if (list == NULL) { if (*infilename == '@') {
error_line ("file %s not found!", infilename+1); FILE *list = fopen (infilename+1, "rt");
free(infilename); int di, c;
return 1;
}
while ((c = getc (list)) != EOF) { for (di = file_index; di < num_files - 1; di++)
matches [di] = matches [di + 1];
while (c == '\n') file_index--;
c = getc (list); num_files--;
if (c != EOF) { if (list == NULL) {
char *fname = malloc (PATH_MAX); error_line ("file %s not found!", infilename+1);
int ci = 0; free (infilename);
return 1;
do
fname [ci++] = c;
while ((c = getc (list)) != '\n' && c != EOF && ci < PATH_MAX);
fname [ci++] = '\0';
matches = realloc (matches, ++num_files * sizeof (*matches));
matches [num_files - 1] = realloc (fname, ci);
} }
}
fclose (list); while ((c = getc (list)) != EOF) {
free (infilename);
infilename = NULL;
filelist = 1;
}
else if (*infilename != '-') { // skip this if infile is stdin (-)
if (!filespec_ext (infilename))
strcat (infilename, ".wv");
#ifdef NO_WILDCARDS while (c == '\n')
matches = malloc (sizeof (*matches)); c = getc (list);
matches [num_files++] = infilename;
filelist = 1;
#else
// search for and store any filenames that match the user supplied spec
#ifdef __BORLANDC__ if (c != EOF) {
if (findfirst (infilename, &ffblk, 0) == 0) { char *fname = malloc (PATH_MAX);
do { int ci = 0;
matches = realloc (matches, ++num_files * sizeof (*matches));
matches [num_files - 1] = strdup (ffblk.ff_name); do
} while (findnext (&ffblk) == 0); fname [ci++] = c;
} while ((c = getc (list)) != '\n' && c != EOF && ci < PATH_MAX);
#elif defined (WIN32)
if ((i = _findfirst (infilename, &_finddata_t)) != -1L) { fname [ci++] = '\0';
do { fname = realloc (fname, ci);
if (!(_finddata_t.attrib & _A_SUBDIR)) {
matches = realloc (matches, ++num_files * sizeof (*matches)); matches = realloc (matches, ++num_files * sizeof (*matches));
matches [num_files - 1] = strdup (_finddata_t.name);
for (di = num_files - 1; di > file_index + 1; di--)
matches [di] = matches [di - 1];
matches [++file_index] = fname;
} }
} while (_findnext (i, &_finddata_t) == 0); }
_findclose (i); fclose (list);
free (infilename);
}
#if defined (WIN32)
else if (filespec_wild (infilename)) {
FILE *list = fopen (infilename+1, "rt");
int di;
for (di = file_index; di < num_files - 1; di++)
matches [di] = matches [di + 1];
file_index--;
num_files--;
if ((i = _findfirst (infilename, &_finddata_t)) != -1L) {
do {
if (!(_finddata_t.attrib & _A_SUBDIR)) {
matches = realloc (matches, ++num_files * sizeof (*matches));
for (di = num_files - 1; di > file_index + 1; di--)
matches [di] = matches [di - 1];
matches [++file_index] = malloc (strlen (infilename) + strlen (_finddata_t.name) + 10);
strcpy (matches [file_index], infilename);
*filespec_name (matches [file_index]) = '\0';
strcat (matches [file_index], _finddata_t.name);
}
} while (_findnext (i, &_finddata_t) == 0);
_findclose (i);
}
free (infilename);
} }
#else
i = 0;
if (glob(infilename, 0, NULL, &globs) == 0 && globs.gl_pathc > 0) {
do {
if (stat(globs.gl_pathv[i], &fstats) == 0 && !(fstats.st_mode & S_IFDIR)) {
matches = realloc (matches, ++num_files * sizeof (*matches));
matches [num_files - 1] = strdup (globs.gl_pathv[i]);
}
} while (i++ < globs.gl_pathc);
}
globfree(&globs);
#endif #endif
#endif
}
else { // handle case of stdin (-)
matches = malloc (sizeof (*matches));
matches [num_files++] = infilename;
} }
// If the outfile specification begins with a '@', then it actually points // If the outfile specification begins with a '@', then it actually points
@ -330,14 +392,12 @@ int main (argc, argv) int argc; char **argv;
// if we found any files to process, this is where we start // if we found any files to process, this is where we start
if (num_files) { if (num_files) {
int soft_errors = 0;
if (outfilename && *outfilename != '-') { if (outfilename && *outfilename != '-') {
outpath = (filespec_path (outfilename) != NULL); outpath = (filespec_path (outfilename) != NULL);
if (num_files > 1 && !outpath) { if (num_files > 1 && !outpath) {
error_line ("%s is not a valid output path", outfilename); error_line ("%s is not a valid output path", outfilename);
free(outfilename); free (outfilename);
return 1; return 1;
} }
} }
@ -352,15 +412,6 @@ int main (argc, argv) int argc; char **argv;
if (check_break ()) if (check_break ())
break; break;
// get input filename from list
if (filelist)
infilename = matches [file_index];
else if (*infilename != '-') {
*filespec_name (infilename) = '\0';
strcat (infilename, matches [file_index]);
}
// generate output filename // generate output filename
if (outpath) { if (outpath) {
@ -370,8 +421,8 @@ int main (argc, argv) int argc; char **argv;
*filespec_ext (outfilename) = '\0'; *filespec_ext (outfilename) = '\0';
} }
else if (!outfilename) { else if (!outfilename) {
outfilename = malloc (strlen (infilename) + 10); outfilename = malloc (strlen (matches [file_index]) + 10);
strcpy (outfilename, infilename); strcpy (outfilename, matches [file_index]);
if (filespec_ext (outfilename)) if (filespec_ext (outfilename))
*filespec_ext (outfilename) = '\0'; *filespec_ext (outfilename) = '\0';
@ -381,14 +432,15 @@ int main (argc, argv) int argc; char **argv;
strcat (outfilename, raw_decode ? ".raw" : ".wav"); strcat (outfilename, raw_decode ? ".raw" : ".wav");
if (num_files > 1) if (num_files > 1)
fprintf (stderr, "\n%s:\n", infilename); fprintf (stderr, "\n%s:\n", matches [file_index]);
result = unpack_file (infilename, verify_only ? NULL : outfilename); result = unpack_file (matches [file_index], verify_only ? NULL : outfilename);
if (result != NO_ERROR)
++error_count;
if (result == HARD_ERROR) if (result == HARD_ERROR)
break; break;
else if (result == SOFT_ERROR)
++soft_errors;
// clean up in preparation for potentially another file // clean up in preparation for potentially another file
@ -403,26 +455,27 @@ int main (argc, argv) int argc; char **argv;
} }
if (num_files > 1) { if (num_files > 1) {
if (soft_errors) if (error_count)
fprintf (stderr, "\n **** warning: errors occurred in %d of %d files! ****\n", soft_errors, num_files); fprintf (stderr, "\n **** warning: errors occurred in %d of %d files! ****\n", error_count, num_files);
else if (!quiet_mode) else if (!quiet_mode)
fprintf (stderr, "\n **** %d files successfully processed ****\n", num_files); fprintf (stderr, "\n **** %d files successfully processed ****\n", num_files);
} }
free (matches); free (matches);
} }
else else {
error_line (filespec_wild (infilename) ? "nothing to do!" : error_line ("nothing to do!");
"file %s not found!", infilename); ++error_count;
}
if (outfilename) if (outfilename)
free(outfilename); free (outfilename);
#ifdef DEBUG_ALLOC #ifdef DEBUG_ALLOC
error_line ("malloc_count = %d", dump_alloc ()); error_line ("malloc_count = %d", dump_alloc ());
#endif #endif
return 0; return error_count ? 1 : 0;
} }
// Unpack the specified WavPack input file into the specified output file name. // Unpack the specified WavPack input file into the specified output file name.
@ -436,8 +489,6 @@ int main (argc, argv) int argc; char **argv;
static uchar *format_samples (int bps, uchar *dst, int32_t *src, uint32_t samcnt); static uchar *format_samples (int bps, uchar *dst, int32_t *src, uint32_t samcnt);
static void dump_summary (WavpackContext *wpc, char *name, FILE *dst); static void dump_summary (WavpackContext *wpc, char *name, FILE *dst);
extern int delta_blocks [8];
static int unpack_file (char *infilename, char *outfilename) static int unpack_file (char *infilename, char *outfilename)
{ {
int result = NO_ERROR, md5_diff = FALSE, open_flags = 0, bytes_per_sample, num_channels, wvc_mode, bps; int result = NO_ERROR, md5_diff = FALSE, open_flags = 0, bytes_per_sample, num_channels, wvc_mode, bps;
@ -450,9 +501,7 @@ static int unpack_file (char *infilename, char *outfilename)
char error [80]; char error [80];
FILE *outfile; FILE *outfile;
#ifdef __BORLANDC__ #if defined(WIN32)
struct time time1, time2;
#elif defined(WIN32)
struct _timeb time1, time2; struct _timeb time1, time2;
#else #else
struct timeval time1, time2; struct timeval time1, time2;
@ -470,6 +519,9 @@ static int unpack_file (char *infilename, char *outfilename)
if (!ignore_wvc) if (!ignore_wvc)
open_flags |= OPEN_WVC; open_flags |= OPEN_WVC;
if (summary > 1)
open_flags |= OPEN_TAGS;
wpc = WavpackOpenFileInput (infilename, error, open_flags, 0); wpc = WavpackOpenFileInput (infilename, error, open_flags, 0);
if (!wpc) { if (!wpc) {
@ -491,6 +543,12 @@ static int unpack_file (char *infilename, char *outfilename)
return NO_ERROR; return NO_ERROR;
} }
if (!WavpackGetWrapperBytes (wpc) && outfilename && !raw_decode) {
error_line ("no wav header, can only decode to raw file (use -r)!");
WavpackCloseFile (wpc);
return SOFT_ERROR;
}
if (outfilename) { if (outfilename) {
if (*outfilename != '-') { if (*outfilename != '-') {
@ -554,9 +612,7 @@ static int unpack_file (char *infilename, char *outfilename)
FN_FIT (infilename), wvc_mode ? " (+.wvc)" : ""); FN_FIT (infilename), wvc_mode ? " (+.wvc)" : "");
} }
#ifdef __BORLANDC__ #if defined(WIN32)
gettime (&time1);
#elif defined(WIN32)
_ftime (&time1); _ftime (&time1);
#else #else
gettimeofday(&time1,&timez); gettimeofday(&time1,&timez);
@ -609,7 +665,7 @@ static int unpack_file (char *infilename, char *outfilename)
if (calc_md5 && samples_unpacked) { if (calc_md5 && samples_unpacked) {
format_samples (bps, (uchar *) temp_buffer, temp_buffer, samples_unpacked * num_channels); format_samples (bps, (uchar *) temp_buffer, temp_buffer, samples_unpacked * num_channels);
MD5Update (&md5_context, temp_buffer, bps * samples_unpacked * num_channels); MD5Update (&md5_context, (unsigned char *) temp_buffer, bps * samples_unpacked * num_channels);
} }
if (!samples_unpacked) if (!samples_unpacked)
@ -641,12 +697,6 @@ static int unpack_file (char *infilename, char *outfilename)
if (output_buffer) if (output_buffer)
free (output_buffer); free (output_buffer);
if (0) {
int i;
for (i = 0; i < 8; ++i)
error_line ("delta = %d, count = %d", i, delta_blocks [i]);
}
if (!check_break () && calc_md5) { if (!check_break () && calc_md5) {
char md5_string1 [] = "00000000000000000000000000000000"; char md5_string1 [] = "00000000000000000000000000000000";
char md5_string2 [] = "00000000000000000000000000000000"; char md5_string2 [] = "00000000000000000000000000000000";
@ -700,11 +750,9 @@ for (i = 0; i < 8; ++i)
DoDeleteFile (outfilename); DoDeleteFile (outfilename);
} }
#if defined (WIN32)
if (result == NO_ERROR && copy_time && outfilename && if (result == NO_ERROR && copy_time && outfilename &&
!copy_timestamp (infilename, outfilename)) !copy_timestamp (infilename, outfilename))
error_line ("failure copying time stamp!"); error_line ("failure copying time stamp!");
#endif
if (result == NO_ERROR && WavpackGetNumSamples (wpc) != (uint32_t) -1 && if (result == NO_ERROR && WavpackGetNumSamples (wpc) != (uint32_t) -1 &&
total_unpacked_samples != WavpackGetNumSamples (wpc)) { total_unpacked_samples != WavpackGetNumSamples (wpc)) {
@ -724,14 +772,7 @@ for (i = 0; i < 8; ++i)
// Compute and display the time consumed along with some other details of // Compute and display the time consumed along with some other details of
// the unpacking operation (assuming there was no error). // the unpacking operation (assuming there was no error).
#ifdef __BORLANDC__ #if defined(WIN32)
gettime (&time2);
dtime = time2.ti_sec * 100.0 + time2.ti_hund + time2.ti_min * 6000.0 + time2.ti_hour * 360000.00;
dtime -= time1.ti_sec * 100.0 + time1.ti_hund + time1.ti_min * 6000.0 + time1.ti_hour * 360000.00;
if ((dtime /= 100.0) < 0.0)
dtime += 86400.0;
#elif defined(WIN32)
_ftime (&time2); _ftime (&time2);
dtime = time2.time + time2.millitm / 1000.0; dtime = time2.time + time2.millitm / 1000.0;
dtime -= time1.time + time1.millitm / 1000.0; dtime -= time1.time + time1.millitm / 1000.0;
@ -837,6 +878,8 @@ static uchar *format_samples (int bps, uchar *dst, int32_t *src, uint32_t samcnt
return dst; return dst;
} }
static UTF8ToAnsi (char *string, int len);
static void dump_summary (WavpackContext *wpc, char *name, FILE *dst) static void dump_summary (WavpackContext *wpc, char *name, FILE *dst)
{ {
int num_channels = WavpackGetNumChannels (wpc); int num_channels = WavpackGetNumChannels (wpc);
@ -864,7 +907,7 @@ static void dump_summary (WavpackContext *wpc, char *name, FILE *dst)
seconds -= minutes * 60.0; seconds -= minutes * 60.0;
minutes -= hours * 60.0; minutes -= hours * 60.0;
fprintf (dst, "duration: %d:%02d:%0.2f\n", hours, minutes, seconds); fprintf (dst, "duration: %d:%02d:%05.2f\n", hours, minutes, seconds);
} }
modes [0] = 0; modes [0] = 0;
@ -907,6 +950,135 @@ static void dump_summary (WavpackContext *wpc, char *name, FILE *dst)
fprintf (dst, "original md5: %s\n", md5_string); fprintf (dst, "original md5: %s\n", md5_string);
} }
if (WavpackGetMode (wpc) & MODE_VALID_TAG) {
int ape_tag = WavpackGetMode (wpc) & MODE_APETAG;
int num_items = WavpackGetNumTagItems (wpc), i;
fprintf (dst, "%s tag items: %d\n\n", ape_tag ? "APEv2" : "ID3v1", num_items);
for (i = 0; i < num_items; ++i) {
int item_len, value_len, j;
char *item, *value;
item_len = WavpackGetTagItemIndexed (wpc, i, NULL, 0);
item = malloc (item_len + 1);
WavpackGetTagItemIndexed (wpc, i, item, item_len + 1);
value_len = WavpackGetTagItem (wpc, item, NULL, 0);
value = malloc (value_len * 2 + 1);
WavpackGetTagItem (wpc, item, value, value_len + 1);
for (j = 0; j < value_len; ++j)
if (!value [j])
value [j] = '\\';
if (ape_tag)
UTF8ToAnsi (value, value_len * 2);
if (item_len + value_len + 3 >= 80)
fprintf (dst, "%s =\n%s\n", item, value);
else
fprintf (dst, "%s = %s\n", item, value);
free (value);
free (item);
}
}
}
// Convert Unicode UTF-8 string to wide format. UTF-8 string must be NULL
// terminated. Resulting wide string must be able to fit in provided space
// and will also be NULL terminated. The number of characters converted will
// be returned (not counting terminator).
static int UTF8ToWideChar (const unsigned char *pUTF8, unsigned short *pWide)
{
int trail_bytes = 0;
int chrcnt = 0;
while (*pUTF8) {
if (*pUTF8 & 0x80) {
if (*pUTF8 & 0x40) {
if (trail_bytes) {
trail_bytes = 0;
chrcnt++;
}
else {
char temp = *pUTF8;
while (temp & 0x80) {
trail_bytes++;
temp <<= 1;
}
pWide [chrcnt] = temp >> trail_bytes--;
}
}
else if (trail_bytes) {
pWide [chrcnt] = (pWide [chrcnt] << 6) | (*pUTF8 & 0x3f);
if (!--trail_bytes)
chrcnt++;
}
}
else
pWide [chrcnt++] = *pUTF8;
pUTF8++;
}
pWide [chrcnt] = 0;
return chrcnt;
}
// Convert a Unicode UTF-8 format string into its Ansi equivalent. The
// conversion is done in-place so the maximum length of the string buffer must
// be specified because the string may become longer or shorter. If the
// resulting string will not fit in the specified buffer size then it is
// truncated.
static UTF8ToAnsi (char *string, int len)
{
int max_chars = strlen (string);
#if defined (WIN32)
unsigned short *temp = malloc ((max_chars + 1) * 2);
int act_chars = UTF8ToWideChar (string, temp);
while (act_chars) {
memset (string, 0, len);
if (WideCharToMultiByte (CP_OEMCP, 0, temp, act_chars, string, len - 1, NULL, NULL))
break;
else
act_chars--;
}
if (!act_chars)
*string = 0;
#else
char *temp = malloc (len);
char *outp = temp;
char *inp = string;
size_t insize = max_chars;
size_t outsize = len - 1;
int err = 0;
char *old_locale;
memset(temp, 0, len);
old_locale = setlocale (LC_CTYPE, "");
iconv_t converter = iconv_open ("", "UTF-8");
err = iconv (converter, &inp, &insize, &outp, &outsize);
iconv_close (converter);
setlocale (LC_CTYPE, old_locale);
if (err == -1) {
free(temp);
return;
}
memmove (string, temp, len);
#endif
free (temp);
} }
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////

View File

@ -86,11 +86,7 @@ void ErrorProc(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus
FLAC__file_decoder_process_until_end_of_metadata(decoder); FLAC__file_decoder_process_until_end_of_metadata(decoder);
#ifdef __BIG_ENDIAN__ isBigEndian = hostIsBigEndian();
isBigEndian = YES;
#else
isBigEndian = NO;
#endif
return YES; return YES;
} }

View File

@ -36,11 +36,7 @@
channels = outputFormat.nChannels; channels = outputFormat.nChannels;
bitsPerSample = 16; bitsPerSample = 16;
#ifdef __BIG_ENDIAN__ isBigEndian = hostIsBigEndian();
isBigEndian = YES;
#else
isBigEndian = NO;
#endif
long duration; long duration;
DecMPA_GetDuration(decoder, &duration); DecMPA_GetDuration(decoder, &duration);

View File

@ -66,11 +66,7 @@ BOOL CanSeekProc(void *data)
} }
// DBLog(@"Ok to go..."); // DBLog(@"Ok to go...");
#ifdef __BIG_ENDIAN__ isBigEndian = hostIsBigEndian();
isBigEndian = YES;
#else
isBigEndian = NO;
#endif
return YES; return YES;
} }

View File

@ -14,6 +14,14 @@
#import "DBLog.h" #import "DBLog.h"
#ifdef __cplusplus
extern "C" {
#endif
BOOL hostIsBigEndian();
#ifdef __cplusplus
}
#endif
@interface SoundFile : NSObject { @interface SoundFile : NSObject {
UInt16 bitsPerSample; UInt16 bitsPerSample;
UInt16 channels; UInt16 channels;

View File

@ -18,6 +18,17 @@
#import "WavPackFile.h" #import "WavPackFile.h"
#import "ShnFile.h" #import "ShnFile.h"
extern "C" {
BOOL hostIsBigEndian()
{
#ifdef __BIG_ENDIAN__
return YES;
#else
return NO;
#endif
}
};
@implementation SoundFile @implementation SoundFile
/*- (void)seek:(unsigned long)position /*- (void)seek:(unsigned long)position

View File

@ -21,8 +21,10 @@
return NO; return NO;
channels = WavpackGetNumChannels(wpc); channels = WavpackGetNumChannels(wpc);
// bitsPerSample = WavpackGetBitsPerSample(wpc); bitsPerSample = WavpackGetBitsPerSample(wpc);
bitsPerSample = 32; // bitsPerSample = 32;
NSLog(@"BYTES PER SAMPLE: %i", WavpackGetBitsPerSample(wpc));
NSLog(@"BYTES PER SAMPLE: %i", WavpackGetBytesPerSample(wpc));
frequency = WavpackGetSampleRate(wpc); frequency = WavpackGetSampleRate(wpc);
@ -32,7 +34,7 @@
bitRate = (int)(WavpackGetAverageBitrate(wpc, TRUE)/1000.0); bitRate = (int)(WavpackGetAverageBitrate(wpc, TRUE)/1000.0);
//isBigEndian = YES; isBigEndian = hostIsBigEndian();
return YES; return YES;
} }
@ -48,19 +50,18 @@
{ {
int numsamples; int numsamples;
int n; int n;
void *sampleBuf = malloc(size*2);
numsamples = size/4/channels; numsamples = size/(bitsPerSample/8)/channels;
// DBLog(@"NUM SAMPLES: %i %i", numsamples, size); // DBLog(@"NUM SAMPLES: %i %i", numsamples, size);
n = WavpackUnpackSamples(wpc, buf, numsamples); n = WavpackUnpackSamples(wpc, sampleBuf, numsamples);
n *= 4*channels;
int i; int i;
for (i = 0; i < n/2; i++) for (i = 0; i < n*channels; i++)
{ {
// ((UInt32 *)buf)[i] = CFSwapInt32LittleToHost(((UInt32 *)buf)[i]); ((UInt16 *)buf)[i] = ((UInt32 *)sampleBuf)[i];
((UInt16 *)buf)[i] = CFSwapInt16LittleToHost(((UInt16 *)buf)[i]);
} }
n *= (bitsPerSample/8)*channels;
return n; return n;
} }

View File

@ -37,11 +37,7 @@
break; break;
case SF_ENDIAN_CPU: case SF_ENDIAN_CPU:
#ifdef __BIG_ENDIAN__ isBigEndian = hostIsBigEndian();
isBigEndian = YES;
#else
isBigEndian = NO;
#endif
//DBLog(@"&CPU ENDIAN"); //DBLog(@"&CPU ENDIAN");
break; break;
case SF_ENDIAN_LITTLE: case SF_ENDIAN_LITTLE: