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
------------
Volume slider now gravitates to 100%, in the middle.
Fixes endian issues for intel?
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>"; };
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>"; };
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>"; };
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>"; };

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
---------------------------

View File

@ -1,5 +1,5 @@
AUTOMAKE_OPTIONS = foreign
bin_PROGRAMS = wavpack wvunpack
bin_PROGRAMS = wavpack wvunpack wvgain
lib_LTLIBRARIES = libwavpack.la
@ -7,21 +7,26 @@ wpincludedir = $(prefix)/include/wavpack
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 \
md5.h wavpack.h wputils.h unpack3.h
libwavpack_la_CFLAGS = -DPACK -DUNPACK -DUSE_FSTREAMS -DTAGS -DSEEKING -DVER3
libwavpack_la_LDFLAGS = -lm @ICONV_LIBS@
wavpack_SOURCES = wavpack.c
wavpack_SOURCES = wavpack.c utils.c
wavpack_CFLAGS = -DPACK
wavpack_LDFLAGS = -lm -lcurses
wavpack_LDFLAGS = -lm
wavpack_LDADD = libwavpack.la
wvunpack_SOURCES = wvunpack.c
wvunpack_SOURCES = wvunpack.c utils.c
wvunpack_CFLAGS = -DUNPACK -DUSE_FSTREAMS
wvunpack_LDFLAGS = -lm -lcurses
wvunpack_LDFLAGS = -lm
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
pkgconfig_DATA = wavpack.pc

View File

@ -13,10 +13,9 @@ of the plugin sources in the Windows source release.
To build everything, type:
1. ./autogen.sh
2. ./configure
3. make
4. make install (optionally, to install into /usr/local/bin)
1. ./configure
2. make
3. make install (optionally, to install into /usr/local/bin)
Notes:
@ -31,10 +30,10 @@ Notes:
a "short" must be 16-bits
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
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
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)
AM_INIT_AUTOMAKE(wavpack, 4.2, bryant@wavpack.com)
AC_INIT(wavpack, 4.32, bryant@wavpack.com)
AM_INIT_AUTOMAKE(wavpack, 4.32, bryant@wavpack.com)
AC_CONFIG_SRCDIR([pack.c])
# Check for os version

View File

@ -17,6 +17,7 @@
#include <string.h>
#include <math.h>
#define LOG_LIMIT 6912
// #define EXTRA_DUMP
#ifdef DEBUG_ALLOC
@ -31,25 +32,21 @@ int32_t dump_alloc (void);
//////////////////////////////// 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
#ifdef MINMAX_WEIGHTS
static int32_t min_weight, max_weight;
static int min_term, max_term;
#endif
extern const signed char default_terms [], high_terms [], fast_terms [];
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;
#ifdef MINMAX_WEIGHTS
dpp->min = dpp->max = 0;
#endif
if (dir < 0) {
out_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
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) {
while (num_samples--) {
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);
update_weight (dpp->weight_A, dpp->delta, sam_A, left);
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;
in_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);
update_weight (dpp->weight_A, dpp->delta, sam_A, left);
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;
in_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) {
int32_t temp_A [MAX_TERM];
int k;
@ -155,14 +142,14 @@ static void reverse_mono_decorr (struct decorr_pass *dpp)
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;
struct decorr_pass dp, *dppi = dpp + tindex;
int delta = dppi->delta, pre_delta, term = dppi->term;
if (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;
decorr_mono_pass (samples, outsamples, num_samples > 2048 ? 2048 : num_samples, &dp, -1);
dp.delta = delta;
reverse_mono_decorr (&dp);
memcpy (dpp->samples_A, dp.samples_A, sizeof (dp.samples_A));
dpp->weight_A = dp.weight_A;
if (tindex == 0)
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) {
dp.delta = 1;
decorr_mono_pass (samples, outsamples, num_samples, &dp, 1);
dp.delta = 0;
memcpy (dp.samples_A, dpp->samples_A, sizeof (dp.samples_A));
dpp->weight_A = dp.weight_A = dp.sum_A / num_samples;
memcpy (dp.samples_A, dppi->samples_A, sizeof (dp.samples_A));
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);
decorr_mono_pass (samples, outsamples, num_samples, &dp, 1);
}
static void recurse_mono (WavpackContext *wpc, int32_t *sampleptrs[], struct decorr_pass dps[],
int depth, int nterms, int delta, uint32_t input_bits, uint32_t *best_bits)
static void recurse_mono (WavpackContext *wpc, WavpackExtraInfo *info, int depth, int delta, uint32_t input_bits)
{
WavpackStream *wps = wpc->streams [wpc->current_stream];
int term, branches = ((wpc->config.extra_flags & EXTRA_BRANCHES) >> 6) - depth;
int32_t *samples, *outsamples;
uint32_t term_bits [22], bits;
if (branches < 1 || depth + 1 == nterms)
if (branches < 1 || depth + 1 == info->nterms)
branches = 1;
CLEAR (term_bits);
samples = sampleptrs [depth];
outsamples = sampleptrs [depth + 1];
samples = info->sampleptrs [depth];
outsamples = info->sampleptrs [depth + 1];
for (term = 1; term <= 18; ++term) {
if (term == 17 && branches == 1 && depth + 1 < nterms)
if (term == 17 && branches == 1 && depth + 1 < info->nterms)
continue;
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))
continue;
dps [depth].term = term;
dps [depth].delta = delta;
decorr_mono_buffer (samples, outsamples, wps->wphdr.block_samples, &dps [depth]);
bits = log2buffer (outsamples, wps->wphdr.block_samples);
info->dps [depth].term = term;
info->dps [depth].delta = delta;
decorr_mono_buffer (samples, outsamples, wps->wphdr.block_samples, info->dps, depth);
bits = log2buffer (outsamples, wps->wphdr.block_samples, info->log_limit);
if (bits < *best_bits) {
*best_bits = bits;
if (bits < info->best_bits) {
info->best_bits = bits;
CLEAR (wps->decorr_passes);
memcpy (wps->decorr_passes, dps, sizeof (dps [0]) * (depth + 1));
memcpy (sampleptrs [nterms + 1], sampleptrs [depth + 1], wps->wphdr.block_samples * 4);
memcpy (wps->decorr_passes, info->dps, sizeof (info->dps [0]) * (depth + 1));
memcpy (info->sampleptrs [info->nterms + 1], info->sampleptrs [depth + 1], wps->wphdr.block_samples * 4);
}
term_bits [term + 3] = bits;
}
while (depth + 1 < nterms && branches--) {
while (depth + 1 < info->nterms && branches--) {
uint32_t local_best_bits = input_bits;
int best_term = 0, i;
@ -249,19 +240,18 @@ static void recurse_mono (WavpackContext *wpc, int32_t *sampleptrs[], struct dec
if (!best_term)
break;
dps [depth].term = best_term;
dps [depth].delta = delta;
decorr_mono_buffer (samples, outsamples, wps->wphdr.block_samples, &dps [depth]);
info->dps [depth].term = best_term;
info->dps [depth].delta = delta;
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!");
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[],
int nterms, uint32_t *best_bits)
static void delta_mono (WavpackContext *wpc, WavpackExtraInfo *info)
{
WavpackStream *wps = wpc->streams [wpc->current_stream];
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))
break;
for (i = 0; i < nterms && wps->decorr_passes [i].term; ++i) {
dps [i].term = wps->decorr_passes [i].term;
dps [i].delta = d;
decorr_mono_buffer (sampleptrs [i], sampleptrs [i+1], wps->wphdr.block_samples, &dps [i]);
for (i = 0; i < info->nterms && wps->decorr_passes [i].term; ++i) {
info->dps [i].term = wps->decorr_passes [i].term;
info->dps [i].delta = d;
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;
*best_bits = bits;
info->best_bits = bits;
CLEAR (wps->decorr_passes);
memcpy (wps->decorr_passes, dps, sizeof (dps [0]) * i);
memcpy (sampleptrs [nterms + 1], sampleptrs [i], wps->wphdr.block_samples * 4);
memcpy (wps->decorr_passes, info->dps, sizeof (info->dps [0]) * i);
memcpy (info->sampleptrs [info->nterms + 1], info->sampleptrs [i], wps->wphdr.block_samples * 4);
}
else
break;
@ -300,27 +290,26 @@ static void delta_mono (WavpackContext *wpc, int32_t *sampleptrs[], struct decor
for (d = delta + 1; !lower && d <= 7; ++d) {
int i;
for (i = 0; i < nterms && wps->decorr_passes [i].term; ++i) {
dps [i].term = wps->decorr_passes [i].term;
dps [i].delta = d;
decorr_mono_buffer (sampleptrs [i], sampleptrs [i+1], wps->wphdr.block_samples, &dps [i]);
for (i = 0; i < info->nterms && wps->decorr_passes [i].term; ++i) {
info->dps [i].term = wps->decorr_passes [i].term;
info->dps [i].delta = d;
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) {
*best_bits = bits;
if (bits < info->best_bits) {
info->best_bits = bits;
CLEAR (wps->decorr_passes);
memcpy (wps->decorr_passes, dps, sizeof (dps [0]) * i);
memcpy (sampleptrs [nterms + 1], sampleptrs [i], wps->wphdr.block_samples * 4);
memcpy (wps->decorr_passes, info->dps, sizeof (info->dps [0]) * i);
memcpy (info->sampleptrs [info->nterms + 1], info->sampleptrs [i], wps->wphdr.block_samples * 4);
}
else
break;
}
}
static void sort_mono (WavpackContext *wpc, int32_t *sampleptrs[], struct decorr_pass dps[],
int nterms, uint32_t *best_bits)
static void sort_mono (WavpackContext *wpc, WavpackExtraInfo *info)
{
WavpackStream *wps = wpc->streams [wpc->current_stream];
int reversed = TRUE;
@ -329,38 +318,38 @@ static void sort_mono (WavpackContext *wpc, int32_t *sampleptrs[], struct decorr
while (reversed) {
int ri, i;
memcpy (dps, wps->decorr_passes, sizeof (wps->decorr_passes));
memcpy (info->dps, wps->decorr_passes, sizeof (wps->decorr_passes));
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;
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;
}
dps [ri] = wps->decorr_passes [ri+1];
dps [ri+1] = wps->decorr_passes [ri];
info->dps [ri] = wps->decorr_passes [ri+1];
info->dps [ri+1] = wps->decorr_passes [ri];
for (i = ri; i < nterms && wps->decorr_passes [i].term; ++i)
decorr_mono_buffer (sampleptrs [i], sampleptrs [i+1], wps->wphdr.block_samples, &dps [i]);
for (i = ri; i < info->nterms && wps->decorr_passes [i].term; ++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;
*best_bits = bits;
info->best_bits = bits;
CLEAR (wps->decorr_passes);
memcpy (wps->decorr_passes, dps, sizeof (dps [0]) * i);
memcpy (sampleptrs [nterms + 1], sampleptrs [i], wps->wphdr.block_samples * 4);
memcpy (wps->decorr_passes, info->dps, sizeof (info->dps [0]) * i);
memcpy (info->sampleptrs [info->nterms + 1], info->sampleptrs [i], wps->wphdr.block_samples * 4);
}
else {
dps [ri] = wps->decorr_passes [ri];
dps [ri+1] = wps->decorr_passes [ri+1];
decorr_mono_buffer (sampleptrs [ri], sampleptrs [ri+1], wps->wphdr.block_samples, &dps [ri]);
info->dps [ri] = wps->decorr_passes [ri];
info->dps [ri+1] = wps->decorr_passes [ri+1];
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)
//extern uint32_t crc3;
void analyze_mono (WavpackContext *wpc, int32_t *samples)
{
WavpackStream *wps = wpc->streams [wpc->current_stream];
#ifdef EXTRA_DUMP
uint32_t bits, best_bits, default_bits, cnt;
uint32_t bits, default_bits, cnt;
#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
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);
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)
decorr_terms = fast_terms;
for (nterms = 0, tp = decorr_terms; *tp; tp++)
for (info.nterms = 0, tp = decorr_terms; *tp; tp++)
if (*tp > 0)
++nterms;
++info.nterms;
if (wpc->config.extra_flags & EXTRA_TERMS)
if ((nterms += (wpc->config.extra_flags & EXTRA_TERMS) >> 10) > MAX_NTERMS)
nterms = MAX_NTERMS;
if ((info.nterms += (wpc->config.extra_flags & EXTRA_TERMS) >> 10) > MAX_NTERMS)
info.nterms = MAX_NTERMS;
for (i = 0; i < nterms + 2; ++i)
sampleptrs [i] = malloc (wps->wphdr.block_samples * 4);
for (i = 0; i < info.nterms + 2; ++i)
info.sampleptrs [i] = malloc (wps->wphdr.block_samples * 4);
memcpy (sampleptrs [nterms + 1], samples, wps->wphdr.block_samples * 4);
best_bits = log2buffer (sampleptrs [nterms + 1], wps->wphdr.block_samples);
memcpy (sampleptrs [0], samples, wps->wphdr.block_samples * 4);
CLEAR (dps);
memcpy (info.sampleptrs [info.nterms + 1], samples, wps->wphdr.block_samples * 4);
info.best_bits = log2buffer (info.sampleptrs [info.nterms + 1], wps->wphdr.block_samples, 0);
memcpy (info.sampleptrs [0], samples, wps->wphdr.block_samples * 4);
CLEAR (info.dps);
for (tp = decorr_terms, i = 0; *tp; tp++)
if (*tp > 0) {
dps [i].term = *tp;
dps [i].delta = 2;
decorr_mono_buffer (sampleptrs [i], sampleptrs [i+1], wps->wphdr.block_samples, &dps [i]);
info.dps [i].term = *tp;
info.dps [i].delta = 2;
decorr_mono_buffer (info.sampleptrs [i], info.sampleptrs [i+1], wps->wphdr.block_samples, info.dps, i);
++i;
}
#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
bits = log2buffer (sampleptrs [i], wps->wphdr.block_samples);
bits = log2buffer (info.sampleptrs [i], wps->wphdr.block_samples, 0);
#endif
if (bits < best_bits) {
best_bits = bits;
if (bits < info.best_bits) {
info.best_bits = bits;
CLEAR (wps->decorr_passes);
memcpy (wps->decorr_passes, dps, sizeof (dps [0]) * i);
memcpy (sampleptrs [nterms + 1], sampleptrs [i], wps->wphdr.block_samples * 4);
memcpy (wps->decorr_passes, info.dps, sizeof (info.dps [0]) * i);
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)) {
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);
cnt = wps->wphdr.block_samples;
lptr = sampleptrs [0];
lptr = info.sampleptrs [0];
if (wps->wphdr.flags & HYBRID_SHAPE) {
while (cnt--) {
@ -472,31 +472,31 @@ void analyze_mono (WavpackContext *wpc, int32_t *samples)
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)
decorr_mono_buffer (sampleptrs [i], sampleptrs [i + 1], wps->wphdr.block_samples, dps + i);
for (i = 0; i < info.nterms && info.dps [i].term; ++i)
decorr_mono_buffer (info.sampleptrs [i], info.sampleptrs [i + 1], wps->wphdr.block_samples, info.dps, i);
#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
best_bits = log2buffer (sampleptrs [i], wps->wphdr.block_samples);
info.best_bits = log2buffer (info.sampleptrs [i], wps->wphdr.block_samples, 0);
#endif
CLEAR (wps->decorr_passes);
memcpy (wps->decorr_passes, dps, sizeof (dps [0]) * i);
memcpy (sampleptrs [nterms + 1], sampleptrs [i], wps->wphdr.block_samples * 4);
memcpy (wps->decorr_passes, info.dps, sizeof (info.dps [0]) * i);
memcpy (info.sampleptrs [info.nterms + 1], info.sampleptrs [i], wps->wphdr.block_samples * 4);
}
if (wpc->config.extra_flags & EXTRA_BRANCHES)
recurse_mono (wpc, sampleptrs, dps, 0, nterms, (int) floor (wps->delta_decay + 0.5),
log2buffer (sampleptrs [0], wps->wphdr.block_samples), &best_bits);
recurse_mono (wpc, &info, 0, (int) floor (wps->delta_decay + 0.5),
log2buffer (info.sampleptrs [0], wps->wphdr.block_samples, 0));
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) {
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)
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)
sort_mono (wpc, sampleptrs, dps, nterms, &best_bits);
sort_mono (wpc, &info);
#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)
decorr_mono_pass (sampleptrs [i], sampleptrs [i + 1], wps->wphdr.block_samples, dps + i, 1);
for (i = 0; i < info.nterms && info.dps [i].term; ++i)
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!");
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!");
#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
if (wpc->config.extra_flags & EXTRA_DUMP_TERMS) {
if (1) {
char string [256], substring [20];
int i;
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 (i && wps->decorr_passes [i-1].delta == wps->decorr_passes [i].delta)
sprintf (substring, " %d", wps->decorr_passes [i].term);
@ -548,16 +548,12 @@ void analyze_mono (WavpackContext *wpc, int32_t *samples)
}
#endif
for (i = 0; i < nterms; ++i)
for (i = 0; i < info.nterms; ++i)
if (!wps->decorr_passes [i].term)
break;
wps->num_terms = i;
for (i = 0; i < nterms + 2; ++i)
free (sampleptrs [i]);
#ifdef MINMAX_WEIGHTS
error_line ("weight range = %ld (%d) to %ld (%d)", min_weight, min_term, max_weight, max_term);
#endif
for (i = 0; i < info.nterms + 2; ++i)
free (info.sampleptrs [i]);
}

View File

@ -17,7 +17,8 @@
#include <string.h>
#include <math.h>
// #define EXTRA_DUMP
#define LOG_LIMIT 6912
//#define EXTRA_DUMP
#ifdef DEBUG_ALLOC
#define malloc malloc_db
@ -29,25 +30,23 @@ void free_db (void *ptr);
int32_t dump_alloc (void);
#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
static int32_t min_weight, max_weight;
static int min_term, max_term;
#endif
extern const signed char default_terms [], high_terms [], fast_terms [];
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;
#ifdef MINMAX_WEIGHTS
dpp->min = dpp->max = 0;
#endif
if (dir < 0) {
out_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
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) {
while (num_samples--) {
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);
dpp->sum_B += dpp->weight_B;
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;
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);
dpp->sum_B += dpp->weight_B;
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;
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);
dpp->sum_B += dpp->weight_B;
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;
out_samples += dir;
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);
dpp->sum_A += dpp->weight_A;
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 [1] = right;
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);
dpp->sum_A += dpp->weight_A;
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 [1] = right;
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);
dpp->sum_A += dpp->weight_A;
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 [1] = right;
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) {
int32_t temp_A [MAX_TERM], temp_B [MAX_TERM];
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 [i++] ^= dpp->samples_B [j--];
}
// CLEAR (dpp->samples_A);
// CLEAR (dpp->samples_B);
}
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;
int term = dpp->term;
struct decorr_pass dp;
struct decorr_pass dp, *dppi = dpp + tindex;
int delta = dppi->delta, pre_delta;
int term = dppi->term;
if (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;
decorr_stereo_pass (samples, outsamples, num_samples > 2048 ? 2048 : num_samples, &dp, -1);
dp.delta = delta;
reverse_decorr (&dp);
memcpy (dpp->samples_A, dp.samples_A, sizeof (dp.samples_A));
memcpy (dpp->samples_B, dp.samples_B, sizeof (dp.samples_B));
dpp->weight_A = dp.weight_A;
dpp->weight_B = dp.weight_B;
if (tindex == 0)
reverse_decorr (&dp);
else {
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) {
dp.delta = 1;
decorr_stereo_pass (samples, outsamples, num_samples, &dp, 1);
dp.delta = 0;
memcpy (dp.samples_A, dpp->samples_A, sizeof (dp.samples_A));
memcpy (dp.samples_B, dpp->samples_B, sizeof (dp.samples_B));
dpp->weight_A = dp.weight_A = dp.sum_A / num_samples;
dpp->weight_B = dp.weight_B = dp.sum_B / num_samples;
memcpy (dp.samples_A, dppi->samples_A, sizeof (dp.samples_A));
memcpy (dp.samples_B, dppi->samples_B, sizeof (dp.samples_B));
dppi->weight_A = dp.weight_A = dp.sum_A / 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);
decorr_stereo_pass (samples, outsamples, num_samples, &dp, 1);
}
static void recurse_stereo (WavpackContext *wpc, int32_t *sampleptrs[], struct decorr_pass dps[],
int depth, int nterms, int delta, uint32_t input_bits, uint32_t *best_bits)
static void recurse_stereo (WavpackContext *wpc, WavpackExtraInfo *info, int depth, int delta, uint32_t input_bits)
{
WavpackStream *wps = wpc->streams [wpc->current_stream];
int term, branches = ((wpc->config.extra_flags & EXTRA_BRANCHES) >> 6) - depth;
int32_t *samples, *outsamples;
uint32_t term_bits [22], bits;
if (branches < 1 || depth + 1 == nterms)
if (branches < 1 || depth + 1 == info->nterms)
branches = 1;
CLEAR (term_bits);
samples = sampleptrs [depth];
outsamples = sampleptrs [depth + 1];
samples = info->sampleptrs [depth];
outsamples = info->sampleptrs [depth + 1];
for (term = -3; term <= 18; ++term) {
if (!term)
continue;
if (term == 17 && branches == 1 && depth + 1 < nterms)
if (term == 17 && branches == 1 && depth + 1 < info->nterms)
continue;
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))
continue;
dps [depth].term = term;
dps [depth].delta = delta;
decorr_stereo_buffer (samples, outsamples, wps->wphdr.block_samples, &dps [depth]);
bits = log2buffer (outsamples, wps->wphdr.block_samples * 2);
info->dps [depth].term = term;
info->dps [depth].delta = delta;
decorr_stereo_buffer (samples, outsamples, wps->wphdr.block_samples, info->dps, depth);
bits = log2buffer (outsamples, wps->wphdr.block_samples * 2, info->log_limit);
if (bits < *best_bits) {
*best_bits = bits;
if (bits < info->best_bits) {
info->best_bits = bits;
CLEAR (wps->decorr_passes);
memcpy (wps->decorr_passes, dps, sizeof (dps [0]) * (depth + 1));
memcpy (sampleptrs [nterms + 1], sampleptrs [depth + 1], wps->wphdr.block_samples * 8);
memcpy (wps->decorr_passes, info->dps, sizeof (info->dps [0]) * (depth + 1));
memcpy (info->sampleptrs [info->nterms + 1], info->sampleptrs [depth + 1], wps->wphdr.block_samples * 8);
}
term_bits [term + 3] = bits;
}
while (depth + 1 < nterms && branches--) {
while (depth + 1 < info->nterms && branches--) {
uint32_t local_best_bits = input_bits;
int best_term = 0, i;
@ -406,19 +370,18 @@ static void recurse_stereo (WavpackContext *wpc, int32_t *sampleptrs[], struct d
if (!best_term)
break;
dps [depth].term = best_term;
dps [depth].delta = delta;
decorr_stereo_buffer (samples, outsamples, wps->wphdr.block_samples, &dps [depth]);
info->dps [depth].term = best_term;
info->dps [depth].delta = delta;
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!");
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[],
int nterms, uint32_t *best_bits)
static void delta_stereo (WavpackContext *wpc, WavpackExtraInfo *info)
{
WavpackStream *wps = wpc->streams [wpc->current_stream];
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))
break;
for (i = 0; i < nterms && wps->decorr_passes [i].term; ++i) {
dps [i].term = wps->decorr_passes [i].term;
dps [i].delta = d;
decorr_stereo_buffer (sampleptrs [i], sampleptrs [i+1], wps->wphdr.block_samples, &dps [i]);
for (i = 0; i < info->nterms && wps->decorr_passes [i].term; ++i) {
info->dps [i].term = wps->decorr_passes [i].term;
info->dps [i].delta = d;
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;
*best_bits = bits;
info->best_bits = bits;
CLEAR (wps->decorr_passes);
memcpy (wps->decorr_passes, dps, sizeof (dps [0]) * i);
memcpy (sampleptrs [nterms + 1], sampleptrs [i], wps->wphdr.block_samples * 8);
memcpy (wps->decorr_passes, info->dps, sizeof (info->dps [0]) * i);
memcpy (info->sampleptrs [info->nterms + 1], info->sampleptrs [i], wps->wphdr.block_samples * 8);
}
else
break;
@ -458,27 +421,26 @@ static void delta_stereo (WavpackContext *wpc, int32_t *sampleptrs[], struct dec
for (d = delta + 1; !lower && d <= 7; ++d) {
int i;
for (i = 0; i < nterms && wps->decorr_passes [i].term; ++i) {
dps [i].term = wps->decorr_passes [i].term;
dps [i].delta = d;
decorr_stereo_buffer (sampleptrs [i], sampleptrs [i+1], wps->wphdr.block_samples, &dps [i]);
for (i = 0; i < info->nterms && wps->decorr_passes [i].term; ++i) {
info->dps [i].term = wps->decorr_passes [i].term;
info->dps [i].delta = d;
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) {
*best_bits = bits;
if (bits < info->best_bits) {
info->best_bits = bits;
CLEAR (wps->decorr_passes);
memcpy (wps->decorr_passes, dps, sizeof (dps [0]) * i);
memcpy (sampleptrs [nterms + 1], sampleptrs [i], wps->wphdr.block_samples * 8);
memcpy (wps->decorr_passes, info->dps, sizeof (info->dps [0]) * i);
memcpy (info->sampleptrs [info->nterms + 1], info->sampleptrs [i], wps->wphdr.block_samples * 8);
}
else
break;
}
}
static void sort_stereo (WavpackContext *wpc, int32_t *sampleptrs[], struct decorr_pass dps[],
int nterms, uint32_t *best_bits)
static void sort_stereo (WavpackContext *wpc, WavpackExtraInfo *info)
{
WavpackStream *wps = wpc->streams [wpc->current_stream];
int reversed = TRUE;
@ -487,38 +449,38 @@ static void sort_stereo (WavpackContext *wpc, int32_t *sampleptrs[], struct deco
while (reversed) {
int ri, i;
memcpy (dps, wps->decorr_passes, sizeof (wps->decorr_passes));
memcpy (info->dps, wps->decorr_passes, sizeof (wps->decorr_passes));
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;
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;
}
dps [ri] = wps->decorr_passes [ri+1];
dps [ri+1] = wps->decorr_passes [ri];
info->dps [ri] = wps->decorr_passes [ri+1];
info->dps [ri+1] = wps->decorr_passes [ri];
for (i = ri; i < nterms && wps->decorr_passes [i].term; ++i)
decorr_stereo_buffer (sampleptrs [i], sampleptrs [i+1], wps->wphdr.block_samples, &dps [i]);
for (i = ri; i < info->nterms && wps->decorr_passes [i].term; ++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;
*best_bits = bits;
info->best_bits = bits;
CLEAR (wps->decorr_passes);
memcpy (wps->decorr_passes, dps, sizeof (dps [0]) * i);
memcpy (sampleptrs [nterms + 1], sampleptrs [i], wps->wphdr.block_samples * 8);
memcpy (wps->decorr_passes, info->dps, sizeof (info->dps [0]) * i);
memcpy (info->sampleptrs [info->nterms + 1], info->sampleptrs [i], wps->wphdr.block_samples * 8);
}
else {
dps [ri] = wps->decorr_passes [ri];
dps [ri+1] = wps->decorr_passes [ri+1];
decorr_stereo_buffer (sampleptrs [ri], sampleptrs [ri+1], wps->wphdr.block_samples, &dps [ri]);
info->dps [ri] = wps->decorr_passes [ri];
info->dps [ri+1] = wps->decorr_passes [ri+1];
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];
#ifdef EXTRA_DUMP
uint32_t bits, best_bits, default_bits, cnt;
uint32_t bits, default_bits, cnt;
#else
uint32_t bits, best_bits, cnt;
uint32_t bits, cnt;
#endif
const char *decorr_terms = default_terms, *tp;
int32_t *sampleptrs [MAX_NTERMS+2], *lptr;
struct decorr_pass dps [MAX_NTERMS];
int nterms, i;
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
CLEAR (wps->decorr_passes);
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)
decorr_terms = fast_terms;
nterms = strlen (decorr_terms);
info.nterms = strlen (decorr_terms);
if (wpc->config.extra_flags & EXTRA_TERMS)
if ((nterms += (wpc->config.extra_flags & EXTRA_TERMS) >> 10) > MAX_NTERMS)
nterms = MAX_NTERMS;
if ((info.nterms += (wpc->config.extra_flags & EXTRA_TERMS) >> 10) > MAX_NTERMS)
info.nterms = MAX_NTERMS;
for (i = 0; i < nterms + 2; ++i)
sampleptrs [i] = malloc (wps->wphdr.block_samples * 8);
for (i = 0; i < info.nterms + 2; ++i)
info.sampleptrs [i] = malloc (wps->wphdr.block_samples * 8);
memcpy (sampleptrs [nterms + 1], samples, wps->wphdr.block_samples * 8);
best_bits = log2buffer (sampleptrs [nterms + 1], wps->wphdr.block_samples * 2);
memcpy (info.sampleptrs [info.nterms + 1], samples, wps->wphdr.block_samples * 8);
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)) {
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;) {
if (*tp > 0 || (wps->wphdr.flags & CROSS_DECORR))
dps [i].term = *tp++;
info.dps [i].term = *tp++;
else {
dps [i].term = -3;
info.dps [i].term = -3;
tp++;
}
dps [i].delta = 2;
decorr_stereo_buffer (sampleptrs [i], sampleptrs [i+1], wps->wphdr.block_samples, &dps [i]);
info.dps [i].delta = 2;
decorr_stereo_buffer (info.sampleptrs [i], info.sampleptrs [i+1], wps->wphdr.block_samples, info.dps, i);
++i;
}
#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
bits = log2buffer (sampleptrs [i], wps->wphdr.block_samples * 2);
bits = log2buffer (info.sampleptrs [i], wps->wphdr.block_samples * 2, 0);
#endif
wps->wphdr.flags &= ~JOINT_STEREO;
if (bits < best_bits) {
best_bits = bits;
if (bits < info.best_bits) {
info.best_bits = bits;
CLEAR (wps->decorr_passes);
memcpy (wps->decorr_passes, dps, sizeof (dps [0]) * i);
memcpy (sampleptrs [nterms + 1], sampleptrs [i], wps->wphdr.block_samples * 8);
memcpy (wps->decorr_passes, info.dps, sizeof (info.dps [0]) * i);
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)) {
memcpy (sampleptrs [0], samples, wps->wphdr.block_samples * 8);
memcpy (info.sampleptrs [0], samples, wps->wphdr.block_samples * 8);
cnt = wps->wphdr.block_samples;
lptr = sampleptrs [0];
lptr = info.sampleptrs [0];
while (cnt--) {
lptr [1] += ((lptr [0] -= lptr [1]) >> 1);
lptr += 2;
}
CLEAR (dps);
CLEAR (info.dps);
for (tp = decorr_terms, i = 0; *tp;) {
if (*tp > 0 || (wps->wphdr.flags & CROSS_DECORR))
dps [i].term = *tp++;
info.dps [i].term = *tp++;
else {
dps [i].term = -3;
info.dps [i].term = -3;
tp++;
}
dps [i].delta = 2;
decorr_stereo_buffer (sampleptrs [i], sampleptrs [i+1], wps->wphdr.block_samples, &dps [i]);
info.dps [i].delta = 2;
decorr_stereo_buffer (info.sampleptrs [i], info.sampleptrs [i+1], wps->wphdr.block_samples, info.dps, i);
++i;
}
#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
bits = log2buffer (sampleptrs [i], wps->wphdr.block_samples * 2);
bits = log2buffer (info.sampleptrs [i], wps->wphdr.block_samples * 2, 0);
#endif
wps->wphdr.flags |= JOINT_STEREO;
if (bits < best_bits) {
best_bits = bits;
if (bits < info.best_bits) {
info.best_bits = bits;
CLEAR (wps->decorr_passes);
memcpy (wps->decorr_passes, dps, sizeof (dps [0]) * i);
memcpy (sampleptrs [nterms + 1], sampleptrs [i], wps->wphdr.block_samples * 8);
memcpy (wps->decorr_passes, info.dps, sizeof (info.dps [0]) * i);
memcpy (info.sampleptrs [info.nterms + 1], info.sampleptrs [i], wps->wphdr.block_samples * 8);
}
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;
}
}
if ((wps->wphdr.flags & HYBRID_FLAG) && (wpc->config.extra_flags & EXTRA_ADVANCED)) {
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);
cnt = wps->wphdr.block_samples;
lptr = sampleptrs [0];
lptr = info.sampleptrs [0];
CLEAR (error);
if (wps->wphdr.flags & HYBRID_SHAPE) {
@ -700,31 +670,31 @@ void analyze_stereo (WavpackContext *wpc, int32_t *samples)
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)
decorr_stereo_buffer (sampleptrs [i], sampleptrs [i + 1], wps->wphdr.block_samples, dps + i);
for (i = 0; i < info.nterms && info.dps [i].term; ++i)
decorr_stereo_buffer (info.sampleptrs [i], info.sampleptrs [i + 1], wps->wphdr.block_samples, info.dps, i);
#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
best_bits = log2buffer (sampleptrs [i], wps->wphdr.block_samples * 2);
info.best_bits = log2buffer (info.sampleptrs [i], wps->wphdr.block_samples * 2, 0);
#endif
CLEAR (wps->decorr_passes);
memcpy (wps->decorr_passes, dps, sizeof (dps [0]) * i);
memcpy (sampleptrs [nterms + 1], sampleptrs [i], wps->wphdr.block_samples * 8);
memcpy (wps->decorr_passes, info.dps, sizeof (info.dps [0]) * i);
memcpy (info.sampleptrs [info.nterms + 1], info.sampleptrs [i], wps->wphdr.block_samples * 8);
}
if (wpc->config.extra_flags & EXTRA_BRANCHES)
recurse_stereo (wpc, sampleptrs, dps, 0, nterms, (int) floor (wps->delta_decay + 0.5),
log2buffer (sampleptrs [0], wps->wphdr.block_samples * 2), &best_bits);
recurse_stereo (wpc, &info, 0, (int) floor (wps->delta_decay + 0.5),
log2buffer (info.sampleptrs [0], wps->wphdr.block_samples * 2, 0));
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) {
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)
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)
sort_stereo (wpc, sampleptrs, dps, nterms, &best_bits);
sort_stereo (wpc, &info);
#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)
decorr_stereo_pass (sampleptrs [i], sampleptrs [i + 1], wps->wphdr.block_samples, dps + i, 1);
for (i = 0; i < info.nterms && info.dps [i].term; ++i)
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!");
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!");
#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
if (1) {
@ -757,9 +727,9 @@ void analyze_stereo (WavpackContext *wpc, int32_t *samples)
sprintf (string, "%s: delta = %.4f%%, terms =",
(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 (i && wps->decorr_passes [i-1].delta == wps->decorr_passes [i].delta)
sprintf (substring, " %d", wps->decorr_passes [i].term);
@ -777,16 +747,12 @@ void analyze_stereo (WavpackContext *wpc, int32_t *samples)
}
#endif
for (i = 0; i < nterms; ++i)
for (i = 0; i < info.nterms; ++i)
if (!wps->decorr_passes [i].term)
break;
wps->num_terms = i;
for (i = 0; i < nterms + 2; ++i)
free (sampleptrs [i]);
#ifdef MINMAX_WEIGHTS
error_line ("weight range = %ld (%d) to %ld (%d)", min_weight, min_term, max_weight, max_term);
#endif
for (i = 0; i < info.nterms + 2; ++i)
free (info.sampleptrs [i]);
}

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)
{
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++;
}
}
#endif

View File

@ -13,10 +13,10 @@ struct MD5Context {
unsigned char in[64];
};
extern void MD5Init();
extern void MD5Update();
extern void MD5Final();
extern void MD5Transform();
extern void MD5Init (struct MD5Context *ctx);
extern void MD5Update (struct MD5Context *ctx, unsigned char *buf, unsigned len);
extern void MD5Final (unsigned char digest[16], struct MD5Context *ctx);
extern void MD5Transform (uint32 buf[4], uint32 in[16]);
/*
* 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:
return read_config_info (wpc, wpmd);
case ID_SAMPLE_RATE:
return read_sample_rate (wpc, wpmd);
case ID_WV_BITSTREAM:
return init_wv_bitstream (wps, wpmd);
@ -268,7 +271,7 @@ int write_metadata_block (WavpackContext *wpc)
CLEAR (*wphdr);
memcpy (wphdr->ckID, "wvpk", 4);
wphdr->total_samples = wpc->total_samples;
wphdr->version = 0x403;
wphdr->version = wpc->stream_version;
wphdr->ckSize = block_size - 8;
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
// values indicate cross channel decorrelation (in stereo only).
const 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 char fast_terms [] = { 17,17,0 };
const signed char default_terms [] = { 18,18,2,3,-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 signed char fast_terms [] = { 17,17,0 };
///////////////////////////// executable code ////////////////////////////////
@ -55,9 +55,6 @@ void pack_init (WavpackContext *wpc)
{
WavpackStream *wps = wpc->streams [wpc->current_stream];
uint32_t flags = wps->wphdr.flags;
struct decorr_pass *dpp;
const char *term_string;
int ti;
wps->sample_index = 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;
}
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);
}
@ -123,18 +102,29 @@ void write_decorr_terms (WavpackStream *wps, WavpackMetadata *wpmd)
void write_decorr_weights (WavpackStream *wps, WavpackMetadata *wpmd)
{
int tcount = wps->num_terms;
struct decorr_pass *dpp;
struct decorr_pass *dpp = wps->decorr_passes;
int tcount = wps->num_terms, i;
char *byteptr;
byteptr = wpmd->data = malloc ((tcount * 2) + 1);
wpmd->id = ID_DECORR_WEIGHTS;
for (dpp = wps->decorr_passes; tcount--; ++dpp) {
dpp->weight_A = restore_weight (*byteptr++ = store_weight (dpp->weight_A));
for (i = wps->num_terms - 1; i >= 0; --i)
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))
dpp->weight_B = restore_weight (*byteptr++ = store_weight (dpp->weight_B));
tcount = i + 1;
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;
@ -170,7 +160,7 @@ void write_decorr_samples (WavpackStream *wps, WavpackMetadata *wpmd)
*byteptr++ = temp;
*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]));
*byteptr++ = temp;
*byteptr++ = temp >> 8;
@ -195,7 +185,7 @@ void write_decorr_samples (WavpackStream *wps, WavpackMetadata *wpmd)
*byteptr++ = temp;
*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]));
*byteptr++ = temp;
*byteptr++ = temp >> 8;
@ -226,13 +216,6 @@ void write_shaping_info (WavpackStream *wps, WavpackMetadata *wpmd)
char *byteptr;
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);
wpmd->id = ID_SHAPING_WEIGHTS;
@ -243,7 +226,7 @@ void write_shaping_info (WavpackStream *wps, WavpackMetadata *wpmd)
*byteptr++ = temp;
*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]));
*byteptr++ = temp;
*byteptr++ = temp >> 8;
@ -257,7 +240,7 @@ void write_shaping_info (WavpackStream *wps, WavpackMetadata *wpmd)
*byteptr++ = temp;
*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]));
*byteptr++ = temp;
*byteptr++ = temp >> 8;
@ -325,6 +308,24 @@ void write_config_info (WavpackContext *wpc, WavpackMetadata *wpmd)
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
// WavPack block. This function is actually a shell for pack_samples() and
// 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.
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 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;
int32_t *ptr = buffer;
if (flags & MONO_FLAG)
if (flags & MONO_DATA)
while (cnt--)
*ptr++ >>= shift;
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 & HYBRID_FLAG) || wpc->wvc_flag) && !(wpc->config.flags & CONFIG_SKIP_WVX)) {
orig_data = malloc (sizeof (f32) * ((flags & MONO_FLAG) ? sample_count : sample_count * 2));
memcpy (orig_data, buffer, 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_DATA) ? sample_count : sample_count * 2));
if (flags & FLOAT_DATA) {
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);
orig_data = NULL;
}
}
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);
orig_data = NULL;
}
@ -392,20 +394,28 @@ int pack_block (WavpackContext *wpc, int32_t *buffer)
if (flags & FLOAT_DATA) {
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;
}
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->config.extra_flags |= EXTRA_SCAN_ONLY;
}
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 (flags & MONO_FLAG)
if (flags & MONO_DATA)
analyze_mono (wpc, buffer);
else
analyze_stereo (wpc, buffer);
@ -413,7 +423,7 @@ int pack_block (WavpackContext *wpc, int32_t *buffer)
else if (!wps->sample_index || !wps->num_terms) {
wpc->config.extra_flags = EXTRA_SCAN_ONLY;
if (flags & MONO_FLAG)
if (flags & MONO_DATA)
analyze_mono (wpc, buffer);
else
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);
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
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);
free (orig_data);
@ -475,6 +485,70 @@ int pack_block (WavpackContext *wpc, int32_t *buffer)
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
// 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
@ -548,12 +622,6 @@ static int scan_int32_data (WavpackStream *wps, int32_t *values, int32_t num_val
*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;
}
@ -641,6 +709,12 @@ static int pack_samples (WavpackContext *wpc, int32_t *buffer)
copy_metadata (&wpmd, wps->blockbuff, wps->blockend);
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) {
write_hybrid_profile (wps, &wpmd);
copy_metadata (&wpmd, wps->blockbuff, wps->blockend);
@ -690,7 +764,7 @@ static int pack_samples (WavpackContext *wpc, int32_t *buffer)
/////////////////////// 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) {
int32_t code;
@ -724,8 +798,8 @@ static int pack_samples (WavpackContext *wpc, int32_t *buffer)
//////////////////// handle the lossless stereo mode //////////////////////
#ifdef FAST_ENCODE
else if (!(flags & HYBRID_FLAG) && !(flags & MONO_FLAG)) {
int32_t *eptr = buffer + (sample_count * 2), sam_A, sam_B;
else if (!(flags & HYBRID_FLAG) && !(flags & MONO_DATA)) {
int32_t *eptr = buffer + (sample_count * 2);
if (flags & JOINT_STEREO)
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);
}
#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) {
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 /////////////////////
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) {
int32_t code, temp;
@ -881,7 +955,7 @@ static int pack_samples (WavpackContext *wpc, int32_t *buffer)
/////////////////// 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) {
int32_t left, right, temp;
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]));
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);
right = send_word (wps, right, 1);

View File

@ -70,18 +70,14 @@ int unpack_init (WavpackContext *wpc)
blockptr = wps->blockbuff + sizeof (WavpackHeader);
while (read_metadata_buff (&wpmd, wps->blockbuff, &blockptr))
if (!process_metadata (wpc, &wpmd)) {
sprintf (wpc->error_message, "invalid metadata %2x!", wpmd.id);
if (!process_metadata (wpc, &wpmd))
return FALSE;
}
block2ptr = wps->block2buff + sizeof (WavpackHeader);
while (wpc->wvc_flag && wps->wphdr.block_samples && read_metadata_buff (&wpmd, wps->block2buff, &block2ptr))
if (!process_metadata (wpc, &wpmd)) {
sprintf (wpc->error_message, "invalid metadata %2x in wvc file!", wpmd.id);
if (!process_metadata (wpc, &wpmd))
return FALSE;
}
if (wps->wphdr.block_samples && !bs_is_open (&wps->wvbits)) {
if (bs_is_open (&wps->wvcbits))
@ -181,7 +177,7 @@ int read_decorr_weights (WavpackStream *wps, WavpackMetadata *wpmd)
char *byteptr = wpmd->data;
struct decorr_pass *dpp;
if (!(wps->wphdr.flags & MONO_FLAG))
if (!(wps->wphdr.flags & MONO_DATA))
termcnt /= 2;
if (termcnt > wps->num_terms)
@ -193,7 +189,7 @@ int read_decorr_weights (WavpackStream *wps, WavpackMetadata *wpmd)
while (--dpp >= wps->decorr_passes && termcnt--) {
dpp->weight_A = restore_weight (*byteptr++);
if (!(wps->wphdr.flags & MONO_FLAG))
if (!(wps->wphdr.flags & MONO_DATA))
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)));
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)));
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)));
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 [1] = exp2s ((short)(byteptr [2] + (byteptr [3] << 8)));
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)));
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)));
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;
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;
wps->dc.error [0] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8)));
wps->dc.shaping_acc [0] = exp2s ((short)(byteptr [2] + (byteptr [3] << 8)));
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.shaping_acc [1] = exp2s ((short)(byteptr [2] + (byteptr [3] << 8)));
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)));
if (!(wps->wphdr.flags & MONO_FLAG))
if (!(wps->wphdr.flags & MONO_DATA))
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;
}
// 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
// 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
@ -435,7 +447,7 @@ int32_t unpack_samples (WavpackContext *wpc, int32_t *buffer, uint32_t sample_co
///////////////// 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) {
if ((read_word = get_word_lossless (wps, 0)) == WORD_EOF)
break;
@ -473,7 +485,7 @@ int32_t unpack_samples (WavpackContext *wpc, int32_t *buffer, uint32_t sample_co
//////////////// 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);
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 //////////////////
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) {
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 ////////////////
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) {
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);
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);
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->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;
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;
}
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 ones = wps->int32_ones, dups = wps->int32_dups;
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;
}
if (!(flags & MONO_FLAG))
if (!(flags & MONO_DATA))
sample_count *= 2;
while (sample_count--) {
@ -1419,7 +1442,7 @@ static void fixup_samples (WavpackContext *wpc, int32_t *buffer, uint32_t sample
}
}
else if (shift) {
if (!(flags & MONO_FLAG))
if (!(flags & MONO_DATA))
sample_count *= 2;
while (sample_count--)

View File

@ -33,7 +33,7 @@ int32_t dump_alloc (void);
#endif
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);
#ifdef SEEKING
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
// 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);
@ -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
// 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 char default_terms [] = { 1,1,1,-1,2,1,-2 };
static const char simple_terms [] = { 1,1,1,1 };
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 signed char default_terms [] = { 1,1,1,-1,2,1,-2 };
static const signed char simple_terms [] = { 1,1,1,1 };
// This function initializes everything required to unpack WavPack
// 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);
uchar *buf, *end, *ptr;
uint32_t bufsiz, fpos, sr;
stream_reader *reader;
WavpackStreamReader *reader;
int error, bc;
void *id;
} Bitstream3;

View File

@ -15,15 +15,11 @@
#include <windows.h>
#include <io.h>
#include <conio.h>
#include <shlobj.h>
#elif defined(__GNUC__)
#include <glob.h>
#endif
#ifndef WIN32
#include <locale.h>
#include <iconv.h>
#endif
#include <sys/stat.h>
#include <stdlib.h>
#include <stdarg.h>
@ -63,6 +59,34 @@ int copy_timestamp (const char *src_filename, const char *dst_filename)
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
//////////////////////////////////////////////////////////////////////////////
@ -107,7 +131,7 @@ char *filespec_ext (char *filespec)
while (--cp >= filespec) {
if (*cp == '\\' || *cp == ':')
if (*cp == '/' || *cp == ':')
return NULL;
if (*cp == '.') {
@ -143,20 +167,21 @@ char *filespec_path (char *filespec)
if (cp == filespec || filespec_wild (filespec))
return NULL;
if (*--cp == '\\' || *cp == ':')
if (*--cp == '/' || *cp == ':')
return filespec;
if (*cp == '.' && cp == filespec)
return strcat (filespec, "\\");
return strcat (filespec, "/");
if (glob (filespec, GLOB_MARK|GLOB_NOSORT, NULL, &globs) == 0 &&
globs.gl_pathc > 0)
{
/* test if the file is a directory */
if (stat(globs.gl_pathv[0], &fstats) == 0 && (fstats.st_mode & S_IFDIR)) {
globfree(&globs);
filespec[0] = '\0';
return strcat (filespec, globs.gl_pathv[0]);
strcat (filespec, globs.gl_pathv[0]);
globfree(&globs);
return filespec;
}
}
globfree(&globs);
@ -243,7 +268,7 @@ char *filespec_name (char *filespec)
char *cp = filespec + strlen (filespec);
while (--cp >= filespec)
if (*cp == '\\' || *cp == ':')
if (*cp == '/' || *cp == ':')
break;
if (strlen (cp + 1))
@ -336,6 +361,62 @@ char yna (void)
// 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, ...)
{
char error_msg [512];
@ -347,8 +428,70 @@ void error_line (char *error, ...)
va_end (argptr);
fputs (error_msg, stderr);
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+");
if (error_log) {
@ -357,7 +500,6 @@ void error_line (char *error, ...)
fclose (error_log);
}
}
#endif
}
//////////////////////////////////////////////////////////////////////////////
@ -376,9 +518,6 @@ BOOL WINAPI ctrl_handler (DWORD ctrl)
if (ctrl == CTRL_BREAK_EVENT) {
if (waiting_input) {
#ifdef __BORLANDC__
fprintf (stderr, "^C\n");
#endif
return FALSE;
}
else {
@ -424,7 +563,7 @@ void finish_line (void)
CONSOLE_SCREEN_BUFFER_INFO 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--)
fputc (' ', stderr);
@ -440,12 +579,7 @@ void finish_line (void)
void finish_line (void)
{
/* char spaces = 1;
while (spaces--)
putc (' ', stderr);
else*/
fputc ('\n', stderr);
fprintf (stderr, " \n");
}
//////////////////////////////////////////////////////////////////////////////
@ -566,75 +700,3 @@ int DoDeleteFile (char *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
#define VERSION_OS "Win32"
#endif
#define VERSION_STR "4.2 "
#define DATE_STR "2005-04-02"
#define VERSION_STR "4.32"
#define DATE_STR "2006-04-05"
// 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"
typedef struct {
int32_t tag_file_pos;
ID3_Tag id3_tag;
APE_Tag_Hdr ape_tag_hdr;
char *ape_tag_data;
@ -168,11 +169,20 @@ typedef struct {
#define SRATE_LSB 23
#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 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
#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 /////////////////////////////////
// This is an internal representation of metadata.
@ -183,6 +193,7 @@ typedef struct {
uchar id;
} WavpackMetadata;
#define ID_UNIQUE 0x3f
#define ID_OPTIONAL_DATA 0x20
#define ID_ODD_SIZE 0x40
#define ID_LARGE 0x80
@ -208,6 +219,7 @@ typedef struct {
#define ID_CUESHEET (ID_OPTIONAL_DATA | 0x4)
#define ID_CONFIG_BLOCK (ID_OPTIONAL_DATA | 0x5)
#define ID_MD5_CHECKSUM (ID_OPTIONAL_DATA | 0x6)
#define ID_SAMPLE_RATE (ID_OPTIONAL_DATA | 0x7)
///////////////////////// WavPack Configuration ///////////////////////////////
@ -255,10 +267,10 @@ typedef struct {
#define CONFIG_MD5_CHECKSUM 0x8000000 // compute & store MD5 signature
#define CONFIG_QUIET_MODE 0x10000000 // don't report progress %
#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_STEREO_MODES 2
//#define EXTRA_CHECK_TERMS 4
#define EXTRA_TRY_DELTAS 8
#define EXTRA_ADJUST_DELTAS 16
#define EXTRA_SORT_FIRST 32
@ -291,9 +303,7 @@ struct decorr_pass {
int term, delta, weight_A, weight_B;
int32_t samples_A [MAX_TERM], samples_B [MAX_TERM];
int32_t aweight_A, aweight_B;
#ifdef PACK
int32_t sum_A, sum_B, min, max;
#endif
int32_t sum_A, sum_B;
};
typedef struct {
@ -303,9 +313,9 @@ typedef struct {
uchar *block2buff, *block2end;
int32_t *sample_buffer;
int bits, num_terms, mute_error, false_stereo, shift;
uint32_t sample_index, crc, crc_x, crc_wvx;
Bitstream wvbits, wvcbits, wvxbits;
int bits, num_terms, mute_error;
float delta_decay;
uchar int32_sent_bits, int32_zeros, int32_ones, int32_dups;
@ -349,9 +359,12 @@ typedef struct {
int (*push_back_byte)(void *id, int c);
uint32_t (*get_length)(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 {
WavpackConfig config;
@ -363,18 +376,18 @@ typedef struct {
uchar *wrapper_data;
uint32_t wrapper_bytes;
blockout blockout;
WavpackBlockOutput blockout;
void *wv_out, *wvc_out;
stream_reader *reader;
WavpackStreamReader *reader;
void *wv_in, *wvc_in;
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 block_samples, max_samples, acc_samples;
int block_samples, max_samples, acc_samples, riff_header_added, riff_header_created;
M_Tag m_tag;
int current_stream, num_streams;
int current_stream, num_streams, stream_version;
WavpackStream *streams [8];
void *stream3;
@ -459,8 +472,14 @@ int DoCloseHandle (FILE *hFile), DoTruncateFile (FILE *hFile);
(bs)->bc += 8; \
} \
*(value) = (bs)->sr; \
(bs)->sr >>= (nbits); \
(bs)->bc -= (nbits); \
if ((bs)->bc > 32) { \
(bs)->bc -= (nbits); \
(bs)->sr = *((bs)->ptr) >> (8 - (bs)->bc); \
} \
else { \
(bs)->bc -= (nbits); \
(bs)->sr >>= (nbits); \
} \
}
#define putbit(bit, bs) { if (bit) (bs)->sr |= (1 << (bs)->bc); \
@ -490,8 +509,9 @@ int DoCloseHandle (FILE *hFile), DoTruncateFile (FILE *hFile);
do { \
*((bs)->ptr) = (bs)->sr; \
(bs)->sr >>= 8; \
if (((bs)->bc -= 8) > 24) (bs)->sr |= ((value) >> ((nbits) - (bs)->bc)); \
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);
@ -517,6 +537,7 @@ int read_float_info (WavpackStream *wps, WavpackMetadata *wpmd);
int read_int32_info (WavpackStream *wps, WavpackMetadata *wpmd);
int read_channel_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);
int32_t unpack_samples (WavpackContext *wpc, int32_t *buffer, uint32_t sample_count);
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);
char *filespec_ext (char *filespec), *filespec_path (char *filespec);
char *filespec_name (char *filespec), *filespec_wild (char *filespec);
void error_line (char *error, ...), finish_line (void);
void setup_break (void);
void error_line (char *error, ...);
void setup_break (void), finish_line (void);
int check_break (void);
char yna (void);
void AnsiToUTF8 (char *string, int len);
#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);
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);
int restore_weight (char weight);
signed char store_weight (int weight);
int restore_weight (signed char weight);
#define WORD_EOF (1L << 31)
@ -593,7 +613,7 @@ void analyze_mono (WavpackContext *wpc, int32_t *samples);
// 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);
#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_STREAMING 0x20 // "streaming" mode blindly unpacks blocks
// w/o regard to header file position info
#define OPEN_EDIT_TAGS 0x40 // allow editing of tags
int WavpackGetMode (WavpackContext *wpc);
@ -639,11 +660,14 @@ uint32_t WavpackGetFileSize (WavpackContext *wpc);
double WavpackGetRatio (WavpackContext *wpc);
double WavpackGetAverageBitrate (WavpackContext *wpc, int count_wvc);
double WavpackGetInstantBitrate (WavpackContext *wpc);
int WavpackGetNumTagItems (WavpackContext *wpc);
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);
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 WavpackAddWrapper (WavpackContext *wpc, void *data, uint32_t bcount);
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 WavpackFlushSamples (WavpackContext *wpc);
void WavpackUpdateNumSamples (WavpackContext *wpc, void *first_block);
void *WavpackGetWrapperLocation (void *first_block);
void *WavpackGetWrapperLocation (void *first_block, uint32_t *size);
#endif

View File

@ -200,7 +200,7 @@ void word_set_bitrate (WavpackStream *wps)
if (wps->wphdr.flags & HYBRID_BITRATE) {
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)
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 >> 8;
if (!(wps->wphdr.flags & MONO_FLAG)) {
if (!(wps->wphdr.flags & MONO_DATA)) {
*byteptr++ = temp = mylog2 (wps->w.median [0] [1]);
*byteptr++ = temp >> 8;
*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 >> 8;
if (!(wps->wphdr.flags & MONO_FLAG)) {
if (!(wps->wphdr.flags & MONO_DATA)) {
*byteptr++ = temp = log2s (wps->w.slow_level [1]);
*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 >> 8;
if (!(wps->wphdr.flags & MONO_FLAG)) {
if (!(wps->wphdr.flags & MONO_DATA)) {
*byteptr++ = temp = wps->w.bitrate_acc [1] >> 16;
*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 >> 8;
if (!(wps->wphdr.flags & MONO_FLAG)) {
if (!(wps->wphdr.flags & MONO_DATA)) {
*byteptr++ = temp = log2s (wps->w.bitrate_delta [1]);
*byteptr++ = temp >> 8;
}
@ -319,14 +319,14 @@ int read_entropy_vars (WavpackStream *wps, WavpackMetadata *wpmd)
{
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;
wps->w.median [0] [0] = exp2s (byteptr [0] + (byteptr [1] << 8));
wps->w.median [1] [0] = exp2s (byteptr [2] + (byteptr [3] << 8));
wps->w.median [2] [0] = exp2s (byteptr [4] + (byteptr [5] << 8));
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 [1] [1] = exp2s (byteptr [8] + (byteptr [9] << 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));
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));
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;
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;
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)));
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)));
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;
if (wps->wphdr.flags & MONO_FLAG) {
if (wps->wphdr.flags & MONO_DATA) {
if (wps->wphdr.flags & HYBRID_BITRATE) {
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) {
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);
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.median);
if (flags & MONO_FLAG) {
if (flags & MONO_DATA) {
if (dir < 0) {
samples += (num_samples - 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]);
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
// 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;
int dbits;
@ -1373,7 +1366,10 @@ uint32_t log2buffer (int32_t *samples, uint32_t num_samples)
else
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
// 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)
weight = 1024;
@ -1426,7 +1422,7 @@ char store_weight (int weight)
return (weight + 4) >> 3;
}
int restore_weight (char weight)
int restore_weight (signed char weight)
{
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_SHAPE_OVERRIDE 0x8000 // shaping 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_OPTIMIZE_WVC 0x100000 // maximize bybrid compression
#define CONFIG_CALC_NOISE 0x800000 // calc noise in hybrid mode
#define CONFIG_EXTRA_MODE 0x2000000 // extra processing mode
#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 //////////
@ -78,9 +80,12 @@ typedef struct {
int (*push_back_byte)(void *id, int c);
uint32_t (*get_length)(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 //////////////////////
@ -90,7 +95,7 @@ typedef void WavpackContext;
extern "C" {
#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);
#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_STREAMING 0x20 // "streaming" mode blindly unpacks blocks
// w/o regard to header file position info
#define OPEN_EDIT_TAGS 0x40 // allow editing of tags
int WavpackGetMode (WavpackContext *wpc);
@ -137,12 +143,15 @@ uint32_t WavpackGetFileSize (WavpackContext *wpc);
double WavpackGetRatio (WavpackContext *wpc);
double WavpackGetAverageBitrate (WavpackContext *wpc, int count_wvc);
double WavpackGetInstantBitrate (WavpackContext *wpc);
int WavpackGetNumTagItems (WavpackContext *wpc);
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);
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 WavpackAddWrapper (WavpackContext *wpc, void *data, uint32_t bcount);
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 WavpackFlushSamples (WavpackContext *wpc);
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

View File

@ -16,15 +16,15 @@
#else
#include <sys/stat.h>
#include <sys/param.h>
#include <locale.h>
#include <iconv.h>
#if defined (__GNUC__)
#include <unistd.h>
#include <glob.h>
#endif
#endif
#ifdef __BORLANDC__
#include <dir.h>
#elif defined(__GNUC__) && !defined(WIN32)
#if defined(__GNUC__) && !defined(WIN32)
#include <sys/time.h>
#else
#include <sys/timeb.h>
@ -53,25 +53,39 @@ static char *strdup (const char *s)
///////////////////////////// local variable storage //////////////////////////
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";
static const char *usage =
#if defined (WIN32)
" 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"
" Options: -d = delete source file if successful (use with caution!)\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"
" -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"
" -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"
#endif
" -v = verify source data only (no output file created)\n"
" -y = yes to overwrite warning (use with caution!)\n\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,
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 verify_only = 0, usage_error = 0, filelist = 0, add_extension = 0;
char *infilename = NULL, *outfilename = NULL;
char outpath, **matches = NULL;
int verify_only = 0, error_count = 0, add_extension = 0, output_spec = 0;
char outpath, **matches = NULL, *outfilename = NULL;
int result, i;
#ifdef __BORLANDC__
struct ffblk ffblk;
#elif defined(WIN32)
#if defined(WIN32)
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
glob_t globs;
struct stat fstats;
if (filespec_name (*argv))
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
// loop through command-line arguments
@ -123,17 +154,26 @@ int main (argc, argv) int argc; char **argv;
case 'D': case 'd':
delete_source = 1;
break;
#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':
copy_time = 1;
break;
#endif
case 'V': case 'v':
verify_only = 1;
break;
case 'S': case 's':
summary = 1;
++summary;
break;
case 'K': case 'k':
@ -159,12 +199,20 @@ int main (argc, argv) int argc; char **argv;
default:
error_line ("illegal option: %c !", **argv);
usage_error = 1;
++error_count;
}
else {
if (!infilename) {
infilename = malloc (strlen (*argv) + PATH_MAX);
strcpy (infilename, *argv);
#if defined (WIN32)
if (!num_files) {
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) {
outfilename = malloc (strlen (*argv) + PATH_MAX);
@ -172,8 +220,26 @@ int main (argc, argv) int argc; char **argv;
}
else {
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) {
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);
if (!infilename) {
if (!num_files) {
printf ("%s", usage);
return 0;
return 1;
}
if (usage_error) {
free (infilename);
return 0;
}
if (error_count)
return 1;
setup_break ();
// If the infile specification begins with a '@', then it actually points
// to a file that contains the names of the files to be converted. This
// was included for use by Wim Speekenbrink's frontends, but could be used
// for other purposes.
for (file_index = 0; file_index < num_files; ++file_index) {
char *infilename = matches [file_index];
if (infilename [0] == '@') {
FILE *list = fopen (infilename+1, "rt");
int c;
// If the single infile specification begins with a '@', then it
// actually points to a file that contains the names of the files
// to be converted. This was included for use by Wim Speekenbrink's
// frontends, but could be used for other purposes.
if (list == NULL) {
error_line ("file %s not found!", infilename+1);
free(infilename);
return 1;
}
if (*infilename == '@') {
FILE *list = fopen (infilename+1, "rt");
int di, c;
while ((c = getc (list)) != EOF) {
for (di = file_index; di < num_files - 1; di++)
matches [di] = matches [di + 1];
while (c == '\n')
c = getc (list);
file_index--;
num_files--;
if (c != EOF) {
char *fname = malloc (PATH_MAX);
int ci = 0;
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);
if (list == NULL) {
error_line ("file %s not found!", infilename+1);
free (infilename);
return 1;
}
}
fclose (list);
free (infilename);
infilename = NULL;
filelist = 1;
}
else if (*infilename != '-') { // skip this if infile is stdin (-)
if (!filespec_ext (infilename))
strcat (infilename, ".wv");
while ((c = getc (list)) != EOF) {
#ifdef NO_WILDCARDS
matches = malloc (sizeof (*matches));
matches [num_files++] = infilename;
filelist = 1;
#else
// search for and store any filenames that match the user supplied spec
while (c == '\n')
c = getc (list);
#ifdef __BORLANDC__
if (findfirst (infilename, &ffblk, 0) == 0) {
do {
matches = realloc (matches, ++num_files * sizeof (*matches));
matches [num_files - 1] = strdup (ffblk.ff_name);
} while (findnext (&ffblk) == 0);
}
#elif defined (WIN32)
if ((i = _findfirst (infilename, &_finddata_t)) != -1L) {
do {
if (!(_finddata_t.attrib & _A_SUBDIR)) {
if (c != EOF) {
char *fname = malloc (PATH_MAX);
int ci = 0;
do
fname [ci++] = c;
while ((c = getc (list)) != '\n' && c != EOF && ci < PATH_MAX);
fname [ci++] = '\0';
fname = realloc (fname, ci);
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
}
else { // handle case of stdin (-)
matches = malloc (sizeof (*matches));
matches [num_files++] = infilename;
}
// 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 (num_files) {
int soft_errors = 0;
if (outfilename && *outfilename != '-') {
outpath = (filespec_path (outfilename) != NULL);
if (num_files > 1 && !outpath) {
error_line ("%s is not a valid output path", outfilename);
free(outfilename);
free (outfilename);
return 1;
}
}
@ -352,15 +412,6 @@ int main (argc, argv) int argc; char **argv;
if (check_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
if (outpath) {
@ -370,8 +421,8 @@ int main (argc, argv) int argc; char **argv;
*filespec_ext (outfilename) = '\0';
}
else if (!outfilename) {
outfilename = malloc (strlen (infilename) + 10);
strcpy (outfilename, infilename);
outfilename = malloc (strlen (matches [file_index]) + 10);
strcpy (outfilename, matches [file_index]);
if (filespec_ext (outfilename))
*filespec_ext (outfilename) = '\0';
@ -381,14 +432,15 @@ int main (argc, argv) int argc; char **argv;
strcat (outfilename, raw_decode ? ".raw" : ".wav");
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)
break;
else if (result == SOFT_ERROR)
++soft_errors;
// 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 (soft_errors)
fprintf (stderr, "\n **** warning: errors occurred in %d of %d files! ****\n", soft_errors, num_files);
if (error_count)
fprintf (stderr, "\n **** warning: errors occurred in %d of %d files! ****\n", error_count, num_files);
else if (!quiet_mode)
fprintf (stderr, "\n **** %d files successfully processed ****\n", num_files);
}
free (matches);
}
else
error_line (filespec_wild (infilename) ? "nothing to do!" :
"file %s not found!", infilename);
else {
error_line ("nothing to do!");
++error_count;
}
if (outfilename)
free(outfilename);
free (outfilename);
#ifdef DEBUG_ALLOC
error_line ("malloc_count = %d", dump_alloc ());
#endif
return 0;
return error_count ? 1 : 0;
}
// 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 void dump_summary (WavpackContext *wpc, char *name, FILE *dst);
extern int delta_blocks [8];
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;
@ -450,9 +501,7 @@ static int unpack_file (char *infilename, char *outfilename)
char error [80];
FILE *outfile;
#ifdef __BORLANDC__
struct time time1, time2;
#elif defined(WIN32)
#if defined(WIN32)
struct _timeb time1, time2;
#else
struct timeval time1, time2;
@ -470,6 +519,9 @@ static int unpack_file (char *infilename, char *outfilename)
if (!ignore_wvc)
open_flags |= OPEN_WVC;
if (summary > 1)
open_flags |= OPEN_TAGS;
wpc = WavpackOpenFileInput (infilename, error, open_flags, 0);
if (!wpc) {
@ -491,6 +543,12 @@ static int unpack_file (char *infilename, char *outfilename)
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 != '-') {
@ -554,9 +612,7 @@ static int unpack_file (char *infilename, char *outfilename)
FN_FIT (infilename), wvc_mode ? " (+.wvc)" : "");
}
#ifdef __BORLANDC__
gettime (&time1);
#elif defined(WIN32)
#if defined(WIN32)
_ftime (&time1);
#else
gettimeofday(&time1,&timez);
@ -609,7 +665,7 @@ static int unpack_file (char *infilename, char *outfilename)
if (calc_md5 && samples_unpacked) {
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)
@ -641,12 +697,6 @@ static int unpack_file (char *infilename, char *outfilename)
if (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) {
char md5_string1 [] = "00000000000000000000000000000000";
char md5_string2 [] = "00000000000000000000000000000000";
@ -700,11 +750,9 @@ for (i = 0; i < 8; ++i)
DoDeleteFile (outfilename);
}
#if defined (WIN32)
if (result == NO_ERROR && copy_time && outfilename &&
!copy_timestamp (infilename, outfilename))
error_line ("failure copying time stamp!");
#endif
if (result == NO_ERROR && WavpackGetNumSamples (wpc) != (uint32_t) -1 &&
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
// the unpacking operation (assuming there was no error).
#ifdef __BORLANDC__
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)
#if defined(WIN32)
_ftime (&time2);
dtime = time2.time + time2.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;
}
static UTF8ToAnsi (char *string, int len);
static void dump_summary (WavpackContext *wpc, char *name, FILE *dst)
{
int num_channels = WavpackGetNumChannels (wpc);
@ -864,7 +907,7 @@ static void dump_summary (WavpackContext *wpc, char *name, FILE *dst)
seconds -= minutes * 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;
@ -907,6 +950,135 @@ static void dump_summary (WavpackContext *wpc, char *name, FILE *dst)
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);
#ifdef __BIG_ENDIAN__
isBigEndian = YES;
#else
isBigEndian = NO;
#endif
isBigEndian = hostIsBigEndian();
return YES;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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