summaryrefslogtreecommitdiff
path: root/apps/codecs/libwavpack
diff options
context:
space:
mode:
authorChristian Gmeiner <christian.gmeiner@gmail.com>2005-02-25 17:05:30 +0000
committerChristian Gmeiner <christian.gmeiner@gmail.com>2005-02-25 17:05:30 +0000
commite449d88b3e6b584998f8f38ed61467c35ca74466 (patch)
tree307e87242fd5fbf45d7424bb5afad17b9dd34429 /apps/codecs/libwavpack
parent234489a449e13d99b76daff61ff7774226d21a5b (diff)
downloadrockbox-e449d88b3e6b584998f8f38ed61467c35ca74466.tar.gz
rockbox-e449d88b3e6b584998f8f38ed61467c35ca74466.zip
Initial import of libwavpack
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@6056 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/codecs/libwavpack')
-rw-r--r--apps/codecs/libwavpack/LICENSE25
-rw-r--r--apps/codecs/libwavpack/README52
-rw-r--r--apps/codecs/libwavpack/README.rockbox15
-rw-r--r--apps/codecs/libwavpack/SOURCES6
-rw-r--r--apps/codecs/libwavpack/bits.c140
-rw-r--r--apps/codecs/libwavpack/float.c83
-rw-r--r--apps/codecs/libwavpack/make.bat1
-rw-r--r--apps/codecs/libwavpack/metadata.c105
-rw-r--r--apps/codecs/libwavpack/unpack.c576
-rw-r--r--apps/codecs/libwavpack/wavpack.h330
-rw-r--r--apps/codecs/libwavpack/words.c503
-rw-r--r--apps/codecs/libwavpack/wputils.c354
12 files changed, 2190 insertions, 0 deletions
diff --git a/apps/codecs/libwavpack/LICENSE b/apps/codecs/libwavpack/LICENSE
new file mode 100644
index 0000000000..3ee485817d
--- /dev/null
+++ b/apps/codecs/libwavpack/LICENSE
@@ -0,0 +1,25 @@
1 Copyright (c) 1998 - 2004 Conifer Software
2 All rights reserved.
3
4Redistribution and use in source and binary forms, with or without
5modification, are permitted provided that the following conditions are met:
6
7 * Redistributions of source code must retain the above copyright notice,
8 this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright notice,
10 this list of conditions and the following disclaimer in the
11 documentation and/or other materials provided with the distribution.
12 * Neither the name of Conifer Software nor the names of its contributors
13 may be used to endorse or promote products derived from this software
14 without specific prior written permission.
15
16THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
20ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/apps/codecs/libwavpack/README b/apps/codecs/libwavpack/README
new file mode 100644
index 0000000000..b373235e1c
--- /dev/null
+++ b/apps/codecs/libwavpack/README
@@ -0,0 +1,52 @@
1////////////////////////////////////////////////////////////////////////////
2// **** WAVPACK **** //
3// Hybrid Lossless Wavefile Compressor //
4// Copyright (c) 1998 - 2004 Conifer Software. //
5// All Rights Reserved. //
6// Distributed under the BSD Software License (see license.txt) //
7////////////////////////////////////////////////////////////////////////////
8
9This package contains a tiny version of the WavPack 4.0 decoder that might
10be used in a "resource limited" CPU environment or form the basis for a
11hardware decoding implementation. It is packaged with a demo command-line
12program that accepts a WavPack audio file on stdin and outputs a RIFF wav
13file to stdout. The program is standard C, and a win32 executable is
14included which was compiled under MS Visual C++ 6.0 using this command:
15
16cl /O1 /DWIN32 wvfilter.c wputils.c unpack.c float.c metadata.c words.c bits.c
17
18WavPack data is read with a stream reading callback. No direct seeking is
19provided for, but it is possible to start decoding anywhere in a WavPack
20stream. In this case, WavPack will be able to provide the sample-accurate
21position when it synchs with the data and begins decoding.
22
23For demonstration purposes this uses a single static copy of the
24WavpackContext structure, so obviously it cannot be used for more than one
25file at a time. Also, this decoder will not handle "correction" files, plays
26only the first two channels of multi-channel files, and is limited in
27resolution in some large integer or floating point files (but always
28provides at least 24 bits of resolution). It also will not accept WavPack
29files from before version 4.0.
30
31To make this code viable on the greatest number of hardware platforms, the
32following are true:
33
34 speed is about 4x realtime on an AMD K6 300 MHz
35 ("high" mode 16/44 stereo; normal mode is about twice that fast)
36
37 no floating-point math required; just 32b * 32b = 32b int multiply
38
39 large data areas are static and less than 4K total
40 executable code and tables are less than 32K
41 no malloc / free usage
42
43To maintain compatibility on various platforms, the following conventions
44are used:
45
46 a "short" must be 16-bits
47 a "long" must be 32-bits
48 an "int" must be at least 16-bits, but may be larger
49 a "char" must default to signed
50
51
52Questions or comments should be directed to david@wavpack.com
diff --git a/apps/codecs/libwavpack/README.rockbox b/apps/codecs/libwavpack/README.rockbox
new file mode 100644
index 0000000000..a74b0c511c
--- /dev/null
+++ b/apps/codecs/libwavpack/README.rockbox
@@ -0,0 +1,15 @@
1Library: wavpack - Release 4.1 - September 14, 2004
2Imported: 2005-02-25 by Christian Gmeiner
3
4
5This directory contains a "tiny" decoder version of wavpack for version 4.x.
6
7LICENSING INFORMATION
8
9wavpack is released under the BSD License as described
10in the LICENSE file in this directory.
11
12
13IMPORT DETAILS
14
15Excluded is wvfilter.c, because it is only a test programm.
diff --git a/apps/codecs/libwavpack/SOURCES b/apps/codecs/libwavpack/SOURCES
new file mode 100644
index 0000000000..9b79d70b22
--- /dev/null
+++ b/apps/codecs/libwavpack/SOURCES
@@ -0,0 +1,6 @@
1bits.c
2float.c
3metadata.c
4unpack.c
5words.c
6wputils.c \ No newline at end of file
diff --git a/apps/codecs/libwavpack/bits.c b/apps/codecs/libwavpack/bits.c
new file mode 100644
index 0000000000..25a222780f
--- /dev/null
+++ b/apps/codecs/libwavpack/bits.c
@@ -0,0 +1,140 @@
1////////////////////////////////////////////////////////////////////////////
2// **** WAVPACK **** //
3// Hybrid Lossless Wavefile Compressor //
4// Copyright (c) 1998 - 2004 Conifer Software. //
5// All Rights Reserved. //
6// Distributed under the BSD Software License (see license.txt) //
7////////////////////////////////////////////////////////////////////////////
8
9// bits.c
10
11// This module provides utilities to support the BitStream structure which is
12// used to read and write all WavPack audio data streams. It also contains a
13// wrapper for the stream I/O functions and a set of functions dealing with
14// endian-ness, both for enhancing portability. Finally, a debug wrapper for
15// the malloc() system is provided.
16
17#include "wavpack.h"
18
19#include <string.h>
20#include <ctype.h>
21
22////////////////////////// Bitstream functions ////////////////////////////////
23
24// Open the specified BitStream and associate with the specified buffer.
25
26static void bs_read (Bitstream *bs);
27
28void bs_open_read (Bitstream *bs, uchar *buffer_start, uchar *buffer_end, read_stream file, ulong file_bytes)
29{
30 CLEAR (*bs);
31 bs->buf = buffer_start;
32 bs->end = buffer_end;
33
34 if (file) {
35 bs->ptr = bs->end - 1;
36 bs->file_bytes = file_bytes;
37 bs->file = file;
38 }
39 else
40 bs->ptr = bs->buf - 1;
41
42 bs->wrap = bs_read;
43}
44
45// This function is only called from the getbit() and getbits() macros when
46// the BitStream has been exhausted and more data is required. Sinve these
47// bistreams no longer access files, this function simple sets an error and
48// resets the buffer.
49
50static void bs_read (Bitstream *bs)
51{
52 if (bs->file && bs->file_bytes) {
53 ulong bytes_read, bytes_to_read = bs->end - bs->buf;
54
55 if (bytes_to_read > bs->file_bytes)
56 bytes_to_read = bs->file_bytes;
57
58 bytes_read = bs->file (bs->buf, bytes_to_read);
59
60 if (bytes_read) {
61 bs->end = bs->buf + bytes_read;
62 bs->file_bytes -= bytes_read;
63 }
64 else {
65 memset (bs->buf, -1, bs->end - bs->buf);
66 bs->error = 1;
67 }
68 }
69 else
70 bs->error = 1;
71
72 if (bs->error)
73 memset (bs->buf, -1, bs->end - bs->buf);
74
75 bs->ptr = bs->buf;
76}
77
78/////////////////////// Endian Correction Routines ////////////////////////////
79
80void little_endian_to_native (void *data, char *format)
81{
82 uchar *cp = (uchar *) data;
83 long temp;
84
85 while (*format) {
86 switch (*format) {
87 case 'L':
88 temp = cp [0] + ((long) cp [1] << 8) + ((long) cp [2] << 16) + ((long) cp [3] << 24);
89 * (long *) cp = temp;
90 cp += 4;
91 break;
92
93 case 'S':
94 temp = cp [0] + (cp [1] << 8);
95 * (short *) cp = (short) temp;
96 cp += 2;
97 break;
98
99 default:
100 if (isdigit (*format))
101 cp += *format - '0';
102
103 break;
104 }
105
106 format++;
107 }
108}
109
110void native_to_little_endian (void *data, char *format)
111{
112 uchar *cp = (uchar *) data;
113 long temp;
114
115 while (*format) {
116 switch (*format) {
117 case 'L':
118 temp = * (long *) cp;
119 *cp++ = (uchar) temp;
120 *cp++ = (uchar) (temp >> 8);
121 *cp++ = (uchar) (temp >> 16);
122 *cp++ = (uchar) (temp >> 24);
123 break;
124
125 case 'S':
126 temp = * (short *) cp;
127 *cp++ = (uchar) temp;
128 *cp++ = (uchar) (temp >> 8);
129 break;
130
131 default:
132 if (isdigit (*format))
133 cp += *format - '0';
134
135 break;
136 }
137
138 format++;
139 }
140}
diff --git a/apps/codecs/libwavpack/float.c b/apps/codecs/libwavpack/float.c
new file mode 100644
index 0000000000..3e678e824d
--- /dev/null
+++ b/apps/codecs/libwavpack/float.c
@@ -0,0 +1,83 @@
1////////////////////////////////////////////////////////////////////////////
2// **** WAVPACK **** //
3// Hybrid Lossless Wavefile Compressor //
4// Copyright (c) 1998 - 2004 Conifer Software. //
5// All Rights Reserved. //
6// Distributed under the BSD Software License (see license.txt) //
7////////////////////////////////////////////////////////////////////////////
8
9// float.c
10
11#include "wavpack.h"
12
13int read_float_info (WavpackStream *wps, WavpackMetadata *wpmd)
14{
15 int bytecnt = wpmd->byte_length;
16 char *byteptr = wpmd->data;
17
18 if (bytecnt != 4)
19 return FALSE;
20
21 wps->float_flags = *byteptr++;
22 wps->float_shift = *byteptr++;
23 wps->float_max_exp = *byteptr++;
24 wps->float_norm_exp = *byteptr;
25 return TRUE;
26}
27
28void float_values (WavpackStream *wps, long *values, long num_values)
29{
30 while (num_values--) {
31 int shift_count = 0, exp = wps->float_max_exp;
32 f32 outval = { 0, 0, 0 };
33
34 if (*values) {
35 *values <<= wps->float_shift;
36
37 if (*values < 0) {
38 *values = -*values;
39 outval.sign = 1;
40 }
41
42 if (*values == 0x1000000)
43 outval.exponent = 255;
44 else {
45 if (exp)
46 while (!(*values & 0x800000) && --exp) {
47 shift_count++;
48 *values <<= 1;
49 }
50
51 if (shift_count && (wps->float_flags & FLOAT_SHIFT_ONES))
52 *values |= ((1 << shift_count) - 1);
53
54 outval.mantissa = *values;
55 outval.exponent = exp;
56 }
57 }
58
59 * (f32 *) values++ = outval;
60 }
61}
62
63void float_normalize (long *values, long num_values, int delta_exp)
64{
65 f32 *fvalues = (f32 *) values, fzero = { 0, 0, 0 };
66 int exp;
67
68 if (!delta_exp)
69 return;
70
71 while (num_values--) {
72 if ((exp = fvalues->exponent) == 0 || exp + delta_exp <= 0)
73 *fvalues = fzero;
74 else if (exp == 255 || (exp += delta_exp) >= 255) {
75 fvalues->exponent = 255;
76 fvalues->mantissa = 0;
77 }
78 else
79 fvalues->exponent = exp;
80
81 fvalues++;
82 }
83}
diff --git a/apps/codecs/libwavpack/make.bat b/apps/codecs/libwavpack/make.bat
new file mode 100644
index 0000000000..0ca72d7e55
--- /dev/null
+++ b/apps/codecs/libwavpack/make.bat
@@ -0,0 +1 @@
cl /O1 /DWIN32 wvfilter.c wputils.c unpack.c float.c metadata.c words.c bits.c
diff --git a/apps/codecs/libwavpack/metadata.c b/apps/codecs/libwavpack/metadata.c
new file mode 100644
index 0000000000..40ede99cd4
--- /dev/null
+++ b/apps/codecs/libwavpack/metadata.c
@@ -0,0 +1,105 @@
1////////////////////////////////////////////////////////////////////////////
2// **** WAVPACK **** //
3// Hybrid Lossless Wavefile Compressor //
4// Copyright (c) 1998 - 2003 Conifer Software. //
5// All Rights Reserved. //
6// Distributed under the BSD Software License (see license.txt) //
7////////////////////////////////////////////////////////////////////////////
8
9// metadata.c
10
11// This module handles the metadata structure introduced in WavPack 4.0
12
13#include "wavpack.h"
14
15int read_metadata_buff (WavpackContext *wpc, WavpackMetadata *wpmd)
16{
17 uchar tchar;
18
19 if (!wpc->infile (&wpmd->id, 1) || !wpc->infile (&tchar, 1))
20 return FALSE;
21
22 wpmd->byte_length = tchar << 1;
23
24 if (wpmd->id & ID_LARGE) {
25 wpmd->id &= ~ID_LARGE;
26
27 if (!wpc->infile (&tchar, 1))
28 return FALSE;
29
30 wpmd->byte_length += (long) tchar << 9;
31
32 if (!wpc->infile (&tchar, 1))
33 return FALSE;
34
35 wpmd->byte_length += (long) tchar << 17;
36 }
37
38 if (wpmd->id & ID_ODD_SIZE) {
39 wpmd->id &= ~ID_ODD_SIZE;
40 wpmd->byte_length--;
41 }
42
43 if (wpmd->byte_length && wpmd->byte_length <= sizeof (wpc->read_buffer)) {
44 ulong bytes_to_read = wpmd->byte_length + (wpmd->byte_length & 1);
45
46 if (wpc->infile (wpc->read_buffer, bytes_to_read) != (long) bytes_to_read) {
47 wpmd->data = NULL;
48 return FALSE;
49 }
50
51 wpmd->data = wpc->read_buffer;
52 }
53 else
54 wpmd->data = NULL;
55
56 return TRUE;
57}
58
59int process_metadata (WavpackContext *wpc, WavpackMetadata *wpmd)
60{
61 WavpackStream *wps = &wpc->stream;
62
63 switch (wpmd->id) {
64 case ID_DUMMY:
65 return TRUE;
66
67 case ID_DECORR_TERMS:
68 return read_decorr_terms (wps, wpmd);
69
70 case ID_DECORR_WEIGHTS:
71 return read_decorr_weights (wps, wpmd);
72
73 case ID_DECORR_SAMPLES:
74 return read_decorr_samples (wps, wpmd);
75
76 case ID_ENTROPY_VARS:
77 return read_entropy_vars (wps, wpmd);
78
79 case ID_HYBRID_PROFILE:
80 return read_hybrid_profile (wps, wpmd);
81
82 case ID_FLOAT_INFO:
83 return read_float_info (wps, wpmd);
84
85 case ID_INT32_INFO:
86 return read_int32_info (wps, wpmd);
87
88 case ID_CHANNEL_INFO:
89 return read_channel_info (wpc, wpmd);
90
91 case ID_CONFIG_BLOCK:
92 return read_config_info (wpc, wpmd);
93
94 case ID_WV_BITSTREAM:
95 return init_wv_bitstream (wpc, wpmd);
96
97 case ID_SHAPING_WEIGHTS:
98 case ID_WVC_BITSTREAM:
99 case ID_WVX_BITSTREAM:
100 return TRUE;
101
102 default:
103 return (wpmd->id & ID_OPTIONAL_DATA) ? TRUE : FALSE;
104 }
105}
diff --git a/apps/codecs/libwavpack/unpack.c b/apps/codecs/libwavpack/unpack.c
new file mode 100644
index 0000000000..e2e27b4999
--- /dev/null
+++ b/apps/codecs/libwavpack/unpack.c
@@ -0,0 +1,576 @@
1////////////////////////////////////////////////////////////////////////////
2// **** WAVPACK **** //
3// Hybrid Lossless Wavefile Compressor //
4// Copyright (c) 1998 - 2004 Conifer Software. //
5// All Rights Reserved. //
6// Distributed under the BSD Software License (see license.txt) //
7////////////////////////////////////////////////////////////////////////////
8
9// unpack.c
10
11// This module actually handles the decompression of the audio data, except
12// for the entropy decoding which is handled by the words.c module. For
13// maximum efficiency, the conversion is isolated to tight loops that handle
14// an entire buffer.
15
16#include "wavpack.h"
17
18#include <string.h>
19#include <math.h>
20
21#define LOSSY_MUTE
22
23//////////////////////////////// local macros /////////////////////////////////
24
25#define apply_weight_i(weight, sample) ((weight * sample + 512) >> 10)
26
27#define apply_weight_f(weight, sample) (((((sample & 0xffff) * weight) >> 9) + \
28 (((sample & ~0xffff) >> 9) * weight) + 1) >> 1)
29
30#define apply_weight(weight, sample) (sample != (short) sample ? \
31 apply_weight_f (weight, sample) : apply_weight_i (weight, sample))
32
33#define update_weight(weight, delta, source, result) \
34 if (source && result) weight -= ((((source ^ result) >> 30) & 2) - 1) * delta;
35
36#define update_weight_clip(weight, delta, source, result) \
37 if (source && result && ((source ^ result) < 0 ? (weight -= delta) < -1024 : (weight += delta) > 1024)) \
38 weight = weight < 0 ? -1024 : 1024;
39
40///////////////////////////// executable code ////////////////////////////////
41
42// This function initializes everything required to unpack a WavPack block
43// and must be called before unpack_samples() is called to obtain audio data.
44// It is assumed that the WavpackHeader has been read into the wps->wphdr
45// (in the current WavpackStream). This is where all the metadata blocks are
46// scanned up to the one containing the audio bitstream.
47
48int unpack_init (WavpackContext *wpc)
49{
50 WavpackStream *wps = &wpc->stream;
51 WavpackMetadata wpmd;
52
53 if (wps->wphdr.block_samples && wps->wphdr.block_index != (ulong) -1)
54 wps->sample_index = wps->wphdr.block_index;
55
56 wps->mute_error = FALSE;
57 wps->crc = 0xffffffff;
58 CLEAR (wps->wvbits);
59 CLEAR (wps->decorr_passes);
60 CLEAR (wps->w);
61
62 while (read_metadata_buff (wpc, &wpmd)) {
63 if (!process_metadata (wpc, &wpmd)) {
64 strcpy (wpc->error_message, "invalid metadata!");
65 return FALSE;
66 }
67
68 if (wpmd.id == ID_WV_BITSTREAM)
69 break;
70 }
71
72 if (wps->wphdr.block_samples && !bs_is_open (&wps->wvbits)) {
73 strcpy (wpc->error_message, "invalid WavPack file!");
74 return FALSE;
75 }
76
77 if (wps->wphdr.block_samples) {
78 if ((wps->wphdr.flags & INT32_DATA) && wps->int32_sent_bits)
79 wpc->lossy_blocks = TRUE;
80
81 if ((wps->wphdr.flags & FLOAT_DATA) &&
82 wps->float_flags & (FLOAT_EXCEPTIONS | FLOAT_ZEROS_SENT | FLOAT_SHIFT_SENT | FLOAT_SHIFT_SAME))
83 wpc->lossy_blocks = TRUE;
84 }
85
86 return TRUE;
87}
88
89// This function initialzes the main bitstream for audio samples, which must
90// be in the "wv" file.
91
92int init_wv_bitstream (WavpackContext *wpc, WavpackMetadata *wpmd)
93{
94 WavpackStream *wps = &wpc->stream;
95
96 if (wpmd->data)
97 bs_open_read (&wps->wvbits, wpmd->data, (char *) wpmd->data + wpmd->byte_length, NULL, 0);
98 else if (wpmd->byte_length)
99 bs_open_read (&wps->wvbits, wpc->read_buffer, wpc->read_buffer + sizeof (wpc->read_buffer),
100 wpc->infile, wpmd->byte_length + (wpmd->byte_length & 1));
101
102 return TRUE;
103}
104
105// Read decorrelation terms from specified metadata block into the
106// decorr_passes array. The terms range from -3 to 8, plus 17 & 18;
107// other values are reserved and generate errors for now. The delta
108// ranges from 0 to 7 with all values valid. Note that the terms are
109// stored in the opposite order in the decorr_passes array compared
110// to packing.
111
112int read_decorr_terms (WavpackStream *wps, WavpackMetadata *wpmd)
113{
114 int termcnt = wpmd->byte_length;
115 uchar *byteptr = wpmd->data;
116 struct decorr_pass *dpp;
117
118 if (termcnt > MAX_NTERMS)
119 return FALSE;
120
121 wps->num_terms = termcnt;
122
123 for (dpp = wps->decorr_passes + termcnt - 1; termcnt--; dpp--) {
124 dpp->term = (int)(*byteptr & 0x1f) - 5;
125 dpp->delta = (*byteptr++ >> 5) & 0x7;
126
127 if (!dpp->term || dpp->term < -3 || (dpp->term > MAX_TERM && dpp->term < 17) || dpp->term > 18)
128 return FALSE;
129 }
130
131 return TRUE;
132}
133
134// Read decorrelation weights from specified metadata block into the
135// decorr_passes array. The weights range +/-1024, but are rounded and
136// truncated to fit in signed chars for metadata storage. Weights are
137// separate for the two channels and are specified from the "last" term
138// (first during encode). Unspecified weights are set to zero.
139
140int read_decorr_weights (WavpackStream *wps, WavpackMetadata *wpmd)
141{
142 int termcnt = wpmd->byte_length, tcount;
143 char *byteptr = wpmd->data;
144 struct decorr_pass *dpp;
145
146 if (!(wps->wphdr.flags & MONO_FLAG))
147 termcnt /= 2;
148
149 if (termcnt > wps->num_terms)
150 return FALSE;
151
152 for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++)
153 dpp->weight_A = dpp->weight_B = 0;
154
155 while (--dpp >= wps->decorr_passes && termcnt--) {
156 dpp->weight_A = restore_weight (*byteptr++);
157
158 if (!(wps->wphdr.flags & MONO_FLAG))
159 dpp->weight_B = restore_weight (*byteptr++);
160 }
161
162 return TRUE;
163}
164
165// Read decorrelation samples from specified metadata block into the
166// decorr_passes array. The samples are signed 32-bit values, but are
167// converted to signed log2 values for storage in metadata. Values are
168// stored for both channels and are specified from the "last" term
169// (first during encode) with unspecified samples set to zero. The
170// number of samples stored varies with the actual term value, so
171// those must obviously come first in the metadata.
172
173int read_decorr_samples (WavpackStream *wps, WavpackMetadata *wpmd)
174{
175 uchar *byteptr = wpmd->data;
176 uchar *endptr = byteptr + wpmd->byte_length;
177 struct decorr_pass *dpp;
178 int tcount;
179
180 for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++) {
181 CLEAR (dpp->samples_A);
182 CLEAR (dpp->samples_B);
183 }
184
185 if (wps->wphdr.version == 0x402 && (wps->wphdr.flags & HYBRID_FLAG)) {
186 byteptr += 2;
187
188 if (!(wps->wphdr.flags & MONO_FLAG))
189 byteptr += 2;
190 }
191
192 while (dpp-- > wps->decorr_passes && byteptr < endptr)
193 if (dpp->term > MAX_TERM) {
194 dpp->samples_A [0] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8)));
195 dpp->samples_A [1] = exp2s ((short)(byteptr [2] + (byteptr [3] << 8)));
196 byteptr += 4;
197
198 if (!(wps->wphdr.flags & MONO_FLAG)) {
199 dpp->samples_B [0] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8)));
200 dpp->samples_B [1] = exp2s ((short)(byteptr [2] + (byteptr [3] << 8)));
201 byteptr += 4;
202 }
203 }
204 else if (dpp->term < 0) {
205 dpp->samples_A [0] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8)));
206 dpp->samples_B [0] = exp2s ((short)(byteptr [2] + (byteptr [3] << 8)));
207 byteptr += 4;
208 }
209 else {
210 int m = 0, cnt = dpp->term;
211
212 while (cnt--) {
213 dpp->samples_A [m] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8)));
214 byteptr += 2;
215
216 if (!(wps->wphdr.flags & MONO_FLAG)) {
217 dpp->samples_B [m] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8)));
218 byteptr += 2;
219 }
220
221 m++;
222 }
223 }
224
225 return byteptr == endptr;
226}
227
228// Read the int32 data from the specified metadata into the specified stream.
229// This data is used for integer data that has more than 24 bits of magnitude
230// or, in some cases, used to eliminate redundant bits from any audio stream.
231
232int read_int32_info (WavpackStream *wps, WavpackMetadata *wpmd)
233{
234 int bytecnt = wpmd->byte_length;
235 char *byteptr = wpmd->data;
236
237 if (bytecnt != 4)
238 return FALSE;
239
240 wps->int32_sent_bits = *byteptr++;
241 wps->int32_zeros = *byteptr++;
242 wps->int32_ones = *byteptr++;
243 wps->int32_dups = *byteptr;
244 return TRUE;
245}
246
247// Read multichannel information from metadata. The first byte is the total
248// number of channels and the following bytes represent the channel_mask
249// as described for Microsoft WAVEFORMATEX.
250
251int read_channel_info (WavpackContext *wpc, WavpackMetadata *wpmd)
252{
253 int bytecnt = wpmd->byte_length, shift = 0;
254 char *byteptr = wpmd->data;
255 ulong mask = 0;
256
257 if (!bytecnt || bytecnt > 5)
258 return FALSE;
259
260 wpc->config.num_channels = *byteptr++;
261
262 while (--bytecnt) {
263 mask |= (ulong) *byteptr++ << shift;
264 shift += 8;
265 }
266
267 wpc->config.channel_mask = mask;
268 return TRUE;
269}
270
271// Read configuration information from metadata.
272
273int read_config_info (WavpackContext *wpc, WavpackMetadata *wpmd)
274{
275 int bytecnt = wpmd->byte_length;
276 uchar *byteptr = wpmd->data;
277
278 if (bytecnt >= 3) {
279 wpc->config.flags &= 0xff;
280 wpc->config.flags |= (long) *byteptr++ << 8;
281 wpc->config.flags |= (long) *byteptr++ << 16;
282 wpc->config.flags |= (long) *byteptr << 24;
283 }
284
285 return TRUE;
286}
287
288// This monster actually unpacks the WavPack bitstream(s) into the specified
289// buffer as 32-bit integers or floats (depending on orignal data). Lossy
290// samples will be clipped to their original limits (i.e. 8-bit samples are
291// clipped to -128/+127) but are still returned in longs. It is up to the
292// caller to potentially reformat this for the final output including any
293// multichannel distribution, block alignment or endian compensation. The
294// function unpack_init() must have been called and the entire WavPack block
295// must still be visible (although wps->blockbuff will not be accessed again).
296// For maximum clarity, the function is broken up into segments that handle
297// various modes. This makes for a few extra infrequent flag checks, but
298// makes the code easier to follow because the nesting does not become so
299// deep. For maximum efficiency, the conversion is isolated to tight loops
300// that handle an entire buffer. The function returns the total number of
301// samples unpacked, which can be less than the number requested if an error
302// occurs or the end of the block is reached.
303
304static void fixup_samples (WavpackStream *wps, long *buffer, ulong sample_count);
305
306long unpack_samples (WavpackContext *wpc, long *buffer, ulong sample_count)
307{
308 WavpackStream *wps = &wpc->stream;
309 ulong flags = wps->wphdr.flags, crc = wps->crc, i;
310 long mute_limit = (1L << ((flags & MAG_MASK) >> MAG_LSB)) + 2;
311 struct decorr_pass *dpp;
312 long read_word, *bptr;
313 int tcount, m = 0;
314
315 if (wps->sample_index + sample_count > wps->wphdr.block_index + wps->wphdr.block_samples)
316 sample_count = wps->wphdr.block_index + wps->wphdr.block_samples - wps->sample_index;
317
318 if (wps->mute_error) {
319 memset (buffer, 0, sample_count * (flags & MONO_FLAG ? 4 : 8));
320 wps->sample_index += sample_count;
321 return sample_count;
322 }
323
324 if (flags & HYBRID_FLAG)
325 mute_limit *= 2;
326
327 ///////////////////// handle version 4 mono data /////////////////////////
328
329 if (flags & MONO_FLAG)
330 for (bptr = buffer, i = 0; i < sample_count; ++i) {
331 if ((read_word = get_word (wps, 0)) == WORD_EOF)
332 break;
333
334 for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++) {
335 long sam, temp;
336 int k;
337
338 if (dpp->term > MAX_TERM) {
339 if (dpp->term & 1)
340 sam = 2 * dpp->samples_A [0] - dpp->samples_A [1];
341 else
342 sam = (3 * dpp->samples_A [0] - dpp->samples_A [1]) >> 1;
343
344 dpp->samples_A [1] = dpp->samples_A [0];
345 k = 0;
346 }
347 else {
348 sam = dpp->samples_A [m];
349 k = (m + dpp->term) & (MAX_TERM - 1);
350 }
351
352 temp = apply_weight (dpp->weight_A, sam) + read_word;
353 update_weight (dpp->weight_A, dpp->delta, sam, read_word);
354 dpp->samples_A [k] = read_word = temp;
355 }
356
357 if (labs (read_word) > mute_limit)
358 break;
359
360 m = (m + 1) & (MAX_TERM - 1);
361 crc = crc * 3 + read_word;
362 *bptr++ = read_word;
363 }
364
365 //////////////////// handle version 4 stereo data ////////////////////////
366
367 else
368 for (bptr = buffer, i = 0; i < sample_count; ++i) {
369 long left, right, left2, right2;
370
371 if ((left = get_word (wps, 0)) == WORD_EOF ||
372 (right = get_word (wps, 1)) == WORD_EOF)
373 break;
374
375 for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++)
376 if (dpp->term > 0) {
377 long sam_A, sam_B;
378 int k;
379
380 if (dpp->term > MAX_TERM) {
381 if (dpp->term & 1) {
382 sam_A = 2 * dpp->samples_A [0] - dpp->samples_A [1];
383 sam_B = 2 * dpp->samples_B [0] - dpp->samples_B [1];
384 }
385 else {
386 sam_A = (3 * dpp->samples_A [0] - dpp->samples_A [1]) >> 1;
387 sam_B = (3 * dpp->samples_B [0] - dpp->samples_B [1]) >> 1;
388 }
389
390 dpp->samples_A [1] = dpp->samples_A [0];
391 dpp->samples_B [1] = dpp->samples_B [0];
392 k = 0;
393 }
394 else {
395 sam_A = dpp->samples_A [m];
396 sam_B = dpp->samples_B [m];
397 k = (m + dpp->term) & (MAX_TERM - 1);
398 }
399
400 left2 = apply_weight (dpp->weight_A, sam_A) + left;
401 right2 = apply_weight (dpp->weight_B, sam_B) + right;
402
403 update_weight (dpp->weight_A, dpp->delta, sam_A, left);
404 update_weight (dpp->weight_B, dpp->delta, sam_B, right);
405
406 dpp->samples_A [k] = left = left2;
407 dpp->samples_B [k] = right = right2;
408 }
409 else if (dpp->term == -1) {
410 left2 = left + apply_weight (dpp->weight_A, dpp->samples_A [0]);
411 update_weight_clip (dpp->weight_A, dpp->delta, dpp->samples_A [0], left);
412 left = left2;
413 right2 = right + apply_weight (dpp->weight_B, left2);
414 update_weight_clip (dpp->weight_B, dpp->delta, left2, right);
415 dpp->samples_A [0] = right = right2;
416 }
417 else {
418 right2 = right + apply_weight (dpp->weight_B, dpp->samples_B [0]);
419 update_weight_clip (dpp->weight_B, dpp->delta, dpp->samples_B [0], right);
420 right = right2;
421
422 if (dpp->term == -3) {
423 right2 = dpp->samples_A [0];
424 dpp->samples_A [0] = right;
425 }
426
427 left2 = left + apply_weight (dpp->weight_A, right2);
428 update_weight_clip (dpp->weight_A, dpp->delta, right2, left);
429 dpp->samples_B [0] = left = left2;
430 }
431
432 m = (m + 1) & (MAX_TERM - 1);
433
434 if (flags & JOINT_STEREO)
435 left += (right -= (left >> 1));
436
437 if (labs (left) > mute_limit || labs (right) > mute_limit)
438 break;
439
440 crc = (crc * 3 + left) * 3 + right;
441 *bptr++ = left;
442 *bptr++ = right;
443 }
444
445 if (i != sample_count) {
446 memset (buffer, 0, sample_count * (flags & MONO_FLAG ? 4 : 8));
447 wps->mute_error = TRUE;
448 i = sample_count;
449 }
450
451 while (m--)
452 for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++)
453 if (dpp->term > 0 && dpp->term <= MAX_TERM) {
454 long temp = dpp->samples_A [0];
455 memcpy (dpp->samples_A, dpp->samples_A + 1, sizeof (dpp->samples_A) - sizeof (dpp->samples_A [0]));
456 dpp->samples_A [MAX_TERM - 1] = temp;
457 temp = dpp->samples_B [0];
458 memcpy (dpp->samples_B, dpp->samples_B + 1, sizeof (dpp->samples_B) - sizeof (dpp->samples_B [0]));
459 dpp->samples_B [MAX_TERM - 1] = temp;
460 }
461
462 fixup_samples (wps, buffer, i);
463
464 if (flags & FLOAT_DATA)
465 float_normalize (buffer, (flags & MONO_FLAG) ? i : i * 2,
466 127 - wps->float_norm_exp + wpc->norm_offset);
467
468 wps->sample_index += i;
469 wps->crc = crc;
470
471 return i;
472}
473
474// This is a helper function for unpack_samples() that applies several final
475// operations. First, if the data is 32-bit float data, then that conversion
476// is done in the float.c module (whether lossy or lossless) and we return.
477// Otherwise, if the extended integer data applies, then that operation is
478// executed first. If the unpacked data is lossy (and not corrected) then
479// it is clipped and shifted in a single operation. Otherwise, if it's
480// lossless then the last step is to apply the final shift (if any).
481
482static void fixup_samples (WavpackStream *wps, long *buffer, ulong sample_count)
483{
484 ulong flags = wps->wphdr.flags;
485 int shift = (flags & SHIFT_MASK) >> SHIFT_LSB;
486
487 if (flags & FLOAT_DATA) {
488 float_values (wps, buffer, (flags & MONO_FLAG) ? sample_count : sample_count * 2);
489 return;
490 }
491
492 if (flags & INT32_DATA) {
493 ulong count = (flags & MONO_FLAG) ? sample_count : sample_count * 2;
494 int sent_bits = wps->int32_sent_bits, zeros = wps->int32_zeros;
495 int ones = wps->int32_ones, dups = wps->int32_dups;
496// ulong mask = (1 << sent_bits) - 1;
497 long *dptr = buffer;
498
499 if (!(flags & HYBRID_FLAG) && !sent_bits && (zeros + ones + dups))
500 while (count--) {
501 if (zeros)
502 *dptr <<= zeros;
503 else if (ones)
504 *dptr = ((*dptr + 1) << ones) - 1;
505 else if (dups)
506 *dptr = ((*dptr + (*dptr & 1)) << dups) - (*dptr & 1);
507
508 dptr++;
509 }
510 else
511 shift += zeros + sent_bits + ones + dups;
512 }
513
514 if (flags & HYBRID_FLAG) {
515 long min_value, max_value, min_shifted, max_shifted;
516
517 switch (flags & BYTES_STORED) {
518 case 0:
519 min_shifted = (min_value = -128 >> shift) << shift;
520 max_shifted = (max_value = 127 >> shift) << shift;
521 break;
522
523 case 1:
524 min_shifted = (min_value = -32768 >> shift) << shift;
525 max_shifted = (max_value = 32767 >> shift) << shift;
526 break;
527
528 case 2:
529 min_shifted = (min_value = -8388608 >> shift) << shift;
530 max_shifted = (max_value = 8388607 >> shift) << shift;
531 break;
532
533 case 3:
534 min_shifted = (min_value = -(long)2147483648 >> shift) << shift;
535 max_shifted = (max_value = (long) 2147483647 >> shift) << shift;
536 break;
537 }
538
539 if (!(flags & MONO_FLAG))
540 sample_count *= 2;
541
542 while (sample_count--) {
543 if (*buffer < min_value)
544 *buffer++ = min_shifted;
545 else if (*buffer > max_value)
546 *buffer++ = max_shifted;
547 else
548 *buffer++ <<= shift;
549 }
550 }
551 else if (shift) {
552 if (!(flags & MONO_FLAG))
553 sample_count *= 2;
554
555 while (sample_count--)
556 *buffer++ <<= shift;
557 }
558}
559
560// This function checks the crc value(s) for an unpacked block, returning the
561// number of actual crc errors detected for the block. The block must be
562// completely unpacked before this test is valid. For losslessly unpacked
563// blocks of float or extended integer data the extended crc is also checked.
564// Note that WavPack's crc is not a CCITT approved polynomial algorithm, but
565// is a much simpler method that is virtually as robust for real world data.
566
567int check_crc_error (WavpackContext *wpc)
568{
569 WavpackStream *wps = &wpc->stream;
570 int result = 0;
571
572 if (wps->crc != wps->wphdr.crc)
573 ++result;
574
575 return result;
576}
diff --git a/apps/codecs/libwavpack/wavpack.h b/apps/codecs/libwavpack/wavpack.h
new file mode 100644
index 0000000000..af9d88dfe6
--- /dev/null
+++ b/apps/codecs/libwavpack/wavpack.h
@@ -0,0 +1,330 @@
1////////////////////////////////////////////////////////////////////////////
2// **** WAVPACK **** //
3// Hybrid Lossless Wavefile Compressor //
4// Copyright (c) 1998 - 2004 Conifer Software. //
5// All Rights Reserved. //
6// Distributed under the BSD Software License (see license.txt) //
7////////////////////////////////////////////////////////////////////////////
8
9// wavpack.h
10
11#include <sys/types.h>
12
13// This header file contains all the definitions required by WavPack.
14
15typedef unsigned char uchar;
16#if !defined(__GNUC__) || defined(WIN32)
17typedef unsigned short ushort;
18typedef unsigned long ulong;
19typedef unsigned int uint;
20#elif defined(__APPLE__)
21typedef unsigned long ulong;
22#endif
23
24// This structure is used to access the individual fields of 32-bit ieee
25// floating point numbers. This will not be compatible with compilers that
26// allocate bit fields from the most significant bits, although I'm not sure
27// how common that is.
28
29typedef struct {
30 unsigned mantissa : 23;
31 unsigned exponent : 8;
32 unsigned sign : 1;
33} f32;
34
35#include <stdio.h>
36
37#define FALSE 0
38#define TRUE 1
39
40////////////////////////////// WavPack Header /////////////////////////////////
41
42// Note that this is the ONLY structure that is written to (or read from)
43// WavPack 4.0 files, and is the preamble to every block in both the .wv
44// and .wvc files.
45
46typedef struct {
47 char ckID [4];
48 ulong ckSize;
49 short version;
50 uchar track_no, index_no;
51 ulong total_samples, block_index, block_samples, flags, crc;
52} WavpackHeader;
53
54#define WavpackHeaderFormat "4LS2LLLLL"
55
56// or-values for "flags"
57
58#define BYTES_STORED 3 // 1-4 bytes/sample
59#define MONO_FLAG 4 // not stereo
60#define HYBRID_FLAG 8 // hybrid mode
61#define JOINT_STEREO 0x10 // joint stereo
62#define CROSS_DECORR 0x20 // no-delay cross decorrelation
63#define HYBRID_SHAPE 0x40 // noise shape (hybrid mode only)
64#define FLOAT_DATA 0x80 // ieee 32-bit floating point data
65
66#define INT32_DATA 0x100 // special extended int handling
67#define HYBRID_BITRATE 0x200 // bitrate noise (hybrid mode only)
68#define HYBRID_BALANCE 0x400 // balance noise (hybrid stereo mode only)
69
70#define INITIAL_BLOCK 0x800 // initial block of multichannel segment
71#define FINAL_BLOCK 0x1000 // final block of multichannel segment
72
73#define SHIFT_LSB 13
74#define SHIFT_MASK (0x1fL << SHIFT_LSB)
75
76#define MAG_LSB 18
77#define MAG_MASK (0x1fL << MAG_LSB)
78
79#define SRATE_LSB 23
80#define SRATE_MASK (0xfL << SRATE_LSB)
81
82#define IGNORED_FLAGS 0x18000000 // reserved, but ignore if encountered
83#define NEW_SHAPING 0x20000000 // use IIR filter for negative shaping
84#define UNKNOWN_FLAGS 0xC0000000 // also reserved, but refuse decode if
85 // encountered
86
87//////////////////////////// WavPack Metadata /////////////////////////////////
88
89// This is an internal representation of metadata.
90
91typedef struct {
92 long byte_length;
93 void *data;
94 uchar id;
95} WavpackMetadata;
96
97#define ID_OPTIONAL_DATA 0x20
98#define ID_ODD_SIZE 0x40
99#define ID_LARGE 0x80
100
101#define ID_DUMMY 0x0
102#define ID_ENCODER_INFO 0x1
103#define ID_DECORR_TERMS 0x2
104#define ID_DECORR_WEIGHTS 0x3
105#define ID_DECORR_SAMPLES 0x4
106#define ID_ENTROPY_VARS 0x5
107#define ID_HYBRID_PROFILE 0x6
108#define ID_SHAPING_WEIGHTS 0x7
109#define ID_FLOAT_INFO 0x8
110#define ID_INT32_INFO 0x9
111#define ID_WV_BITSTREAM 0xa
112#define ID_WVC_BITSTREAM 0xb
113#define ID_WVX_BITSTREAM 0xc
114#define ID_CHANNEL_INFO 0xd
115
116#define ID_RIFF_HEADER (ID_OPTIONAL_DATA | 0x1)
117#define ID_RIFF_TRAILER (ID_OPTIONAL_DATA | 0x2)
118#define ID_REPLAY_GAIN (ID_OPTIONAL_DATA | 0x3)
119#define ID_CUESHEET (ID_OPTIONAL_DATA | 0x4)
120#define ID_CONFIG_BLOCK (ID_OPTIONAL_DATA | 0x5)
121#define ID_MD5_CHECKSUM (ID_OPTIONAL_DATA | 0x6)
122
123///////////////////////// WavPack Configuration ///////////////////////////////
124
125// This internal structure is used during encode to provide configuration to
126// the encoding engine and during decoding to provide fle information back to
127// the higher level functions. Not all fields are used in both modes.
128
129typedef struct {
130 int bits_per_sample, bytes_per_sample;
131 int qmode, flags, xmode, num_channels, float_norm_exp;
132 long block_samples, extra_flags, sample_rate, channel_mask;
133} WavpackConfig;
134
135#define CONFIG_BYTES_STORED 3 // 1-4 bytes/sample
136#define CONFIG_MONO_FLAG 4 // not stereo
137#define CONFIG_HYBRID_FLAG 8 // hybrid mode
138#define CONFIG_JOINT_STEREO 0x10 // joint stereo
139#define CONFIG_CROSS_DECORR 0x20 // no-delay cross decorrelation
140#define CONFIG_HYBRID_SHAPE 0x40 // noise shape (hybrid mode only)
141#define CONFIG_FLOAT_DATA 0x80 // ieee 32-bit floating point data
142
143#define CONFIG_ADOBE_MODE 0x100 // "adobe" mode for 32-bit floats
144#define CONFIG_FAST_FLAG 0x200 // fast mode
145#define CONFIG_VERY_FAST_FLAG 0x400 // double fast
146#define CONFIG_HIGH_FLAG 0x800 // high quality mode
147#define CONFIG_VERY_HIGH_FLAG 0x1000 // double high (not used yet)
148#define CONFIG_BITRATE_KBPS 0x2000 // bitrate is kbps, not bits / sample
149#define CONFIG_AUTO_SHAPING 0x4000 // automatic noise shaping
150#define CONFIG_SHAPE_OVERRIDE 0x8000 // shaping mode specified
151#define CONFIG_JOINT_OVERRIDE 0x10000 // joint-stereo mode specified
152#define CONFIG_COPY_TIME 0x20000 // copy file-time from source
153#define CONFIG_CREATE_EXE 0x40000 // create executable (not yet)
154#define CONFIG_CREATE_WVC 0x80000 // create correction file
155#define CONFIG_OPTIMIZE_WVC 0x100000 // maximize bybrid compression
156#define CONFIG_QUALITY_MODE 0x200000 // psychoacoustic quality mode
157#define CONFIG_RAW_FLAG 0x400000 // raw mode (not implemented yet)
158#define CONFIG_CALC_NOISE 0x800000 // calc noise in hybrid mode
159#define CONFIG_LOSSY_MODE 0x1000000 // obsolete (for information)
160#define CONFIG_EXTRA_MODE 0x2000000 // extra processing mode
161#define CONFIG_SKIP_WVX 0x4000000 // no wvx stream w/ floats & big ints
162#define CONFIG_MD5_CHECKSUM 0x8000000 // compute & store MD5 signature
163#define CONFIG_QUIET_MODE 0x10000000 // don't report progress %
164
165//////////////////////////////// WavPack Stream ///////////////////////////////
166
167// This internal structure contains everything required to handle a WavPack
168// "stream", which is defined as a stereo or mono stream of audio samples. For
169// multichannel audio several of these would be required. Each stream contains
170// pointers to hold a complete allocated block of WavPack data, although it's
171// possible to decode WavPack blocks without buffering an entire block.
172
173typedef long (*read_stream)(void *, long);
174
175typedef struct bs {
176 uchar *buf, *end, *ptr;
177 void (*wrap)(struct bs *bs);
178 ulong file_bytes, sr;
179 int error, bc;
180 read_stream file;
181} Bitstream;
182
183#define MAX_NTERMS 16
184#define MAX_TERM 8
185
186struct decorr_pass {
187 short term, delta, weight_A, weight_B;
188 long samples_A [MAX_TERM], samples_B [MAX_TERM];
189};
190
191typedef struct {
192 WavpackHeader wphdr;
193
194 int num_terms, mute_error;
195 ulong sample_index, crc;
196 Bitstream wvbits;
197
198 uchar int32_sent_bits, int32_zeros, int32_ones, int32_dups;
199 uchar float_flags, float_shift, float_max_exp, float_norm_exp;
200
201 struct decorr_pass decorr_passes [MAX_NTERMS];
202
203 struct {
204 ulong bitrate_delta [2], bitrate_acc [2];
205 ulong median [3] [2], slow_level [2], error_limit [2];
206 ulong pend_data, holding_one, zeros_acc;
207 int holding_zero, pend_count;
208 } w;
209} WavpackStream;
210
211// flags for float_flags:
212
213#define FLOAT_SHIFT_ONES 1 // bits left-shifted into float = '1'
214#define FLOAT_SHIFT_SAME 2 // bits left-shifted into float are the same
215#define FLOAT_SHIFT_SENT 4 // bits shifted into float are sent literally
216#define FLOAT_ZEROS_SENT 8 // "zeros" are not all real zeros
217#define FLOAT_NEG_ZEROS 0x10 // contains negative zeros
218#define FLOAT_EXCEPTIONS 0x20 // contains exceptions (inf, nan, etc.)
219
220/////////////////////////////// WavPack Context ///////////////////////////////
221
222// This internal structure holds everything required to encode or decode WavPack
223// files. It is recommended that direct access to this structure be minimized
224// and the provided utilities used instead.
225
226typedef struct {
227 WavpackConfig config;
228 WavpackStream stream;
229
230 uchar read_buffer [1024];
231 char error_message [80];
232
233 read_stream infile;
234 ulong total_samples, crc_errors, first_flags;
235 int open_flags, norm_offset, reduced_channels, lossy_blocks;
236
237} WavpackContext;
238
239//////////////////////// function prototypes and macros //////////////////////
240
241#define CLEAR(destin) memset (&destin, 0, sizeof (destin));
242
243// bits.c
244
245void bs_open_read (Bitstream *bs, uchar *buffer_start, uchar *buffer_end, read_stream file, ulong file_bytes);
246
247#define bs_is_open(bs) ((bs)->ptr != NULL)
248
249#define getbit(bs) ( \
250 (((bs)->bc) ? \
251 ((bs)->bc--, (bs)->sr & 1) : \
252 (((++((bs)->ptr) != (bs)->end) ? (void) 0 : (bs)->wrap (bs)), (bs)->bc = 7, ((bs)->sr = *((bs)->ptr)) & 1) \
253 ) ? \
254 ((bs)->sr >>= 1, 1) : \
255 ((bs)->sr >>= 1, 0) \
256)
257
258#define getbits(value, nbits, bs) { \
259 while ((nbits) > (bs)->bc) { \
260 if (++((bs)->ptr) == (bs)->end) (bs)->wrap (bs); \
261 (bs)->sr |= (long)*((bs)->ptr) << (bs)->bc; \
262 (bs)->bc += 8; \
263 } \
264 *(value) = (bs)->sr; \
265 (bs)->sr >>= (nbits); \
266 (bs)->bc -= (nbits); \
267}
268
269void little_endian_to_native (void *data, char *format);
270void native_to_little_endian (void *data, char *format);
271
272// unpack.c
273
274int unpack_init (WavpackContext *wpc);
275int init_wv_bitstream (WavpackContext *wpc, WavpackMetadata *wpmd);
276int read_decorr_terms (WavpackStream *wps, WavpackMetadata *wpmd);
277int read_decorr_weights (WavpackStream *wps, WavpackMetadata *wpmd);
278int read_decorr_samples (WavpackStream *wps, WavpackMetadata *wpmd);
279int read_float_info (WavpackStream *wps, WavpackMetadata *wpmd);
280int read_int32_info (WavpackStream *wps, WavpackMetadata *wpmd);
281int read_channel_info (WavpackContext *wpc, WavpackMetadata *wpmd);
282int read_config_info (WavpackContext *wpc, WavpackMetadata *wpmd);
283long unpack_samples (WavpackContext *wpc, long *buffer, ulong sample_count);
284int check_crc_error (WavpackContext *wpc);
285
286// metadata.c stuff
287
288int read_metadata_buff (WavpackContext *wpc, WavpackMetadata *wpmd);
289int process_metadata (WavpackContext *wpc, WavpackMetadata *wpmd);
290
291// words.c stuff
292
293int read_entropy_vars (WavpackStream *wps, WavpackMetadata *wpmd);
294int read_hybrid_profile (WavpackStream *wps, WavpackMetadata *wpmd);
295long get_word (WavpackStream *wps, int chan);
296long exp2s (int log);
297int restore_weight (char weight);
298
299#define WORD_EOF (1L << 31)
300
301// float.c
302
303int read_float_info (WavpackStream *wps, WavpackMetadata *wpmd);
304void float_values (WavpackStream *wps, long *values, long num_values);
305void float_normalize (long *values, long num_values, int delta_exp);
306
307// wputils.c
308
309WavpackContext *WavpackOpenFileInput (read_stream infile, char *error);
310
311int WavpackGetMode (WavpackContext *wpc);
312
313#define MODE_WVC 0x1
314#define MODE_LOSSLESS 0x2
315#define MODE_HYBRID 0x4
316#define MODE_FLOAT 0x8
317#define MODE_VALID_TAG 0x10
318#define MODE_HIGH 0x20
319#define MODE_FAST 0x40
320
321ulong WavpackUnpackSamples (WavpackContext *wpc, long *buffer, ulong samples);
322ulong WavpackGetNumSamples (WavpackContext *wpc);
323ulong WavpackGetSampleIndex (WavpackContext *wpc);
324int WavpackGetNumErrors (WavpackContext *wpc);
325int WavpackLossyBlocks (WavpackContext *wpc);
326ulong WavpackGetSampleRate (WavpackContext *wpc);
327int WavpackGetBitsPerSample (WavpackContext *wpc);
328int WavpackGetBytesPerSample (WavpackContext *wpc);
329int WavpackGetNumChannels (WavpackContext *wpc);
330int WavpackGetReducedChannels (WavpackContext *wpc);
diff --git a/apps/codecs/libwavpack/words.c b/apps/codecs/libwavpack/words.c
new file mode 100644
index 0000000000..35061b69a9
--- /dev/null
+++ b/apps/codecs/libwavpack/words.c
@@ -0,0 +1,503 @@
1////////////////////////////////////////////////////////////////////////////
2// **** WAVPACK **** //
3// Hybrid Lossless Wavefile Compressor //
4// Copyright (c) 1998 - 2004 Conifer Software. //
5// All Rights Reserved. //
6////////////////////////////////////////////////////////////////////////////
7
8// words.c
9
10// This module provides entropy word encoding and decoding functions using
11// a variation on the Rice method. This was introduced in version 3.93
12// because it allows splitting the data into a "lossy" stream and a
13// "correction" stream in a very efficient manner and is therefore ideal
14// for the "hybrid" mode. For 4.0, the efficiency of this method was
15// significantly improved by moving away from the normal Rice restriction of
16// using powers of two for the modulus divisions and now the method can be
17// used for both hybrid and pure lossless encoding.
18
19// Samples are divided by median probabilities at 5/7 (71.43%), 10/49 (20.41%),
20// and 20/343 (5.83%). Each zone has 3.5 times fewer samples than the
21// previous. Using standard Rice coding on this data would result in 1.4
22// bits per sample average (not counting sign bit). However, there is a
23// very simple encoding that is over 99% efficient with this data and
24// results in about 1.22 bits per sample.
25
26#include "wavpack.h"
27
28#include <string.h>
29
30//////////////////////////////// local macros /////////////////////////////////
31
32#define LIMIT_ONES 16 // maximum consecutive 1s sent for "div" data
33
34// these control the time constant "slow_level" which is used for hybrid mode
35// that controls bitrate as a function of residual level (HYBRID_BITRATE).
36#define SLS 8
37#define SLO ((1 << (SLS - 1)))
38
39// these control the time constant of the 3 median level breakpoints
40#define DIV0 128 // 5/7 of samples
41#define DIV1 64 // 10/49 of samples
42#define DIV2 32 // 20/343 of samples
43
44// this macro retrieves the specified median breakpoint (without frac; min = 1)
45#define GET_MED(med) (((wps->w.median [med] [chan]) >> 4) + 1)
46
47// These macros update the specified median breakpoints. Note that the median
48// is incremented when the sample is higher than the median, else decremented.
49// They are designed so that the median will never drop below 1 and the value
50// is essentially stationary if there are 2 increments for every 5 decrements.
51
52#define INC_MED0() (wps->w.median [0] [chan] += ((wps->w.median [0] [chan] + DIV0) / DIV0) * 5)
53#define DEC_MED0() (wps->w.median [0] [chan] -= ((wps->w.median [0] [chan] + (DIV0-2)) / DIV0) * 2)
54#define INC_MED1() (wps->w.median [1] [chan] += ((wps->w.median [1] [chan] + DIV1) / DIV1) * 5)
55#define DEC_MED1() (wps->w.median [1] [chan] -= ((wps->w.median [1] [chan] + (DIV1-2)) / DIV1) * 2)
56#define INC_MED2() (wps->w.median [2] [chan] += ((wps->w.median [2] [chan] + DIV2) / DIV2) * 5)
57#define DEC_MED2() (wps->w.median [2] [chan] -= ((wps->w.median [2] [chan] + (DIV2-2)) / DIV2) * 2)
58
59#define count_bits(av) ( \
60 (av) < (1 << 8) ? nbits_table [av] : \
61 ( \
62 (av) < (1L << 16) ? nbits_table [(av) >> 8] + 8 : \
63 ((av) < (1L << 24) ? nbits_table [(av) >> 16] + 16 : nbits_table [(av) >> 24] + 24) \
64 ) \
65)
66
67///////////////////////////// local table storage ////////////////////////////
68
69const char nbits_table [] = {
70 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, // 0 - 15
71 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, // 16 - 31
72 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, // 32 - 47
73 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, // 48 - 63
74 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 64 - 79
75 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 80 - 95
76 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 96 - 111
77 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 112 - 127
78 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, // 128 - 143
79 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, // 144 - 159
80 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, // 160 - 175
81 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, // 176 - 191
82 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, // 192 - 207
83 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, // 208 - 223
84 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, // 224 - 239
85 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 // 240 - 255
86};
87
88static const uchar log2_table [] = {
89 0x00, 0x01, 0x03, 0x04, 0x06, 0x07, 0x09, 0x0a, 0x0b, 0x0d, 0x0e, 0x10, 0x11, 0x12, 0x14, 0x15,
90 0x16, 0x18, 0x19, 0x1a, 0x1c, 0x1d, 0x1e, 0x20, 0x21, 0x22, 0x24, 0x25, 0x26, 0x28, 0x29, 0x2a,
91 0x2c, 0x2d, 0x2e, 0x2f, 0x31, 0x32, 0x33, 0x34, 0x36, 0x37, 0x38, 0x39, 0x3b, 0x3c, 0x3d, 0x3e,
92 0x3f, 0x41, 0x42, 0x43, 0x44, 0x45, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4d, 0x4e, 0x4f, 0x50, 0x51,
93 0x52, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63,
94 0x64, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x74, 0x75,
95 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85,
96 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95,
97 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4,
98 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb2,
99 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc0,
100 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcb, 0xcc, 0xcd, 0xce,
101 0xcf, 0xd0, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd8, 0xd9, 0xda, 0xdb,
102 0xdc, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe4, 0xe5, 0xe6, 0xe7, 0xe7,
103 0xe8, 0xe9, 0xea, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xee, 0xef, 0xf0, 0xf1, 0xf1, 0xf2, 0xf3, 0xf4,
104 0xf4, 0xf5, 0xf6, 0xf7, 0xf7, 0xf8, 0xf9, 0xf9, 0xfa, 0xfb, 0xfc, 0xfc, 0xfd, 0xfe, 0xff, 0xff
105};
106
107static const uchar exp2_table [] = {
108 0x00, 0x01, 0x01, 0x02, 0x03, 0x03, 0x04, 0x05, 0x06, 0x06, 0x07, 0x08, 0x08, 0x09, 0x0a, 0x0b,
109 0x0b, 0x0c, 0x0d, 0x0e, 0x0e, 0x0f, 0x10, 0x10, 0x11, 0x12, 0x13, 0x13, 0x14, 0x15, 0x16, 0x16,
110 0x17, 0x18, 0x19, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1d, 0x1e, 0x1f, 0x20, 0x20, 0x21, 0x22, 0x23,
111 0x24, 0x24, 0x25, 0x26, 0x27, 0x28, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
112 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3a, 0x3b, 0x3c, 0x3d,
113 0x3e, 0x3f, 0x40, 0x41, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x48, 0x49, 0x4a, 0x4b,
114 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a,
115 0x5b, 0x5c, 0x5d, 0x5e, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
116 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
117 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x87, 0x88, 0x89, 0x8a,
118 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b,
119 0x9c, 0x9d, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad,
120 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0,
121 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc8, 0xc9, 0xca, 0xcb, 0xcd, 0xce, 0xcf, 0xd0, 0xd2, 0xd3, 0xd4,
122 0xd6, 0xd7, 0xd8, 0xd9, 0xdb, 0xdc, 0xdd, 0xde, 0xe0, 0xe1, 0xe2, 0xe4, 0xe5, 0xe6, 0xe8, 0xe9,
123 0xea, 0xec, 0xed, 0xee, 0xf0, 0xf1, 0xf2, 0xf4, 0xf5, 0xf6, 0xf8, 0xf9, 0xfa, 0xfc, 0xfd, 0xff
124};
125
126///////////////////////////// executable code ////////////////////////////////
127
128static int log2 (unsigned long avalue);
129
130// Read the median log2 values from the specifed metadata structure, convert
131// them back to 32-bit unsigned values and store them. If length is not
132// exactly correct then we flag and return an error.
133
134int read_entropy_vars (WavpackStream *wps, WavpackMetadata *wpmd)
135{
136 uchar *byteptr = wpmd->data;
137
138 if (wpmd->byte_length != ((wps->wphdr.flags & MONO_FLAG) ? 6 : 12))
139 return FALSE;
140
141 wps->w.median [0] [0] = exp2s (byteptr [0] + (byteptr [1] << 8));
142 wps->w.median [1] [0] = exp2s (byteptr [2] + (byteptr [3] << 8));
143 wps->w.median [2] [0] = exp2s (byteptr [4] + (byteptr [5] << 8));
144
145 if (!(wps->wphdr.flags & MONO_FLAG)) {
146 wps->w.median [0] [1] = exp2s (byteptr [6] + (byteptr [7] << 8));
147 wps->w.median [1] [1] = exp2s (byteptr [8] + (byteptr [9] << 8));
148 wps->w.median [2] [1] = exp2s (byteptr [10] + (byteptr [11] << 8));
149 }
150
151 return TRUE;
152}
153
154// Read the hybrid related values from the specifed metadata structure, convert
155// them back to their internal formats and store them. The extended profile
156// stuff is not implemented yet, so return an error if we get more data than
157// we know what to do with.
158
159int read_hybrid_profile (WavpackStream *wps, WavpackMetadata *wpmd)
160{
161 uchar *byteptr = wpmd->data;
162 uchar *endptr = byteptr + wpmd->byte_length;
163
164 if (wps->wphdr.flags & HYBRID_BITRATE) {
165 wps->w.slow_level [0] = exp2s (byteptr [0] + (byteptr [1] << 8));
166 byteptr += 2;
167
168 if (!(wps->wphdr.flags & MONO_FLAG)) {
169 wps->w.slow_level [1] = exp2s (byteptr [0] + (byteptr [1] << 8));
170 byteptr += 2;
171 }
172 }
173
174 wps->w.bitrate_acc [0] = (long)(byteptr [0] + (byteptr [1] << 8)) << 16;
175 byteptr += 2;
176
177 if (!(wps->wphdr.flags & MONO_FLAG)) {
178 wps->w.bitrate_acc [1] = (long)(byteptr [0] + (byteptr [1] << 8)) << 16;
179 byteptr += 2;
180 }
181
182 if (byteptr < endptr) {
183 wps->w.bitrate_delta [0] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8)));
184 byteptr += 2;
185
186 if (!(wps->wphdr.flags & MONO_FLAG)) {
187 wps->w.bitrate_delta [1] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8)));
188 byteptr += 2;
189 }
190
191 if (byteptr < endptr)
192 return FALSE;
193 }
194 else
195 wps->w.bitrate_delta [0] = wps->w.bitrate_delta [1] = 0;
196
197 return TRUE;
198}
199
200// This function is called during both encoding and decoding of hybrid data to
201// update the "error_limit" variable which determines the maximum sample error
202// allowed in the main bitstream. In the HYBRID_BITRATE mode (which is the only
203// currently implemented) this is calculated from the slow_level values and the
204// bitrate accumulators. Note that the bitrate accumulators can be changing.
205
206static void update_error_limit (WavpackStream *wps)
207{
208 int bitrate_0 = (wps->w.bitrate_acc [0] += wps->w.bitrate_delta [0]) >> 16;
209
210 if (wps->wphdr.flags & MONO_FLAG) {
211 if (wps->wphdr.flags & HYBRID_BITRATE) {
212 int slow_log_0 = (wps->w.slow_level [0] + SLO) >> SLS;
213
214 if (slow_log_0 - bitrate_0 > -0x100)
215 wps->w.error_limit [0] = exp2s (slow_log_0 - bitrate_0 + 0x100);
216 else
217 wps->w.error_limit [0] = 0;
218 }
219 else
220 wps->w.error_limit [0] = exp2s (bitrate_0);
221 }
222 else {
223 int bitrate_1 = (wps->w.bitrate_acc [1] += wps->w.bitrate_delta [1]) >> 16;
224
225 if (wps->wphdr.flags & HYBRID_BITRATE) {
226 int slow_log_0 = (wps->w.slow_level [0] + SLO) >> SLS;
227 int slow_log_1 = (wps->w.slow_level [1] + SLO) >> SLS;
228
229 if (wps->wphdr.flags & HYBRID_BALANCE) {
230 int balance = (slow_log_1 - slow_log_0 + bitrate_1 + 1) >> 1;
231
232 if (balance > bitrate_0) {
233 bitrate_1 = bitrate_0 * 2;
234 bitrate_0 = 0;
235 }
236 else if (-balance > bitrate_0) {
237 bitrate_0 = bitrate_0 * 2;
238 bitrate_1 = 0;
239 }
240 else {
241 bitrate_1 = bitrate_0 + balance;
242 bitrate_0 = bitrate_0 - balance;
243 }
244 }
245
246 if (slow_log_0 - bitrate_0 > -0x100)
247 wps->w.error_limit [0] = exp2s (slow_log_0 - bitrate_0 + 0x100);
248 else
249 wps->w.error_limit [0] = 0;
250
251 if (slow_log_1 - bitrate_1 > -0x100)
252 wps->w.error_limit [1] = exp2s (slow_log_1 - bitrate_1 + 0x100);
253 else
254 wps->w.error_limit [1] = 0;
255 }
256 else {
257 wps->w.error_limit [0] = exp2s (bitrate_0);
258 wps->w.error_limit [1] = exp2s (bitrate_1);
259 }
260 }
261}
262
263static ulong read_code (Bitstream *bs, ulong maxcode);
264
265// Read the next word from the bitstream "wvbits" and return the value. This
266// function can be used for hybrid or lossless streams, but since an
267// optimized version is available for lossless this function would normally
268// be used for hybrid only. If a hybrid lossless stream is being read then
269// the "correction" offset is written at the specified pointer. A return value
270// of WORD_EOF indicates that the end of the bitstream was reached (all 1s) or
271// some other error occurred.
272
273long get_word (WavpackStream *wps, int chan)
274{
275 ulong ones_count, low, mid, high;
276 int sign;
277
278 if (wps->w.zeros_acc) {
279 if (--wps->w.zeros_acc) {
280 wps->w.slow_level [chan] -= (wps->w.slow_level [chan] + SLO) >> SLS;
281 return 0;
282 }
283 }
284 else if (!wps->w.holding_zero && !wps->w.holding_one && !(wps->w.median [0] [0] & ~1) && !(wps->w.median [0] [1] & ~1)) {
285 ulong mask;
286 int cbits;
287
288 for (cbits = 0; cbits < 33 && getbit (&wps->wvbits); ++cbits);
289
290 if (cbits == 33)
291 return WORD_EOF;
292
293 if (cbits < 2)
294 wps->w.zeros_acc = cbits;
295 else {
296 for (mask = 1, wps->w.zeros_acc = 0; --cbits; mask <<= 1)
297 if (getbit (&wps->wvbits))
298 wps->w.zeros_acc |= mask;
299
300 wps->w.zeros_acc |= mask;
301 }
302
303 if (wps->w.zeros_acc) {
304 wps->w.slow_level [chan] -= (wps->w.slow_level [chan] + SLO) >> SLS;
305 CLEAR (wps->w.median);
306 return 0;
307 }
308 }
309
310 if (wps->w.holding_zero)
311 ones_count = wps->w.holding_zero = 0;
312 else {
313#ifdef LIMIT_ONES
314 for (ones_count = 0; ones_count < (LIMIT_ONES + 1) && getbit (&wps->wvbits); ++ones_count);
315
316 if (ones_count == (LIMIT_ONES + 1))
317 return WORD_EOF;
318
319 if (ones_count == LIMIT_ONES) {
320 ulong mask;
321 int cbits;
322
323 for (cbits = 0; cbits < 33 && getbit (&wps->wvbits); ++cbits);
324
325 if (cbits == 33)
326 return WORD_EOF;
327
328 if (cbits < 2)
329 ones_count = cbits;
330 else {
331 for (mask = 1, ones_count = 0; --cbits; mask <<= 1)
332 if (getbit (&wps->wvbits))
333 ones_count |= mask;
334
335 ones_count |= mask;
336 }
337
338 ones_count += LIMIT_ONES;
339 }
340#else
341 for (ones_count = 0; getbit (&wps->wvbits); ++ones_count);
342#endif
343
344 if (wps->w.holding_one) {
345 wps->w.holding_one = ones_count & 1;
346 ones_count = (ones_count >> 1) + 1;
347 }
348 else {
349 wps->w.holding_one = ones_count & 1;
350 ones_count >>= 1;
351 }
352
353 wps->w.holding_zero = ~wps->w.holding_one & 1;
354 }
355
356 if ((wps->wphdr.flags & HYBRID_FLAG) && !chan)
357 update_error_limit (wps);
358
359 if (ones_count == 0) {
360 low = 0;
361 high = GET_MED (0) - 1;
362 DEC_MED0 ();
363 }
364 else {
365 low = GET_MED (0);
366 INC_MED0 ();
367
368 if (ones_count == 1) {
369 high = low + GET_MED (1) - 1;
370 DEC_MED1 ();
371 }
372 else {
373 low += GET_MED (1);
374 INC_MED1 ();
375
376 if (ones_count == 2) {
377 high = low + GET_MED (2) - 1;
378 DEC_MED2 ();
379 }
380 else {
381 low += (ones_count - 2) * GET_MED (2);
382 high = low + GET_MED (2) - 1;
383 INC_MED2 ();
384 }
385 }
386 }
387
388 mid = (high + low + 1) >> 1;
389
390 if (!wps->w.error_limit [chan])
391 mid = read_code (&wps->wvbits, high - low) + low;
392 else while (high - low > wps->w.error_limit [chan]) {
393 if (getbit (&wps->wvbits))
394 mid = (high + (low = mid) + 1) >> 1;
395 else
396 mid = ((high = mid - 1) + low + 1) >> 1;
397 }
398
399 sign = getbit (&wps->wvbits);
400
401 if (wps->wphdr.flags & HYBRID_BITRATE) {
402 wps->w.slow_level [chan] -= (wps->w.slow_level [chan] + SLO) >> SLS;
403 wps->w.slow_level [chan] += log2 (mid);
404 }
405
406 return sign ? ~mid : mid;
407}
408
409// Read a single unsigned value from the specified bitstream with a value
410// from 0 to maxcode. If there are exactly a power of two number of possible
411// codes then this will read a fixed number of bits; otherwise it reads the
412// minimum number of bits and then determines whether another bit is needed
413// to define the code.
414
415static ulong read_code (Bitstream *bs, ulong maxcode)
416{
417 int bitcount = count_bits (maxcode);
418 ulong extras = (1L << bitcount) - maxcode - 1, code;
419
420 if (!bitcount)
421 return 0;
422
423 getbits (&code, bitcount - 1, bs);
424 code &= (1L << (bitcount - 1)) - 1;
425
426 if (code >= extras) {
427 code = (code << 1) - extras;
428
429 if (getbit (bs))
430 ++code;
431 }
432
433 return code;
434}
435
436// The concept of a base 2 logarithm is used in many parts of WavPack. It is
437// a way of sufficiently accurately representing 32-bit signed and unsigned
438// values storing only 16 bits (actually fewer). It is also used in the hybrid
439// mode for quickly comparing the relative magnitude of large values (i.e.
440// division) and providing smooth exponentials using only addition.
441
442// These are not strict logarithms in that they become linear around zero and
443// can therefore represent both zero and negative values. They have 8 bits
444// of precision and in "roundtrip" conversions the total error never exceeds 1
445// part in 225 except for the cases of +/-115 and +/-195 (which error by 1).
446
447
448// This function returns the log2 for the specified 32-bit unsigned value.
449// The maximum value allowed is about 0xff800000 and returns 8447.
450
451static int log2 (unsigned long avalue)
452{
453 int dbits;
454
455 if ((avalue += avalue >> 9) < (1 << 8)) {
456 dbits = nbits_table [avalue];
457 return (dbits << 8) + log2_table [(avalue << (9 - dbits)) & 0xff];
458 }
459 else {
460 if (avalue < (1L << 16))
461 dbits = nbits_table [avalue >> 8] + 8;
462 else if (avalue < (1L << 24))
463 dbits = nbits_table [avalue >> 16] + 16;
464 else
465 dbits = nbits_table [avalue >> 24] + 24;
466
467 return (dbits << 8) + log2_table [(avalue >> (dbits - 9)) & 0xff];
468 }
469}
470
471// This function returns the original integer represented by the supplied
472// logarithm (at least within the provided accuracy). The log is signed,
473// but since a full 32-bit value is returned this can be used for unsigned
474// conversions as well (i.e. the input range is -8192 to +8447).
475
476long exp2s (int log)
477{
478 ulong value;
479
480 if (log < 0)
481 return -exp2s (-log);
482
483 value = exp2_table [log & 0xff] | 0x100;
484
485 if ((log >>= 8) <= 9)
486 return value >> (9 - log);
487 else
488 return value << (log - 9);
489}
490
491// These two functions convert internal weights (which are normally +/-1024)
492// to and from an 8-bit signed character version for storage in metadata. The
493// weights are clipped here in the case that they are outside that range.
494
495int restore_weight (char weight)
496{
497 int result;
498
499 if ((result = (int) weight << 3) > 0)
500 result += (result + 64) >> 7;
501
502 return result;
503}
diff --git a/apps/codecs/libwavpack/wputils.c b/apps/codecs/libwavpack/wputils.c
new file mode 100644
index 0000000000..21c399f517
--- /dev/null
+++ b/apps/codecs/libwavpack/wputils.c
@@ -0,0 +1,354 @@
1////////////////////////////////////////////////////////////////////////////
2// **** WAVPACK **** //
3// Hybrid Lossless Wavefile Compressor //
4// Copyright (c) 1998 - 2004 Conifer Software. //
5// All Rights Reserved. //
6// Distributed under the BSD Software License (see license.txt) //
7////////////////////////////////////////////////////////////////////////////
8
9// wputils.c
10
11// This module provides a high-level interface for decoding WavPack 4.0 audio
12// streams and files. WavPack data is read with a stream reading callback. No
13// direct seeking is provided for, but it is possible to start decoding
14// anywhere in a WavPack stream. In this case, WavPack will be able to provide
15// the sample-accurate position when it synchs with the data and begins
16// decoding.
17
18#include "wavpack.h"
19
20#include <string.h>
21
22///////////////////////////// local table storage ////////////////////////////
23
24const ulong sample_rates [] = { 6000, 8000, 9600, 11025, 12000, 16000, 22050,
25 24000, 32000, 44100, 48000, 64000, 88200, 96000, 192000 };
26
27///////////////////////////// executable code ////////////////////////////////
28
29static ulong read_next_header (read_stream infile, WavpackHeader *wphdr);
30
31// This function reads data from the specified stream in search of a valid
32// WavPack 4.0 audio block. If this fails in 1 megabyte (or an invalid or
33// unsupported WavPack block is encountered) then an appropriate message is
34// copied to "error" and NULL is returned, otherwise a pointer to a
35// WavpackContext structure is returned (which is used to call all other
36// functions in this module). This can be initiated at the beginning of a
37// WavPack file, or anywhere inside a WavPack file. To determine the exact
38// position within the file use WavpackGetSampleIndex(). For demonstration
39// purposes this uses a single static copy of the WavpackContext structure,
40// so obviously it cannot be used for more than one file at a time. Also,
41// this function will not handle "correction" files, plays only the first
42// two channels of multi-channel files, and is limited in resolution in some
43// large integer or floating point files (but always provides at least 24 bits
44// of resolution).
45
46static WavpackContext wpc;
47
48WavpackContext *WavpackOpenFileInput (read_stream infile, char *error)
49{
50 WavpackStream *wps = &wpc.stream;
51 ulong bcount;
52
53 CLEAR (wpc);
54 wpc.infile = infile;
55 wpc.total_samples = (ulong) -1;
56 wpc.norm_offset = 0;
57 wpc.open_flags = 0;
58
59 // open the source file for reading and store the size
60
61 while (!wps->wphdr.block_samples) {
62
63 bcount = read_next_header (wpc.infile, &wps->wphdr);
64
65 if (bcount == (ulong) -1) {
66 strcpy (error, "not compatible with this version of WavPack file!");
67 return NULL;
68 }
69
70 if ((wps->wphdr.flags & UNKNOWN_FLAGS) || wps->wphdr.version < 0x402 || wps->wphdr.version > 0x40f) {
71 strcpy (error, "not compatible with this version of WavPack file!");
72 return NULL;
73 }
74
75 if (wps->wphdr.block_samples && wps->wphdr.total_samples != (ulong) -1)
76 wpc.total_samples = wps->wphdr.total_samples;
77
78 if (!unpack_init (&wpc)) {
79 strcpy (error, wpc.error_message [0] ? wpc.error_message :
80 "not compatible with this version of WavPack file!");
81
82 return NULL;
83 }
84 }
85
86 wpc.config.flags &= ~0xff;
87 wpc.config.flags |= wps->wphdr.flags & 0xff;
88 wpc.config.bytes_per_sample = (wps->wphdr.flags & BYTES_STORED) + 1;
89 wpc.config.float_norm_exp = wps->float_norm_exp;
90
91 wpc.config.bits_per_sample = (wpc.config.bytes_per_sample * 8) -
92 ((wps->wphdr.flags & SHIFT_MASK) >> SHIFT_LSB);
93
94 if (!wpc.config.sample_rate) {
95 if (!wps || !wps->wphdr.block_samples || (wps->wphdr.flags & SRATE_MASK) == SRATE_MASK)
96 wpc.config.sample_rate = 44100;
97 else
98 wpc.config.sample_rate = sample_rates [(wps->wphdr.flags & SRATE_MASK) >> SRATE_LSB];
99 }
100
101 if (!wpc.config.num_channels) {
102 wpc.config.num_channels = (wps->wphdr.flags & MONO_FLAG) ? 1 : 2;
103 wpc.config.channel_mask = 0x5 - wpc.config.num_channels;
104 }
105
106 if (!(wps->wphdr.flags & FINAL_BLOCK))
107 wpc.reduced_channels = (wps->wphdr.flags & MONO_FLAG) ? 1 : 2;
108
109 return &wpc;
110}
111
112// This function obtains general information about an open file and returns
113// a mask with the following bit values:
114
115// MODE_LOSSLESS: file is lossless (pure lossless only)
116// MODE_HYBRID: file is hybrid mode (lossy part only)
117// MODE_FLOAT: audio data is 32-bit ieee floating point
118// MODE_HIGH: file was created in "high" mode (information only)
119// MODE_FAST: file was created in "fast" mode (information only)
120
121int WavpackGetMode (WavpackContext *wpc)
122{
123 int mode = 0;
124
125 if (wpc) {
126 if (wpc->config.flags & CONFIG_HYBRID_FLAG)
127 mode |= MODE_HYBRID;
128 else if (!(wpc->config.flags & CONFIG_LOSSY_MODE))
129 mode |= MODE_LOSSLESS;
130
131 if (wpc->lossy_blocks)
132 mode &= ~MODE_LOSSLESS;
133
134 if (wpc->config.flags & CONFIG_FLOAT_DATA)
135 mode |= MODE_FLOAT;
136
137 if (wpc->config.flags & CONFIG_HIGH_FLAG)
138 mode |= MODE_HIGH;
139
140 if (wpc->config.flags & CONFIG_FAST_FLAG)
141 mode |= MODE_FAST;
142 }
143
144 return mode;
145}
146
147// Unpack the specified number of samples from the current file position.
148// Note that "samples" here refers to "complete" samples, which would be
149// 2 longs for stereo files. The audio data is returned right-justified in
150// 32-bit longs in the endian mode native to the executing processor. So,
151// if the original data was 16-bit, then the values returned would be
152// +/-32k. Floating point data can also be returned if the source was
153// floating point data (and this is normalized to +/-1.0). The actual number
154// of samples unpacked is returned, which should be equal to the number
155// requested unless the end of fle is encountered or an error occurs.
156
157ulong WavpackUnpackSamples (WavpackContext *wpc, long *buffer, ulong samples)
158{
159 WavpackStream *wps = &wpc->stream;
160 ulong bcount, samples_unpacked = 0, samples_to_unpack;
161 int num_channels = wpc->config.num_channels;
162
163 while (samples) {
164 if (!wps->wphdr.block_samples || !(wps->wphdr.flags & INITIAL_BLOCK) ||
165 wps->sample_index >= wps->wphdr.block_index + wps->wphdr.block_samples) {
166 bcount = read_next_header (wpc->infile, &wps->wphdr);
167
168 if (bcount == (ulong) -1)
169 break;
170
171 if (wps->wphdr.version < 0x402 || wps->wphdr.version > 0x40f) {
172 strcpy (wpc->error_message, "not compatible with this version of WavPack file!");
173 break;
174 }
175
176 if (!wps->wphdr.block_samples || wps->sample_index == wps->wphdr.block_index)
177 if (!unpack_init (wpc))
178 break;
179 }
180
181 if (!wps->wphdr.block_samples || !(wps->wphdr.flags & INITIAL_BLOCK) ||
182 wps->sample_index >= wps->wphdr.block_index + wps->wphdr.block_samples)
183 continue;
184
185 if (wps->sample_index < wps->wphdr.block_index) {
186 samples_to_unpack = wps->wphdr.block_index - wps->sample_index;
187
188 if (samples_to_unpack > samples)
189 samples_to_unpack = samples;
190
191 wps->sample_index += samples_to_unpack;
192 samples_unpacked += samples_to_unpack;
193 samples -= samples_to_unpack;
194
195 if (wpc->reduced_channels)
196 samples_to_unpack *= wpc->reduced_channels;
197 else
198 samples_to_unpack *= num_channels;
199
200 while (samples_to_unpack--)
201 *buffer++ = 0;
202
203 continue;
204 }
205
206 samples_to_unpack = wps->wphdr.block_index + wps->wphdr.block_samples - wps->sample_index;
207
208 if (samples_to_unpack > samples)
209 samples_to_unpack = samples;
210
211 unpack_samples (wpc, buffer, samples_to_unpack);
212
213 if (wpc->reduced_channels)
214 buffer += samples_to_unpack * wpc->reduced_channels;
215 else
216 buffer += samples_to_unpack * num_channels;
217
218 samples_unpacked += samples_to_unpack;
219 samples -= samples_to_unpack;
220
221 if (wps->sample_index == wps->wphdr.block_index + wps->wphdr.block_samples) {
222 if (check_crc_error (wpc))
223 wpc->crc_errors++;
224 }
225
226 if (wps->sample_index == wpc->total_samples)
227 break;
228 }
229
230 return samples_unpacked;
231}
232
233// Get total number of samples contained in the WavPack file, or -1 if unknown
234
235ulong WavpackGetNumSamples (WavpackContext *wpc)
236{
237 return wpc ? wpc->total_samples : (ulong) -1;
238}
239
240// Get the current sample index position, or -1 if unknown
241
242ulong WavpackGetSampleIndex (WavpackContext *wpc)
243{
244 if (wpc)
245 return wpc->stream.sample_index;
246
247 return (ulong) -1;
248}
249
250// Get the number of errors encountered so far
251
252int WavpackGetNumErrors (WavpackContext *wpc)
253{
254 return wpc ? wpc->crc_errors : 0;
255}
256
257// return TRUE if any uncorrected lossy blocks were actually written or read
258
259int WavpackLossyBlocks (WavpackContext *wpc)
260{
261 return wpc ? wpc->lossy_blocks : 0;
262}
263
264// Returns the sample rate of the specified WavPack file
265
266ulong WavpackGetSampleRate (WavpackContext *wpc)
267{
268 return wpc ? wpc->config.sample_rate : 44100;
269}
270
271// Returns the number of channels of the specified WavPack file. Note that
272// this is the actual number of channels contained in the file, but this
273// version can only decode the first two.
274
275int WavpackGetNumChannels (WavpackContext *wpc)
276{
277 return wpc ? wpc->config.num_channels : 2;
278}
279
280// Returns the actual number of valid bits per sample contained in the
281// original file, which may or may not be a multiple of 8. Floating data
282// always has 32 bits, integers may be from 1 to 32 bits each. When this
283// value is not a multiple of 8, then the "extra" bits are located in the
284// LSBs of the results. That is, values are right justified when unpacked
285// into longs, but are left justified in the number of bytes used by the
286// original data.
287
288int WavpackGetBitsPerSample (WavpackContext *wpc)
289{
290 return wpc ? wpc->config.bits_per_sample : 16;
291}
292
293// Returns the number of bytes used for each sample (1 to 4) in the original
294// file. This is required information for the user of this module because the
295// audio data is returned in the LOWER bytes of the long buffer and must be
296// left-shifted 8, 16, or 24 bits if normalized longs are required.
297
298int WavpackGetBytesPerSample (WavpackContext *wpc)
299{
300 return wpc ? wpc->config.bytes_per_sample : 2;
301}
302
303// This function will return the actual number of channels decoded from the
304// file (which may or may not be less than the actual number of channels, but
305// will always be 1 or 2). Normally, this will be the front left and right
306// channels of a multi-channel file.
307
308int WavpackGetReducedChannels (WavpackContext *wpc)
309{
310 if (wpc)
311 return wpc->reduced_channels ? wpc->reduced_channels : wpc->config.num_channels;
312 else
313 return 2;
314}
315
316// Read from current file position until a valid 32-byte WavPack 4.0 header is
317// found and read into the specified pointer. The number of bytes skipped is
318// returned. If no WavPack header is found within 1 meg, then a -1 is returned
319// to indicate the error. No additional bytes are read past the header and it
320// is returned in the processor's native endian mode. Seeking is not required.
321
322static ulong read_next_header (read_stream infile, WavpackHeader *wphdr)
323{
324 char buffer [sizeof (*wphdr)], *sp = buffer + sizeof (*wphdr), *ep = sp;
325 ulong bytes_skipped = 0;
326 int bleft;
327
328 while (1) {
329 if (sp < ep) {
330 bleft = ep - sp;
331 memcpy (buffer, sp, bleft);
332 }
333 else
334 bleft = 0;
335
336 if (infile (buffer + bleft, sizeof (*wphdr) - bleft) != (long) sizeof (*wphdr) - bleft)
337 return -1;
338
339 sp = buffer;
340
341 if (*sp++ == 'w' && *sp == 'v' && *++sp == 'p' && *++sp == 'k' &&
342 !(*++sp & 1) && sp [2] < 16 && !sp [3] && sp [5] == 4 && sp [4] >= 2 && sp [4] <= 0xf) {
343 memcpy (wphdr, buffer, sizeof (*wphdr));
344 little_endian_to_native (wphdr, WavpackHeaderFormat);
345 return bytes_skipped;
346 }
347
348 while (sp < ep && *sp != 'w')
349 sp++;
350
351 if ((bytes_skipped += sp - buffer) > 1024 * 1024)
352 return -1;
353 }
354}