about summary refs log tree commit diff
path: root/src/engine/external/wavpack/unpack.c
diff options
context:
space:
mode:
authorMagnus Auvinen <magnus.auvinen@gmail.com>2008-11-29 06:39:22 +0000
committerMagnus Auvinen <magnus.auvinen@gmail.com>2008-11-29 06:39:22 +0000
commit4004d13b48fd303c982dbcf7c432add64d128637 (patch)
treefb67a18724bb8e1435b0938abe56c24d68fa2dce /src/engine/external/wavpack/unpack.c
parent61d18702f63cc4731c923e9ca8cd8d98cdaca4ad (diff)
downloadzcatch-4004d13b48fd303c982dbcf7c432add64d128637.tar.gz
zcatch-4004d13b48fd303c982dbcf7c432add64d128637.zip
applied patch from Richie Nyhus to convert CRLF to LF, as it should be
Diffstat (limited to 'src/engine/external/wavpack/unpack.c')
-rw-r--r--src/engine/external/wavpack/unpack.c1570
1 files changed, 785 insertions, 785 deletions
diff --git a/src/engine/external/wavpack/unpack.c b/src/engine/external/wavpack/unpack.c
index 2bed5a0c..317fe222 100644
--- a/src/engine/external/wavpack/unpack.c
+++ b/src/engine/external/wavpack/unpack.c
@@ -1,785 +1,785 @@
-////////////////////////////////////////////////////////////////////////////

-//                           **** WAVPACK ****                            //

-//                  Hybrid Lossless Wavefile Compressor                   //

-//              Copyright (c) 1998 - 2006 Conifer Software.               //

-//                          All Rights Reserved.                          //

-//      Distributed under the BSD Software License (see license.txt)      //

-////////////////////////////////////////////////////////////////////////////

-

-// unpack.c

-

-// This module actually handles the decompression of the audio data, except

-// for the entropy decoding which is handled by the words.c module. For

-// maximum efficiency, the conversion is isolated to tight loops that handle

-// an entire buffer.

-

-#include "wavpack.h"

-

-#include <stdlib.h>

-#include <string.h>

-

-#define LOSSY_MUTE

-

-///////////////////////////// executable code ////////////////////////////////

-

-// This function initializes everything required to unpack a WavPack block

-// and must be called before unpack_samples() is called to obtain audio data.

-// It is assumed that the WavpackHeader has been read into the wps->wphdr

-// (in the current WavpackStream). This is where all the metadata blocks are

-// scanned up to the one containing the audio bitstream.

-

-int unpack_init (WavpackContext *wpc)

-{

-    WavpackStream *wps = &wpc->stream;

-    WavpackMetadata wpmd;

-

-    if (wps->wphdr.block_samples && wps->wphdr.block_index != (uint32_t) -1)

-        wps->sample_index = wps->wphdr.block_index;

-

-    wps->mute_error = FALSE;

-    wps->crc = 0xffffffff;

-    CLEAR (wps->wvbits);

-    CLEAR (wps->decorr_passes);

-    CLEAR (wps->w);

-

-    while (read_metadata_buff (wpc, &wpmd)) {

-        if (!process_metadata (wpc, &wpmd)) {

-            strcpy (wpc->error_message, "invalid metadata!");

-            return FALSE;

-        }

-

-        if (wpmd.id == ID_WV_BITSTREAM)

-            break;

-    }

-

-    if (wps->wphdr.block_samples && !bs_is_open (&wps->wvbits)) {

-        strcpy (wpc->error_message, "invalid WavPack file!");

-        return FALSE;

-    }

-

-    if (wps->wphdr.block_samples) {

-        if ((wps->wphdr.flags & INT32_DATA) && wps->int32_sent_bits)

-            wpc->lossy_blocks = TRUE;

-

-        if ((wps->wphdr.flags & FLOAT_DATA) &&

-            wps->float_flags & (FLOAT_EXCEPTIONS | FLOAT_ZEROS_SENT | FLOAT_SHIFT_SENT | FLOAT_SHIFT_SAME))

-                wpc->lossy_blocks = TRUE;

-    }

-

-    return TRUE;

-}

-

-// This function initialzes the main bitstream for audio samples, which must

-// be in the "wv" file.

-

-int init_wv_bitstream (WavpackContext *wpc, WavpackMetadata *wpmd)

-{

-    WavpackStream *wps = &wpc->stream;

-

-    if (wpmd->data)

-        bs_open_read (&wps->wvbits, wpmd->data, (unsigned char *) wpmd->data + wpmd->byte_length, NULL, 0);

-    else if (wpmd->byte_length)

-        bs_open_read (&wps->wvbits, wpc->read_buffer, wpc->read_buffer + sizeof (wpc->read_buffer),

-            wpc->infile, wpmd->byte_length + (wpmd->byte_length & 1));

-

-    return TRUE;

-}

-

-// Read decorrelation terms from specified metadata block into the

-// decorr_passes array. The terms range from -3 to 8, plus 17 & 18;

-// other values are reserved and generate errors for now. The delta

-// ranges from 0 to 7 with all values valid. Note that the terms are

-// stored in the opposite order in the decorr_passes array compared

-// to packing.

-

-int read_decorr_terms (WavpackStream *wps, WavpackMetadata *wpmd)

-{

-    int termcnt = wpmd->byte_length;

-    uchar *byteptr = wpmd->data;

-    struct decorr_pass *dpp;

-

-    if (termcnt > MAX_NTERMS)

-        return FALSE;

-

-    wps->num_terms = termcnt;

-

-    for (dpp = wps->decorr_passes + termcnt - 1; termcnt--; dpp--) {

-        dpp->term = (int)(*byteptr & 0x1f) - 5;

-        dpp->delta = (*byteptr++ >> 5) & 0x7;

-

-        if (!dpp->term || dpp->term < -3 || (dpp->term > MAX_TERM && dpp->term < 17) || dpp->term > 18)

-            return FALSE;

-    }

-

-    return TRUE;

-}

-

-// Read decorrelation weights from specified metadata block into the

-// decorr_passes array. The weights range +/-1024, but are rounded and

-// truncated to fit in signed chars for metadata storage. Weights are

-// separate for the two channels and are specified from the "last" term

-// (first during encode). Unspecified weights are set to zero.

-

-int read_decorr_weights (WavpackStream *wps, WavpackMetadata *wpmd)

-{

-    int termcnt = wpmd->byte_length, tcount;

-    signed char *byteptr = wpmd->data;

-    struct decorr_pass *dpp;

-

-    if (!(wps->wphdr.flags & MONO_DATA))

-        termcnt /= 2;

-

-    if (termcnt > wps->num_terms)

-        return FALSE;

-

-    for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++)

-        dpp->weight_A = dpp->weight_B = 0;

-

-    while (--dpp >= wps->decorr_passes && termcnt--) {

-        dpp->weight_A = restore_weight (*byteptr++);

-

-        if (!(wps->wphdr.flags & MONO_DATA))

-            dpp->weight_B = restore_weight (*byteptr++);

-    }

-

-    return TRUE;

-}

-

-// Read decorrelation samples from specified metadata block into the

-// decorr_passes array. The samples are signed 32-bit values, but are

-// converted to signed log2 values for storage in metadata. Values are

-// stored for both channels and are specified from the "last" term

-// (first during encode) with unspecified samples set to zero. The

-// number of samples stored varies with the actual term value, so

-// those must obviously come first in the metadata.

-

-int read_decorr_samples (WavpackStream *wps, WavpackMetadata *wpmd)

-{

-    uchar *byteptr = wpmd->data;

-    uchar *endptr = byteptr + wpmd->byte_length;

-    struct decorr_pass *dpp;

-    int tcount;

-

-    for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++) {

-        CLEAR (dpp->samples_A);

-        CLEAR (dpp->samples_B);

-    }

-

-    if (wps->wphdr.version == 0x402 && (wps->wphdr.flags & HYBRID_FLAG)) {

-        byteptr += 2;

-

-        if (!(wps->wphdr.flags & MONO_DATA))

-            byteptr += 2;

-    }

-

-    while (dpp-- > wps->decorr_passes && byteptr < endptr)

-        if (dpp->term > MAX_TERM) {

-            dpp->samples_A [0] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8)));

-            dpp->samples_A [1] = exp2s ((short)(byteptr [2] + (byteptr [3] << 8)));

-            byteptr += 4;

-

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

-            }

-        }

-        else if (dpp->term < 0) {

-            dpp->samples_A [0] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8)));

-            dpp->samples_B [0] = exp2s ((short)(byteptr [2] + (byteptr [3] << 8)));

-            byteptr += 4;

-        }

-        else {

-            int m = 0, cnt = dpp->term;

-

-            while (cnt--) {

-                dpp->samples_A [m] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8)));

-                byteptr += 2;

-

-                if (!(wps->wphdr.flags & MONO_DATA)) {

-                    dpp->samples_B [m] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8)));

-                    byteptr += 2;

-                }

-

-                m++;

-            }

-        }

-

-    return byteptr == endptr;

-}

-

-// Read the int32 data from the specified metadata into the specified stream.

-// This data is used for integer data that has more than 24 bits of magnitude

-// or, in some cases, used to eliminate redundant bits from any audio stream.

-

-int read_int32_info (WavpackStream *wps, WavpackMetadata *wpmd)

-{

-    int bytecnt = wpmd->byte_length;

-    char *byteptr = wpmd->data;

-

-    if (bytecnt != 4)

-        return FALSE;

-

-    wps->int32_sent_bits = *byteptr++;

-    wps->int32_zeros = *byteptr++;

-    wps->int32_ones = *byteptr++;

-    wps->int32_dups = *byteptr;

-    return TRUE;

-}

-

-// Read multichannel information from metadata. The first byte is the total

-// number of channels and the following bytes represent the channel_mask

-// as described for Microsoft WAVEFORMATEX.

-

-int read_channel_info (WavpackContext *wpc, WavpackMetadata *wpmd)

-{

-    int bytecnt = wpmd->byte_length, shift = 0;

-    char *byteptr = wpmd->data;

-    uint32_t mask = 0;

-

-    if (!bytecnt || bytecnt > 5)

-        return FALSE;

-

-    wpc->config.num_channels = *byteptr++;

-

-    while (--bytecnt) {

-        mask |= (uint32_t) *byteptr++ << shift;

-        shift += 8;

-    }

-

-    wpc->config.channel_mask = mask;

-    return TRUE;

-}

-

-// Read configuration information from metadata.

-

-int read_config_info (WavpackContext *wpc, WavpackMetadata *wpmd)

-{

-    int bytecnt = wpmd->byte_length;

-    uchar *byteptr = wpmd->data;

-

-    if (bytecnt >= 3) {

-        wpc->config.flags &= 0xff;

-        wpc->config.flags |= (int32_t) *byteptr++ << 8;

-        wpc->config.flags |= (int32_t) *byteptr++ << 16;

-        wpc->config.flags |= (int32_t) *byteptr << 24;

-    }

-

-    return TRUE;

-}

-

-// This monster actually unpacks the WavPack bitstream(s) into the specified

-// buffer as 32-bit integers or floats (depending on orignal data). Lossy

-// samples will be clipped to their original limits (i.e. 8-bit samples are

-// clipped to -128/+127) but are still returned in int32_ts. It is up to the

-// caller to potentially reformat this for the final output including any

-// multichannel distribution, block alignment or endian compensation. The

-// function unpack_init() must have been called and the entire WavPack block

-// must still be visible (although wps->blockbuff will not be accessed again).

-// For maximum clarity, the function is broken up into segments that handle

-// various modes. This makes for a few extra infrequent flag checks, but

-// makes the code easier to follow because the nesting does not become so

-// deep. For maximum efficiency, the conversion is isolated to tight loops

-// that handle an entire buffer. The function returns the total number of

-// samples unpacked, which can be less than the number requested if an error

-// occurs or the end of the block is reached.

-

-#if defined(CPU_COLDFIRE) && !defined(SIMULATOR)

-extern void decorr_stereo_pass_cont_mcf5249 (struct decorr_pass *dpp, int32_t *buffer, int32_t sample_count);

-#elif defined(CPU_ARM) && !defined(SIMULATOR)

-extern void decorr_stereo_pass_cont_arm (struct decorr_pass *dpp, int32_t *buffer, int32_t sample_count);

-extern void decorr_stereo_pass_cont_arml (struct decorr_pass *dpp, int32_t *buffer, int32_t sample_count);

-#else

-static void decorr_stereo_pass_cont (struct decorr_pass *dpp, int32_t *buffer, int32_t sample_count);

-#endif

-

-static void decorr_mono_pass (struct decorr_pass *dpp, int32_t *buffer, int32_t sample_count);

-static void decorr_stereo_pass (struct decorr_pass *dpp, int32_t *buffer, int32_t sample_count);

-static void fixup_samples (WavpackStream *wps, int32_t *buffer, uint32_t sample_count);

-

-int32_t unpack_samples (WavpackContext *wpc, int32_t *buffer, uint32_t sample_count)

-{

-    WavpackStream *wps = &wpc->stream;

-    uint32_t flags = wps->wphdr.flags, crc = wps->crc, i;

-    int32_t mute_limit = (1L << ((flags & MAG_MASK) >> MAG_LSB)) + 2;

-    struct decorr_pass *dpp;

-    int32_t *bptr, *eptr;

-    int tcount;

-

-    if (wps->sample_index + sample_count > wps->wphdr.block_index + wps->wphdr.block_samples)

-        sample_count = wps->wphdr.block_index + wps->wphdr.block_samples - wps->sample_index;

-

-    if (wps->mute_error) {

-        memset (buffer, 0, sample_count * (flags & MONO_FLAG ? 4 : 8));

-        wps->sample_index += sample_count;

-        return sample_count;

-    }

-

-    if (flags & HYBRID_FLAG)

-        mute_limit *= 2;

-

-    ///////////////////// handle version 4 mono data /////////////////////////

-

-    if (flags & MONO_DATA) {

-        eptr = buffer + sample_count;

-        i = get_words (buffer, sample_count, flags, &wps->w, &wps->wvbits);

-

-        for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++)

-            decorr_mono_pass (dpp, buffer, sample_count);

-

-        for (bptr = buffer; bptr < eptr; ++bptr) {

-            if (labs (bptr [0]) > mute_limit) {

-                i = bptr - buffer;

-                break;

-            }

-

-            crc = crc * 3 + bptr [0];

-        }

-    }

-

-    //////////////////// handle version 4 stereo data ////////////////////////

-

-    else {

-        eptr = buffer + (sample_count * 2);

-        i = get_words (buffer, sample_count, flags, &wps->w, &wps->wvbits);

-

-        if (sample_count < 16)

-            for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++)

-                decorr_stereo_pass (dpp, buffer, sample_count);

-        else

-            for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++) {

-                decorr_stereo_pass (dpp, buffer, 8);

-#if defined(CPU_COLDFIRE) && !defined(SIMULATOR)

-                decorr_stereo_pass_cont_mcf5249 (dpp, buffer + 16, sample_count - 8);

-#elif defined(CPU_ARM) && !defined(SIMULATOR)

-                if (((flags & MAG_MASK) >> MAG_LSB) > 15)

-                    decorr_stereo_pass_cont_arml (dpp, buffer + 16, sample_count - 8);

-                else

-                    decorr_stereo_pass_cont_arm (dpp, buffer + 16, sample_count - 8);

-#else

-                decorr_stereo_pass_cont (dpp, buffer + 16, sample_count - 8);

-#endif

-            }

-

-        if (flags & JOINT_STEREO)

-            for (bptr = buffer; bptr < eptr; bptr += 2) {

-                bptr [0] += (bptr [1] -= (bptr [0] >> 1));

-

-                if (labs (bptr [0]) > mute_limit || labs (bptr [1]) > mute_limit) {

-                    i = (bptr - buffer) / 2;

-                    break;

-                }

-

-                crc = (crc * 3 + bptr [0]) * 3 + bptr [1];

-            }

-        else

-            for (bptr = buffer; bptr < eptr; bptr += 2) {

-                if (labs (bptr [0]) > mute_limit || labs (bptr [1]) > mute_limit) {

-                    i = (bptr - buffer) / 2;

-                    break;

-                }

-

-                crc = (crc * 3 + bptr [0]) * 3 + bptr [1];

-            }

-    }

-

-    if (i != sample_count) {

-        memset (buffer, 0, sample_count * (flags & MONO_FLAG ? 4 : 8));

-        wps->mute_error = TRUE;

-        i = sample_count;

-    }

-

-    fixup_samples (wps, buffer, i);

-

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

-

-    return i;

-}

-

-static void decorr_stereo_pass (struct decorr_pass *dpp, int32_t *buffer, int32_t sample_count)

-{

-    int32_t delta = dpp->delta, weight_A = dpp->weight_A, weight_B = dpp->weight_B;

-    int32_t *bptr, *eptr = buffer + (sample_count * 2), sam_A, sam_B;

-    int m, k;

-

-    switch (dpp->term) {

-

-        case 17:

-            for (bptr = buffer; bptr < eptr; bptr += 2) {

-                sam_A = 2 * dpp->samples_A [0] - dpp->samples_A [1];

-                dpp->samples_A [1] = dpp->samples_A [0];

-                dpp->samples_A [0] = apply_weight (weight_A, sam_A) + bptr [0];

-                update_weight (weight_A, delta, sam_A, bptr [0]);

-                bptr [0] = dpp->samples_A [0];

-

-                sam_A = 2 * dpp->samples_B [0] - dpp->samples_B [1];

-                dpp->samples_B [1] = dpp->samples_B [0];

-                dpp->samples_B [0] = apply_weight (weight_B, sam_A) + bptr [1];

-                update_weight (weight_B, delta, sam_A, bptr [1]);

-                bptr [1] = dpp->samples_B [0];

-            }

-

-            break;

-

-        case 18:

-            for (bptr = buffer; bptr < eptr; bptr += 2) {

-                sam_A = (3 * dpp->samples_A [0] - dpp->samples_A [1]) >> 1;

-                dpp->samples_A [1] = dpp->samples_A [0];

-                dpp->samples_A [0] = apply_weight (weight_A, sam_A) + bptr [0];

-                update_weight (weight_A, delta, sam_A, bptr [0]);

-                bptr [0] = dpp->samples_A [0];

-

-                sam_A = (3 * dpp->samples_B [0] - dpp->samples_B [1]) >> 1;

-                dpp->samples_B [1] = dpp->samples_B [0];

-                dpp->samples_B [0] = apply_weight (weight_B, sam_A) + bptr [1];

-                update_weight (weight_B, delta, sam_A, bptr [1]);

-                bptr [1] = dpp->samples_B [0];

-            }

-

-            break;

-

-        default:

-            for (m = 0, k = dpp->term & (MAX_TERM - 1), bptr = buffer; bptr < eptr; bptr += 2) {

-                sam_A = dpp->samples_A [m];

-                dpp->samples_A [k] = apply_weight (weight_A, sam_A) + bptr [0];

-                update_weight (weight_A, delta, sam_A, bptr [0]);

-                bptr [0] = dpp->samples_A [k];

-

-                sam_A = dpp->samples_B [m];

-                dpp->samples_B [k] = apply_weight (weight_B, sam_A) + bptr [1];

-                update_weight (weight_B, delta, sam_A, bptr [1]);

-                bptr [1] = dpp->samples_B [k];

-

-                m = (m + 1) & (MAX_TERM - 1);

-                k = (k + 1) & (MAX_TERM - 1);

-            }

-

-            if (m) {

-                int32_t temp_samples [MAX_TERM];

-

-                memcpy (temp_samples, dpp->samples_A, sizeof (dpp->samples_A));

-

-                for (k = 0; k < MAX_TERM; k++, m++)

-                    dpp->samples_A [k] = temp_samples [m & (MAX_TERM - 1)];

-

-                memcpy (temp_samples, dpp->samples_B, sizeof (dpp->samples_B));

-

-                for (k = 0; k < MAX_TERM; k++, m++)

-                    dpp->samples_B [k] = temp_samples [m & (MAX_TERM - 1)];

-            }

-

-            break;

-

-        case -1:

-            for (bptr = buffer; bptr < eptr; bptr += 2) {

-                sam_A = bptr [0] + apply_weight (weight_A, dpp->samples_A [0]);

-                update_weight_clip (weight_A, delta, dpp->samples_A [0], bptr [0]);

-                bptr [0] = sam_A;

-                dpp->samples_A [0] = bptr [1] + apply_weight (weight_B, sam_A);

-                update_weight_clip (weight_B, delta, sam_A, bptr [1]);

-                bptr [1] = dpp->samples_A [0];

-            }

-

-            break;

-

-        case -2:

-            for (bptr = buffer; bptr < eptr; bptr += 2) {

-                sam_B = bptr [1] + apply_weight (weight_B, dpp->samples_B [0]);

-                update_weight_clip (weight_B, delta, dpp->samples_B [0], bptr [1]);

-                bptr [1] = sam_B;

-                dpp->samples_B [0] = bptr [0] + apply_weight (weight_A, sam_B);

-                update_weight_clip (weight_A, delta, sam_B, bptr [0]);

-                bptr [0] = dpp->samples_B [0];

-            }

-

-            break;

-

-        case -3:

-            for (bptr = buffer; bptr < eptr; bptr += 2) {

-                sam_A = bptr [0] + apply_weight (weight_A, dpp->samples_A [0]);

-                update_weight_clip (weight_A, delta, dpp->samples_A [0], bptr [0]);

-                sam_B = bptr [1] + apply_weight (weight_B, dpp->samples_B [0]);

-                update_weight_clip (weight_B, delta, dpp->samples_B [0], bptr [1]);

-                bptr [0] = dpp->samples_B [0] = sam_A;

-                bptr [1] = dpp->samples_A [0] = sam_B;

-            }

-

-            break;

-    }

-

-    dpp->weight_A = weight_A;

-    dpp->weight_B = weight_B;

-}

-

-#if (!defined(CPU_COLDFIRE) && !defined(CPU_ARM)) || defined(SIMULATOR)

-

-static void decorr_stereo_pass_cont (struct decorr_pass *dpp, int32_t *buffer, int32_t sample_count)

-{

-    int32_t delta = dpp->delta, weight_A = dpp->weight_A, weight_B = dpp->weight_B;

-    int32_t *bptr, *tptr, *eptr = buffer + (sample_count * 2), sam_A, sam_B;

-    int k, i;

-

-    switch (dpp->term) {

-

-        case 17:

-            for (bptr = buffer; bptr < eptr; bptr += 2) {

-                sam_A = 2 * bptr [-2] - bptr [-4];

-                bptr [0] = apply_weight (weight_A, sam_A) + (sam_B = bptr [0]);

-                update_weight (weight_A, delta, sam_A, sam_B);

-

-                sam_A = 2 * bptr [-1] - bptr [-3];

-                bptr [1] = apply_weight (weight_B, sam_A) + (sam_B = bptr [1]);

-                update_weight (weight_B, delta, sam_A, sam_B);

-            }

-

-            dpp->samples_B [0] = bptr [-1];

-            dpp->samples_A [0] = bptr [-2];

-            dpp->samples_B [1] = bptr [-3];

-            dpp->samples_A [1] = bptr [-4];

-            break;

-

-        case 18:

-            for (bptr = buffer; bptr < eptr; bptr += 2) {

-                sam_A = (3 * bptr [-2] - bptr [-4]) >> 1;

-                bptr [0] = apply_weight (weight_A, sam_A) + (sam_B = bptr [0]);

-                update_weight (weight_A, delta, sam_A, sam_B);

-

-                sam_A = (3 * bptr [-1] - bptr [-3]) >> 1;

-                bptr [1] = apply_weight (weight_B, sam_A) + (sam_B = bptr [1]);

-                update_weight (weight_B, delta, sam_A, sam_B);

-            }

-

-            dpp->samples_B [0] = bptr [-1];

-            dpp->samples_A [0] = bptr [-2];

-            dpp->samples_B [1] = bptr [-3];

-            dpp->samples_A [1] = bptr [-4];

-            break;

-

-        default:

-            for (bptr = buffer, tptr = buffer - (dpp->term * 2); bptr < eptr; bptr += 2, tptr += 2) {

-                bptr [0] = apply_weight (weight_A, tptr [0]) + (sam_A = bptr [0]);

-                update_weight (weight_A, delta, tptr [0], sam_A);

-

-                bptr [1] = apply_weight (weight_B, tptr [1]) + (sam_A = bptr [1]);

-                update_weight (weight_B, delta, tptr [1], sam_A);

-            }

-

-            for (k = dpp->term - 1, i = 8; i--; k--) {

-                dpp->samples_B [k & (MAX_TERM - 1)] = *--bptr;

-                dpp->samples_A [k & (MAX_TERM - 1)] = *--bptr;

-            }

-

-            break;

-

-        case -1:

-            for (bptr = buffer; bptr < eptr; bptr += 2) {

-                bptr [0] = apply_weight (weight_A, bptr [-1]) + (sam_A = bptr [0]);

-                update_weight_clip (weight_A, delta, bptr [-1], sam_A);

-                bptr [1] = apply_weight (weight_B, bptr [0]) + (sam_A = bptr [1]);

-                update_weight_clip (weight_B, delta, bptr [0], sam_A);

-            }

-

-            dpp->samples_A [0] = bptr [-1];

-            break;

-

-        case -2:

-            for (bptr = buffer; bptr < eptr; bptr += 2) {

-                bptr [1] = apply_weight (weight_B, bptr [-2]) + (sam_A = bptr [1]);

-                update_weight_clip (weight_B, delta, bptr [-2], sam_A);

-                bptr [0] = apply_weight (weight_A, bptr [1]) + (sam_A = bptr [0]);

-                update_weight_clip (weight_A, delta, bptr [1], sam_A);

-            }

-

-            dpp->samples_B [0] = bptr [-2];

-            break;

-

-        case -3:

-            for (bptr = buffer; bptr < eptr; bptr += 2) {

-                bptr [0] = apply_weight (weight_A, bptr [-1]) + (sam_A = bptr [0]);

-                update_weight_clip (weight_A, delta, bptr [-1], sam_A);

-                bptr [1] = apply_weight (weight_B, bptr [-2]) + (sam_A = bptr [1]);

-                update_weight_clip (weight_B, delta, bptr [-2], sam_A);

-            }

-

-            dpp->samples_A [0] = bptr [-1];

-            dpp->samples_B [0] = bptr [-2];

-            break;

-    }

-

-    dpp->weight_A = weight_A;

-    dpp->weight_B = weight_B;

-}

-

-#endif

-

-static void decorr_mono_pass (struct decorr_pass *dpp, int32_t *buffer, int32_t sample_count)

-{

-    int32_t delta = dpp->delta, weight_A = dpp->weight_A;

-    int32_t *bptr, *eptr = buffer + sample_count, sam_A;

-    int m, k;

-

-    switch (dpp->term) {

-

-        case 17:

-            for (bptr = buffer; bptr < eptr; bptr++) {

-                sam_A = 2 * dpp->samples_A [0] - dpp->samples_A [1];

-                dpp->samples_A [1] = dpp->samples_A [0];

-                dpp->samples_A [0] = apply_weight (weight_A, sam_A) + bptr [0];

-                update_weight (weight_A, delta, sam_A, bptr [0]);

-                bptr [0] = dpp->samples_A [0];

-            }

-

-            break;

-

-        case 18:

-            for (bptr = buffer; bptr < eptr; bptr++) {

-                sam_A = (3 * dpp->samples_A [0] - dpp->samples_A [1]) >> 1;

-                dpp->samples_A [1] = dpp->samples_A [0];

-                dpp->samples_A [0] = apply_weight (weight_A, sam_A) + bptr [0];

-                update_weight (weight_A, delta, sam_A, bptr [0]);

-                bptr [0] = dpp->samples_A [0];

-            }

-

-            break;

-

-        default:

-            for (m = 0, k = dpp->term & (MAX_TERM - 1), bptr = buffer; bptr < eptr; bptr++) {

-                sam_A = dpp->samples_A [m];

-                dpp->samples_A [k] = apply_weight (weight_A, sam_A) + bptr [0];

-                update_weight (weight_A, delta, sam_A, bptr [0]);

-                bptr [0] = dpp->samples_A [k];

-                m = (m + 1) & (MAX_TERM - 1);

-                k = (k + 1) & (MAX_TERM - 1);

-            }

-

-            if (m) {

-                int32_t temp_samples [MAX_TERM];

-

-                memcpy (temp_samples, dpp->samples_A, sizeof (dpp->samples_A));

-

-                for (k = 0; k < MAX_TERM; k++, m++)

-                    dpp->samples_A [k] = temp_samples [m & (MAX_TERM - 1)];

-            }

-

-            break;

-    }

-

-    dpp->weight_A = weight_A;

-}

-

-

-// This is a helper function for unpack_samples() that applies several final

-// operations. First, if the data is 32-bit float data, then that conversion

-// is done in the float.c module (whether lossy or lossless) and we return.

-// Otherwise, if the extended integer data applies, then that operation is

-// executed first. If the unpacked data is lossy (and not corrected) then

-// it is clipped and shifted in a single operation. Otherwise, if it's

-// lossless then the last step is to apply the final shift (if any).

-

-static void fixup_samples (WavpackStream *wps, int32_t *buffer, uint32_t sample_count)

-{

-    uint32_t flags = wps->wphdr.flags;

-    int shift = (flags & SHIFT_MASK) >> SHIFT_LSB;

-

-    if (flags & FLOAT_DATA) {

-        float_values (wps, buffer, (flags & MONO_FLAG) ? sample_count : sample_count * 2);

-        return;

-    }

-

-    if (flags & INT32_DATA) {

-        uint32_t count = (flags & MONO_FLAG) ? 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;

-        int32_t *dptr = buffer;

-

-        if (!(flags & HYBRID_FLAG) && !sent_bits && (zeros + ones + dups))

-            while (count--) {

-                if (zeros)

-                    *dptr <<= zeros;

-                else if (ones)

-                    *dptr = ((*dptr + 1) << ones) - 1;

-                else if (dups)

-                    *dptr = ((*dptr + (*dptr & 1)) << dups) - (*dptr & 1);

-

-                dptr++;

-            }

-        else

-            shift += zeros + sent_bits + ones + dups;

-    }

-

-    if (flags & HYBRID_FLAG) {

-        int32_t min_value, max_value, min_shifted, max_shifted;

-

-        switch (flags & BYTES_STORED) {

-            case 0:

-                min_shifted = (min_value = -128 >> shift) << shift;

-                max_shifted = (max_value = 127 >> shift) << shift;

-                break;

-

-            case 1:

-                min_shifted = (min_value = -32768 >> shift) << shift;

-                max_shifted = (max_value = 32767 >> shift) << shift;

-                break;

-

-            case 2:

-                min_shifted = (min_value = -8388608 >> shift) << shift;

-                max_shifted = (max_value = 8388607 >> shift) << shift;

-                break;

-

-            case 3:

-            default:

-                min_shifted = (min_value = (int32_t) 0x80000000 >> shift) << shift;

-                max_shifted = (max_value = (int32_t) 0x7FFFFFFF >> shift) << shift;

-                break;

-        }

-

-        if (!(flags & MONO_FLAG))

-            sample_count *= 2;

-

-        while (sample_count--) {

-            if (*buffer < min_value)

-                *buffer++ = min_shifted;

-            else if (*buffer > max_value)

-                *buffer++ = max_shifted;

-            else

-                *buffer++ <<= shift;

-        }

-    }

-    else if (shift) {

-        if (!(flags & MONO_FLAG))

-            sample_count *= 2;

-

-        while (sample_count--)

-            *buffer++ <<= shift;

-    }

-}

-

-// This function checks the crc value(s) for an unpacked block, returning the

-// number of actual crc errors detected for the block. The block must be

-// completely unpacked before this test is valid. For losslessly unpacked

-// blocks of float or extended integer data the extended crc is also checked.

-// Note that WavPack's crc is not a CCITT approved polynomial algorithm, but

-// is a much simpler method that is virtually as robust for real world data.

-

-int check_crc_error (WavpackContext *wpc)

-{

-    WavpackStream *wps = &wpc->stream;

-    int result = 0;

-

-    if (wps->crc != wps->wphdr.crc)

-        ++result;

-

-    return result;

-}

+////////////////////////////////////////////////////////////////////////////
+//                           **** WAVPACK ****                            //
+//                  Hybrid Lossless Wavefile Compressor                   //
+//              Copyright (c) 1998 - 2006 Conifer Software.               //
+//                          All Rights Reserved.                          //
+//      Distributed under the BSD Software License (see license.txt)      //
+////////////////////////////////////////////////////////////////////////////
+
+// unpack.c
+
+// This module actually handles the decompression of the audio data, except
+// for the entropy decoding which is handled by the words.c module. For
+// maximum efficiency, the conversion is isolated to tight loops that handle
+// an entire buffer.
+
+#include "wavpack.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#define LOSSY_MUTE
+
+///////////////////////////// executable code ////////////////////////////////
+
+// This function initializes everything required to unpack a WavPack block
+// and must be called before unpack_samples() is called to obtain audio data.
+// It is assumed that the WavpackHeader has been read into the wps->wphdr
+// (in the current WavpackStream). This is where all the metadata blocks are
+// scanned up to the one containing the audio bitstream.
+
+int unpack_init (WavpackContext *wpc)
+{
+    WavpackStream *wps = &wpc->stream;
+    WavpackMetadata wpmd;
+
+    if (wps->wphdr.block_samples && wps->wphdr.block_index != (uint32_t) -1)
+        wps->sample_index = wps->wphdr.block_index;
+
+    wps->mute_error = FALSE;
+    wps->crc = 0xffffffff;
+    CLEAR (wps->wvbits);
+    CLEAR (wps->decorr_passes);
+    CLEAR (wps->w);
+
+    while (read_metadata_buff (wpc, &wpmd)) {
+        if (!process_metadata (wpc, &wpmd)) {
+            strcpy (wpc->error_message, "invalid metadata!");
+            return FALSE;
+        }
+
+        if (wpmd.id == ID_WV_BITSTREAM)
+            break;
+    }
+
+    if (wps->wphdr.block_samples && !bs_is_open (&wps->wvbits)) {
+        strcpy (wpc->error_message, "invalid WavPack file!");
+        return FALSE;
+    }
+
+    if (wps->wphdr.block_samples) {
+        if ((wps->wphdr.flags & INT32_DATA) && wps->int32_sent_bits)
+            wpc->lossy_blocks = TRUE;
+
+        if ((wps->wphdr.flags & FLOAT_DATA) &&
+            wps->float_flags & (FLOAT_EXCEPTIONS | FLOAT_ZEROS_SENT | FLOAT_SHIFT_SENT | FLOAT_SHIFT_SAME))
+                wpc->lossy_blocks = TRUE;
+    }
+
+    return TRUE;
+}
+
+// This function initialzes the main bitstream for audio samples, which must
+// be in the "wv" file.
+
+int init_wv_bitstream (WavpackContext *wpc, WavpackMetadata *wpmd)
+{
+    WavpackStream *wps = &wpc->stream;
+
+    if (wpmd->data)
+        bs_open_read (&wps->wvbits, wpmd->data, (unsigned char *) wpmd->data + wpmd->byte_length, NULL, 0);
+    else if (wpmd->byte_length)
+        bs_open_read (&wps->wvbits, wpc->read_buffer, wpc->read_buffer + sizeof (wpc->read_buffer),
+            wpc->infile, wpmd->byte_length + (wpmd->byte_length & 1));
+
+    return TRUE;
+}
+
+// Read decorrelation terms from specified metadata block into the
+// decorr_passes array. The terms range from -3 to 8, plus 17 & 18;
+// other values are reserved and generate errors for now. The delta
+// ranges from 0 to 7 with all values valid. Note that the terms are
+// stored in the opposite order in the decorr_passes array compared
+// to packing.
+
+int read_decorr_terms (WavpackStream *wps, WavpackMetadata *wpmd)
+{
+    int termcnt = wpmd->byte_length;
+    uchar *byteptr = wpmd->data;
+    struct decorr_pass *dpp;
+
+    if (termcnt > MAX_NTERMS)
+        return FALSE;
+
+    wps->num_terms = termcnt;
+
+    for (dpp = wps->decorr_passes + termcnt - 1; termcnt--; dpp--) {
+        dpp->term = (int)(*byteptr & 0x1f) - 5;
+        dpp->delta = (*byteptr++ >> 5) & 0x7;
+
+        if (!dpp->term || dpp->term < -3 || (dpp->term > MAX_TERM && dpp->term < 17) || dpp->term > 18)
+            return FALSE;
+    }
+
+    return TRUE;
+}
+
+// Read decorrelation weights from specified metadata block into the
+// decorr_passes array. The weights range +/-1024, but are rounded and
+// truncated to fit in signed chars for metadata storage. Weights are
+// separate for the two channels and are specified from the "last" term
+// (first during encode). Unspecified weights are set to zero.
+
+int read_decorr_weights (WavpackStream *wps, WavpackMetadata *wpmd)
+{
+    int termcnt = wpmd->byte_length, tcount;
+    signed char *byteptr = wpmd->data;
+    struct decorr_pass *dpp;
+
+    if (!(wps->wphdr.flags & MONO_DATA))
+        termcnt /= 2;
+
+    if (termcnt > wps->num_terms)
+        return FALSE;
+
+    for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++)
+        dpp->weight_A = dpp->weight_B = 0;
+
+    while (--dpp >= wps->decorr_passes && termcnt--) {
+        dpp->weight_A = restore_weight (*byteptr++);
+
+        if (!(wps->wphdr.flags & MONO_DATA))
+            dpp->weight_B = restore_weight (*byteptr++);
+    }
+
+    return TRUE;
+}
+
+// Read decorrelation samples from specified metadata block into the
+// decorr_passes array. The samples are signed 32-bit values, but are
+// converted to signed log2 values for storage in metadata. Values are
+// stored for both channels and are specified from the "last" term
+// (first during encode) with unspecified samples set to zero. The
+// number of samples stored varies with the actual term value, so
+// those must obviously come first in the metadata.
+
+int read_decorr_samples (WavpackStream *wps, WavpackMetadata *wpmd)
+{
+    uchar *byteptr = wpmd->data;
+    uchar *endptr = byteptr + wpmd->byte_length;
+    struct decorr_pass *dpp;
+    int tcount;
+
+    for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++) {
+        CLEAR (dpp->samples_A);
+        CLEAR (dpp->samples_B);
+    }
+
+    if (wps->wphdr.version == 0x402 && (wps->wphdr.flags & HYBRID_FLAG)) {
+        byteptr += 2;
+
+        if (!(wps->wphdr.flags & MONO_DATA))
+            byteptr += 2;
+    }
+
+    while (dpp-- > wps->decorr_passes && byteptr < endptr)
+        if (dpp->term > MAX_TERM) {
+            dpp->samples_A [0] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8)));
+            dpp->samples_A [1] = exp2s ((short)(byteptr [2] + (byteptr [3] << 8)));
+            byteptr += 4;
+
+            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;
+            }
+        }
+        else if (dpp->term < 0) {
+            dpp->samples_A [0] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8)));
+            dpp->samples_B [0] = exp2s ((short)(byteptr [2] + (byteptr [3] << 8)));
+            byteptr += 4;
+        }
+        else {
+            int m = 0, cnt = dpp->term;
+
+            while (cnt--) {
+                dpp->samples_A [m] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8)));
+                byteptr += 2;
+
+                if (!(wps->wphdr.flags & MONO_DATA)) {
+                    dpp->samples_B [m] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8)));
+                    byteptr += 2;
+                }
+
+                m++;
+            }
+        }
+
+    return byteptr == endptr;
+}
+
+// Read the int32 data from the specified metadata into the specified stream.
+// This data is used for integer data that has more than 24 bits of magnitude
+// or, in some cases, used to eliminate redundant bits from any audio stream.
+
+int read_int32_info (WavpackStream *wps, WavpackMetadata *wpmd)
+{
+    int bytecnt = wpmd->byte_length;
+    char *byteptr = wpmd->data;
+
+    if (bytecnt != 4)
+        return FALSE;
+
+    wps->int32_sent_bits = *byteptr++;
+    wps->int32_zeros = *byteptr++;
+    wps->int32_ones = *byteptr++;
+    wps->int32_dups = *byteptr;
+    return TRUE;
+}
+
+// Read multichannel information from metadata. The first byte is the total
+// number of channels and the following bytes represent the channel_mask
+// as described for Microsoft WAVEFORMATEX.
+
+int read_channel_info (WavpackContext *wpc, WavpackMetadata *wpmd)
+{
+    int bytecnt = wpmd->byte_length, shift = 0;
+    char *byteptr = wpmd->data;
+    uint32_t mask = 0;
+
+    if (!bytecnt || bytecnt > 5)
+        return FALSE;
+
+    wpc->config.num_channels = *byteptr++;
+
+    while (--bytecnt) {
+        mask |= (uint32_t) *byteptr++ << shift;
+        shift += 8;
+    }
+
+    wpc->config.channel_mask = mask;
+    return TRUE;
+}
+
+// Read configuration information from metadata.
+
+int read_config_info (WavpackContext *wpc, WavpackMetadata *wpmd)
+{
+    int bytecnt = wpmd->byte_length;
+    uchar *byteptr = wpmd->data;
+
+    if (bytecnt >= 3) {
+        wpc->config.flags &= 0xff;
+        wpc->config.flags |= (int32_t) *byteptr++ << 8;
+        wpc->config.flags |= (int32_t) *byteptr++ << 16;
+        wpc->config.flags |= (int32_t) *byteptr << 24;
+    }
+
+    return TRUE;
+}
+
+// This monster actually unpacks the WavPack bitstream(s) into the specified
+// buffer as 32-bit integers or floats (depending on orignal data). Lossy
+// samples will be clipped to their original limits (i.e. 8-bit samples are
+// clipped to -128/+127) but are still returned in int32_ts. It is up to the
+// caller to potentially reformat this for the final output including any
+// multichannel distribution, block alignment or endian compensation. The
+// function unpack_init() must have been called and the entire WavPack block
+// must still be visible (although wps->blockbuff will not be accessed again).
+// For maximum clarity, the function is broken up into segments that handle
+// various modes. This makes for a few extra infrequent flag checks, but
+// makes the code easier to follow because the nesting does not become so
+// deep. For maximum efficiency, the conversion is isolated to tight loops
+// that handle an entire buffer. The function returns the total number of
+// samples unpacked, which can be less than the number requested if an error
+// occurs or the end of the block is reached.
+
+#if defined(CPU_COLDFIRE) && !defined(SIMULATOR)
+extern void decorr_stereo_pass_cont_mcf5249 (struct decorr_pass *dpp, int32_t *buffer, int32_t sample_count);
+#elif defined(CPU_ARM) && !defined(SIMULATOR)
+extern void decorr_stereo_pass_cont_arm (struct decorr_pass *dpp, int32_t *buffer, int32_t sample_count);
+extern void decorr_stereo_pass_cont_arml (struct decorr_pass *dpp, int32_t *buffer, int32_t sample_count);
+#else
+static void decorr_stereo_pass_cont (struct decorr_pass *dpp, int32_t *buffer, int32_t sample_count);
+#endif
+
+static void decorr_mono_pass (struct decorr_pass *dpp, int32_t *buffer, int32_t sample_count);
+static void decorr_stereo_pass (struct decorr_pass *dpp, int32_t *buffer, int32_t sample_count);
+static void fixup_samples (WavpackStream *wps, int32_t *buffer, uint32_t sample_count);
+
+int32_t unpack_samples (WavpackContext *wpc, int32_t *buffer, uint32_t sample_count)
+{
+    WavpackStream *wps = &wpc->stream;
+    uint32_t flags = wps->wphdr.flags, crc = wps->crc, i;
+    int32_t mute_limit = (1L << ((flags & MAG_MASK) >> MAG_LSB)) + 2;
+    struct decorr_pass *dpp;
+    int32_t *bptr, *eptr;
+    int tcount;
+
+    if (wps->sample_index + sample_count > wps->wphdr.block_index + wps->wphdr.block_samples)
+        sample_count = wps->wphdr.block_index + wps->wphdr.block_samples - wps->sample_index;
+
+    if (wps->mute_error) {
+        memset (buffer, 0, sample_count * (flags & MONO_FLAG ? 4 : 8));
+        wps->sample_index += sample_count;
+        return sample_count;
+    }
+
+    if (flags & HYBRID_FLAG)
+        mute_limit *= 2;
+
+    ///////////////////// handle version 4 mono data /////////////////////////
+
+    if (flags & MONO_DATA) {
+        eptr = buffer + sample_count;
+        i = get_words (buffer, sample_count, flags, &wps->w, &wps->wvbits);
+
+        for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++)
+            decorr_mono_pass (dpp, buffer, sample_count);
+
+        for (bptr = buffer; bptr < eptr; ++bptr) {
+            if (labs (bptr [0]) > mute_limit) {
+                i = bptr - buffer;
+                break;
+            }
+
+            crc = crc * 3 + bptr [0];
+        }
+    }
+
+    //////////////////// handle version 4 stereo data ////////////////////////
+
+    else {
+        eptr = buffer + (sample_count * 2);
+        i = get_words (buffer, sample_count, flags, &wps->w, &wps->wvbits);
+
+        if (sample_count < 16)
+            for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++)
+                decorr_stereo_pass (dpp, buffer, sample_count);
+        else
+            for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++) {
+                decorr_stereo_pass (dpp, buffer, 8);
+#if defined(CPU_COLDFIRE) && !defined(SIMULATOR)
+                decorr_stereo_pass_cont_mcf5249 (dpp, buffer + 16, sample_count - 8);
+#elif defined(CPU_ARM) && !defined(SIMULATOR)
+                if (((flags & MAG_MASK) >> MAG_LSB) > 15)
+                    decorr_stereo_pass_cont_arml (dpp, buffer + 16, sample_count - 8);
+                else
+                    decorr_stereo_pass_cont_arm (dpp, buffer + 16, sample_count - 8);
+#else
+                decorr_stereo_pass_cont (dpp, buffer + 16, sample_count - 8);
+#endif
+            }
+
+        if (flags & JOINT_STEREO)
+            for (bptr = buffer; bptr < eptr; bptr += 2) {
+                bptr [0] += (bptr [1] -= (bptr [0] >> 1));
+
+                if (labs (bptr [0]) > mute_limit || labs (bptr [1]) > mute_limit) {
+                    i = (bptr - buffer) / 2;
+                    break;
+                }
+
+                crc = (crc * 3 + bptr [0]) * 3 + bptr [1];
+            }
+        else
+            for (bptr = buffer; bptr < eptr; bptr += 2) {
+                if (labs (bptr [0]) > mute_limit || labs (bptr [1]) > mute_limit) {
+                    i = (bptr - buffer) / 2;
+                    break;
+                }
+
+                crc = (crc * 3 + bptr [0]) * 3 + bptr [1];
+            }
+    }
+
+    if (i != sample_count) {
+        memset (buffer, 0, sample_count * (flags & MONO_FLAG ? 4 : 8));
+        wps->mute_error = TRUE;
+        i = sample_count;
+    }
+
+    fixup_samples (wps, buffer, i);
+
+    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;
+
+    return i;
+}
+
+static void decorr_stereo_pass (struct decorr_pass *dpp, int32_t *buffer, int32_t sample_count)
+{
+    int32_t delta = dpp->delta, weight_A = dpp->weight_A, weight_B = dpp->weight_B;
+    int32_t *bptr, *eptr = buffer + (sample_count * 2), sam_A, sam_B;
+    int m, k;
+
+    switch (dpp->term) {
+
+        case 17:
+            for (bptr = buffer; bptr < eptr; bptr += 2) {
+                sam_A = 2 * dpp->samples_A [0] - dpp->samples_A [1];
+                dpp->samples_A [1] = dpp->samples_A [0];
+                dpp->samples_A [0] = apply_weight (weight_A, sam_A) + bptr [0];
+                update_weight (weight_A, delta, sam_A, bptr [0]);
+                bptr [0] = dpp->samples_A [0];
+
+                sam_A = 2 * dpp->samples_B [0] - dpp->samples_B [1];
+                dpp->samples_B [1] = dpp->samples_B [0];
+                dpp->samples_B [0] = apply_weight (weight_B, sam_A) + bptr [1];
+                update_weight (weight_B, delta, sam_A, bptr [1]);
+                bptr [1] = dpp->samples_B [0];
+            }
+
+            break;
+
+        case 18:
+            for (bptr = buffer; bptr < eptr; bptr += 2) {
+                sam_A = (3 * dpp->samples_A [0] - dpp->samples_A [1]) >> 1;
+                dpp->samples_A [1] = dpp->samples_A [0];
+                dpp->samples_A [0] = apply_weight (weight_A, sam_A) + bptr [0];
+                update_weight (weight_A, delta, sam_A, bptr [0]);
+                bptr [0] = dpp->samples_A [0];
+
+                sam_A = (3 * dpp->samples_B [0] - dpp->samples_B [1]) >> 1;
+                dpp->samples_B [1] = dpp->samples_B [0];
+                dpp->samples_B [0] = apply_weight (weight_B, sam_A) + bptr [1];
+                update_weight (weight_B, delta, sam_A, bptr [1]);
+                bptr [1] = dpp->samples_B [0];
+            }
+
+            break;
+
+        default:
+            for (m = 0, k = dpp->term & (MAX_TERM - 1), bptr = buffer; bptr < eptr; bptr += 2) {
+                sam_A = dpp->samples_A [m];
+                dpp->samples_A [k] = apply_weight (weight_A, sam_A) + bptr [0];
+                update_weight (weight_A, delta, sam_A, bptr [0]);
+                bptr [0] = dpp->samples_A [k];
+
+                sam_A = dpp->samples_B [m];
+                dpp->samples_B [k] = apply_weight (weight_B, sam_A) + bptr [1];
+                update_weight (weight_B, delta, sam_A, bptr [1]);
+                bptr [1] = dpp->samples_B [k];
+
+                m = (m + 1) & (MAX_TERM - 1);
+                k = (k + 1) & (MAX_TERM - 1);
+            }
+
+            if (m) {
+                int32_t temp_samples [MAX_TERM];
+
+                memcpy (temp_samples, dpp->samples_A, sizeof (dpp->samples_A));
+
+                for (k = 0; k < MAX_TERM; k++, m++)
+                    dpp->samples_A [k] = temp_samples [m & (MAX_TERM - 1)];
+
+                memcpy (temp_samples, dpp->samples_B, sizeof (dpp->samples_B));
+
+                for (k = 0; k < MAX_TERM; k++, m++)
+                    dpp->samples_B [k] = temp_samples [m & (MAX_TERM - 1)];
+            }
+
+            break;
+
+        case -1:
+            for (bptr = buffer; bptr < eptr; bptr += 2) {
+                sam_A = bptr [0] + apply_weight (weight_A, dpp->samples_A [0]);
+                update_weight_clip (weight_A, delta, dpp->samples_A [0], bptr [0]);
+                bptr [0] = sam_A;
+                dpp->samples_A [0] = bptr [1] + apply_weight (weight_B, sam_A);
+                update_weight_clip (weight_B, delta, sam_A, bptr [1]);
+                bptr [1] = dpp->samples_A [0];
+            }
+
+            break;
+
+        case -2:
+            for (bptr = buffer; bptr < eptr; bptr += 2) {
+                sam_B = bptr [1] + apply_weight (weight_B, dpp->samples_B [0]);
+                update_weight_clip (weight_B, delta, dpp->samples_B [0], bptr [1]);
+                bptr [1] = sam_B;
+                dpp->samples_B [0] = bptr [0] + apply_weight (weight_A, sam_B);
+                update_weight_clip (weight_A, delta, sam_B, bptr [0]);
+                bptr [0] = dpp->samples_B [0];
+            }
+
+            break;
+
+        case -3:
+            for (bptr = buffer; bptr < eptr; bptr += 2) {
+                sam_A = bptr [0] + apply_weight (weight_A, dpp->samples_A [0]);
+                update_weight_clip (weight_A, delta, dpp->samples_A [0], bptr [0]);
+                sam_B = bptr [1] + apply_weight (weight_B, dpp->samples_B [0]);
+                update_weight_clip (weight_B, delta, dpp->samples_B [0], bptr [1]);
+                bptr [0] = dpp->samples_B [0] = sam_A;
+                bptr [1] = dpp->samples_A [0] = sam_B;
+            }
+
+            break;
+    }
+
+    dpp->weight_A = weight_A;
+    dpp->weight_B = weight_B;
+}
+
+#if (!defined(CPU_COLDFIRE) && !defined(CPU_ARM)) || defined(SIMULATOR)
+
+static void decorr_stereo_pass_cont (struct decorr_pass *dpp, int32_t *buffer, int32_t sample_count)
+{
+    int32_t delta = dpp->delta, weight_A = dpp->weight_A, weight_B = dpp->weight_B;
+    int32_t *bptr, *tptr, *eptr = buffer + (sample_count * 2), sam_A, sam_B;
+    int k, i;
+
+    switch (dpp->term) {
+
+        case 17:
+            for (bptr = buffer; bptr < eptr; bptr += 2) {
+                sam_A = 2 * bptr [-2] - bptr [-4];
+                bptr [0] = apply_weight (weight_A, sam_A) + (sam_B = bptr [0]);
+                update_weight (weight_A, delta, sam_A, sam_B);
+
+                sam_A = 2 * bptr [-1] - bptr [-3];
+                bptr [1] = apply_weight (weight_B, sam_A) + (sam_B = bptr [1]);
+                update_weight (weight_B, delta, sam_A, sam_B);
+            }
+
+            dpp->samples_B [0] = bptr [-1];
+            dpp->samples_A [0] = bptr [-2];
+            dpp->samples_B [1] = bptr [-3];
+            dpp->samples_A [1] = bptr [-4];
+            break;
+
+        case 18:
+            for (bptr = buffer; bptr < eptr; bptr += 2) {
+                sam_A = (3 * bptr [-2] - bptr [-4]) >> 1;
+                bptr [0] = apply_weight (weight_A, sam_A) + (sam_B = bptr [0]);
+                update_weight (weight_A, delta, sam_A, sam_B);
+
+                sam_A = (3 * bptr [-1] - bptr [-3]) >> 1;
+                bptr [1] = apply_weight (weight_B, sam_A) + (sam_B = bptr [1]);
+                update_weight (weight_B, delta, sam_A, sam_B);
+            }
+
+            dpp->samples_B [0] = bptr [-1];
+            dpp->samples_A [0] = bptr [-2];
+            dpp->samples_B [1] = bptr [-3];
+            dpp->samples_A [1] = bptr [-4];
+            break;
+
+        default:
+            for (bptr = buffer, tptr = buffer - (dpp->term * 2); bptr < eptr; bptr += 2, tptr += 2) {
+                bptr [0] = apply_weight (weight_A, tptr [0]) + (sam_A = bptr [0]);
+                update_weight (weight_A, delta, tptr [0], sam_A);
+
+                bptr [1] = apply_weight (weight_B, tptr [1]) + (sam_A = bptr [1]);
+                update_weight (weight_B, delta, tptr [1], sam_A);
+            }
+
+            for (k = dpp->term - 1, i = 8; i--; k--) {
+                dpp->samples_B [k & (MAX_TERM - 1)] = *--bptr;
+                dpp->samples_A [k & (MAX_TERM - 1)] = *--bptr;
+            }
+
+            break;
+
+        case -1:
+            for (bptr = buffer; bptr < eptr; bptr += 2) {
+                bptr [0] = apply_weight (weight_A, bptr [-1]) + (sam_A = bptr [0]);
+                update_weight_clip (weight_A, delta, bptr [-1], sam_A);
+                bptr [1] = apply_weight (weight_B, bptr [0]) + (sam_A = bptr [1]);
+                update_weight_clip (weight_B, delta, bptr [0], sam_A);
+            }
+
+            dpp->samples_A [0] = bptr [-1];
+            break;
+
+        case -2:
+            for (bptr = buffer; bptr < eptr; bptr += 2) {
+                bptr [1] = apply_weight (weight_B, bptr [-2]) + (sam_A = bptr [1]);
+                update_weight_clip (weight_B, delta, bptr [-2], sam_A);
+                bptr [0] = apply_weight (weight_A, bptr [1]) + (sam_A = bptr [0]);
+                update_weight_clip (weight_A, delta, bptr [1], sam_A);
+            }
+
+            dpp->samples_B [0] = bptr [-2];
+            break;
+
+        case -3:
+            for (bptr = buffer; bptr < eptr; bptr += 2) {
+                bptr [0] = apply_weight (weight_A, bptr [-1]) + (sam_A = bptr [0]);
+                update_weight_clip (weight_A, delta, bptr [-1], sam_A);
+                bptr [1] = apply_weight (weight_B, bptr [-2]) + (sam_A = bptr [1]);
+                update_weight_clip (weight_B, delta, bptr [-2], sam_A);
+            }
+
+            dpp->samples_A [0] = bptr [-1];
+            dpp->samples_B [0] = bptr [-2];
+            break;
+    }
+
+    dpp->weight_A = weight_A;
+    dpp->weight_B = weight_B;
+}
+
+#endif
+
+static void decorr_mono_pass (struct decorr_pass *dpp, int32_t *buffer, int32_t sample_count)
+{
+    int32_t delta = dpp->delta, weight_A = dpp->weight_A;
+    int32_t *bptr, *eptr = buffer + sample_count, sam_A;
+    int m, k;
+
+    switch (dpp->term) {
+
+        case 17:
+            for (bptr = buffer; bptr < eptr; bptr++) {
+                sam_A = 2 * dpp->samples_A [0] - dpp->samples_A [1];
+                dpp->samples_A [1] = dpp->samples_A [0];
+                dpp->samples_A [0] = apply_weight (weight_A, sam_A) + bptr [0];
+                update_weight (weight_A, delta, sam_A, bptr [0]);
+                bptr [0] = dpp->samples_A [0];
+            }
+
+            break;
+
+        case 18:
+            for (bptr = buffer; bptr < eptr; bptr++) {
+                sam_A = (3 * dpp->samples_A [0] - dpp->samples_A [1]) >> 1;
+                dpp->samples_A [1] = dpp->samples_A [0];
+                dpp->samples_A [0] = apply_weight (weight_A, sam_A) + bptr [0];
+                update_weight (weight_A, delta, sam_A, bptr [0]);
+                bptr [0] = dpp->samples_A [0];
+            }
+
+            break;
+
+        default:
+            for (m = 0, k = dpp->term & (MAX_TERM - 1), bptr = buffer; bptr < eptr; bptr++) {
+                sam_A = dpp->samples_A [m];
+                dpp->samples_A [k] = apply_weight (weight_A, sam_A) + bptr [0];
+                update_weight (weight_A, delta, sam_A, bptr [0]);
+                bptr [0] = dpp->samples_A [k];
+                m = (m + 1) & (MAX_TERM - 1);
+                k = (k + 1) & (MAX_TERM - 1);
+            }
+
+            if (m) {
+                int32_t temp_samples [MAX_TERM];
+
+                memcpy (temp_samples, dpp->samples_A, sizeof (dpp->samples_A));
+
+                for (k = 0; k < MAX_TERM; k++, m++)
+                    dpp->samples_A [k] = temp_samples [m & (MAX_TERM - 1)];
+            }
+
+            break;
+    }
+
+    dpp->weight_A = weight_A;
+}
+
+
+// This is a helper function for unpack_samples() that applies several final
+// operations. First, if the data is 32-bit float data, then that conversion
+// is done in the float.c module (whether lossy or lossless) and we return.
+// Otherwise, if the extended integer data applies, then that operation is
+// executed first. If the unpacked data is lossy (and not corrected) then
+// it is clipped and shifted in a single operation. Otherwise, if it's
+// lossless then the last step is to apply the final shift (if any).
+
+static void fixup_samples (WavpackStream *wps, int32_t *buffer, uint32_t sample_count)
+{
+    uint32_t flags = wps->wphdr.flags;
+    int shift = (flags & SHIFT_MASK) >> SHIFT_LSB;
+
+    if (flags & FLOAT_DATA) {
+        float_values (wps, buffer, (flags & MONO_FLAG) ? sample_count : sample_count * 2);
+        return;
+    }
+
+    if (flags & INT32_DATA) {
+        uint32_t count = (flags & MONO_FLAG) ? 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;
+        int32_t *dptr = buffer;
+
+        if (!(flags & HYBRID_FLAG) && !sent_bits && (zeros + ones + dups))
+            while (count--) {
+                if (zeros)
+                    *dptr <<= zeros;
+                else if (ones)
+                    *dptr = ((*dptr + 1) << ones) - 1;
+                else if (dups)
+                    *dptr = ((*dptr + (*dptr & 1)) << dups) - (*dptr & 1);
+
+                dptr++;
+            }
+        else
+            shift += zeros + sent_bits + ones + dups;
+    }
+
+    if (flags & HYBRID_FLAG) {
+        int32_t min_value, max_value, min_shifted, max_shifted;
+
+        switch (flags & BYTES_STORED) {
+            case 0:
+                min_shifted = (min_value = -128 >> shift) << shift;
+                max_shifted = (max_value = 127 >> shift) << shift;
+                break;
+
+            case 1:
+                min_shifted = (min_value = -32768 >> shift) << shift;
+                max_shifted = (max_value = 32767 >> shift) << shift;
+                break;
+
+            case 2:
+                min_shifted = (min_value = -8388608 >> shift) << shift;
+                max_shifted = (max_value = 8388607 >> shift) << shift;
+                break;
+
+            case 3:
+            default:
+                min_shifted = (min_value = (int32_t) 0x80000000 >> shift) << shift;
+                max_shifted = (max_value = (int32_t) 0x7FFFFFFF >> shift) << shift;
+                break;
+        }
+
+        if (!(flags & MONO_FLAG))
+            sample_count *= 2;
+
+        while (sample_count--) {
+            if (*buffer < min_value)
+                *buffer++ = min_shifted;
+            else if (*buffer > max_value)
+                *buffer++ = max_shifted;
+            else
+                *buffer++ <<= shift;
+        }
+    }
+    else if (shift) {
+        if (!(flags & MONO_FLAG))
+            sample_count *= 2;
+
+        while (sample_count--)
+            *buffer++ <<= shift;
+    }
+}
+
+// This function checks the crc value(s) for an unpacked block, returning the
+// number of actual crc errors detected for the block. The block must be
+// completely unpacked before this test is valid. For losslessly unpacked
+// blocks of float or extended integer data the extended crc is also checked.
+// Note that WavPack's crc is not a CCITT approved polynomial algorithm, but
+// is a much simpler method that is virtually as robust for real world data.
+
+int check_crc_error (WavpackContext *wpc)
+{
+    WavpackStream *wps = &wpc->stream;
+    int result = 0;
+
+    if (wps->crc != wps->wphdr.crc)
+        ++result;
+
+    return result;
+}