summaryrefslogtreecommitdiff
path: root/lib/rbcodec/codecs/libwavpack/pack.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/rbcodec/codecs/libwavpack/pack.c')
-rw-r--r--lib/rbcodec/codecs/libwavpack/pack.c470
1 files changed, 470 insertions, 0 deletions
diff --git a/lib/rbcodec/codecs/libwavpack/pack.c b/lib/rbcodec/codecs/libwavpack/pack.c
new file mode 100644
index 0000000000..a46d05fe14
--- /dev/null
+++ b/lib/rbcodec/codecs/libwavpack/pack.c
@@ -0,0 +1,470 @@
1////////////////////////////////////////////////////////////////////////////
2// **** WAVPACK **** //
3// Hybrid Lossless Wavefile Compressor //
4// Copyright (c) 1998 - 2005 Conifer Software. //
5// All Rights Reserved. //
6// Distributed under the BSD Software License (see license.txt) //
7////////////////////////////////////////////////////////////////////////////
8
9// pack.c
10
11// This module actually handles the compression of the audio data, except for
12// the entropy coding which is handled by the words? modules. For efficiency,
13// the conversion is isolated to tight loops that handle an entire buffer.
14
15#include "wavpack.h"
16
17#include <string.h>
18
19// This flag provides faster encoding speed at the expense of more code. The
20// improvement applies to 16-bit stereo lossless only.
21
22//////////////////////////////// local tables ///////////////////////////////
23
24// These two tables specify the characteristics of the decorrelation filters.
25// Each term represents one layer of the sequential filter, where positive
26// values indicate the relative sample involved from the same channel (1=prev),
27// 17 & 18 are special functions using the previous 2 samples, and negative
28// values indicate cross channel decorrelation (in stereo only).
29
30static const signed char default_terms [] = { 18,18,2,3,-2,0 };
31static const signed char high_terms [] = { 18,18,2,3,-2,18,2,4,7,5,3,6,0 };
32static const signed char fast_terms [] = { 17,17,0 };
33
34///////////////////////////// executable code ////////////////////////////////
35
36// This function initializes everything required to pack WavPack bitstreams
37// and must be called BEFORE any other function in this module.
38
39void pack_init (WavpackContext *wpc)
40{
41 WavpackStream *wps = &wpc->stream;
42 uint32_t flags = wps->wphdr.flags;
43 struct decorr_pass *dpp;
44 const signed char *term_string;
45 int ti;
46
47 wps->sample_index = 0;
48 CLEAR (wps->decorr_passes);
49
50 if (wpc->config.flags & CONFIG_HIGH_FLAG)
51 term_string = high_terms;
52 else if (wpc->config.flags & CONFIG_FAST_FLAG)
53 term_string = fast_terms;
54 else
55 term_string = default_terms;
56
57 for (dpp = wps->decorr_passes, ti = 0; term_string [ti]; ti++)
58 if (term_string [ti] >= 0 || (flags & CROSS_DECORR)) {
59 dpp->term = term_string [ti];
60 dpp++->delta = 2;
61 }
62 else if (!(flags & MONO_FLAG)) {
63 dpp->term = -3;
64 dpp++->delta = 2;
65 }
66
67 wps->num_terms = dpp - wps->decorr_passes;
68 init_words (wps);
69}
70
71// Allocate room for and copy the decorrelation terms from the decorr_passes
72// array into the specified metadata structure. Both the actual term id and
73// the delta are packed into single characters.
74
75static void write_decorr_terms (WavpackStream *wps, WavpackMetadata *wpmd)
76{
77 int tcount = wps->num_terms;
78 struct decorr_pass *dpp;
79 char *byteptr;
80
81 byteptr = wpmd->data = wpmd->temp_data;
82 wpmd->id = ID_DECORR_TERMS;
83
84 for (dpp = wps->decorr_passes; tcount--; ++dpp)
85 *byteptr++ = ((dpp->term + 5) & 0x1f) | ((dpp->delta << 5) & 0xe0);
86
87 wpmd->byte_length = byteptr - (char *) wpmd->data;
88}
89
90// Allocate room for and copy the decorrelation term weights from the
91// decorr_passes array into the specified metadata structure. The weights
92// range +/-1024, but are rounded and truncated to fit in signed chars for
93// metadata storage. Weights are separate for the two channels
94
95static void write_decorr_weights (WavpackStream *wps, WavpackMetadata *wpmd)
96{
97 int tcount = wps->num_terms;
98 struct decorr_pass *dpp;
99 signed char *byteptr;
100
101 byteptr = wpmd->data = wpmd->temp_data;
102 wpmd->id = ID_DECORR_WEIGHTS;
103
104 for (dpp = wps->decorr_passes; tcount--; ++dpp) {
105 dpp->weight_A = restore_weight (*byteptr++ = store_weight (dpp->weight_A));
106
107 if (!(wps->wphdr.flags & MONO_FLAG))
108 dpp->weight_B = restore_weight (*byteptr++ = store_weight (dpp->weight_B));
109 }
110
111 wpmd->byte_length = byteptr - (signed char *) wpmd->data;
112}
113
114// Allocate room for and copy the decorrelation samples from the decorr_passes
115// array into the specified metadata structure. The samples are signed 32-bit
116// values, but are converted to signed log2 values for storage in metadata.
117// Values are stored for both channels and are specified from the first term
118// with unspecified samples set to zero. The number of samples stored varies
119// with the actual term value, so those must obviously be specified before
120// these in the metadata list. Any number of terms can have their samples
121// specified from no terms to all the terms, however I have found that
122// sending more than the first term's samples is a waste. The "wcount"
123// variable can be set to the number of terms to have their samples stored.
124
125static void write_decorr_samples (WavpackStream *wps, WavpackMetadata *wpmd)
126{
127 int tcount = wps->num_terms, wcount = 1, temp;
128 struct decorr_pass *dpp;
129 uchar *byteptr;
130
131 byteptr = wpmd->data = wpmd->temp_data;
132 wpmd->id = ID_DECORR_SAMPLES;
133
134 for (dpp = wps->decorr_passes; tcount--; ++dpp)
135 if (wcount) {
136 if (dpp->term > MAX_TERM) {
137 dpp->samples_A [0] = exp2s (temp = log2s (dpp->samples_A [0]));
138 *byteptr++ = temp;
139 *byteptr++ = temp >> 8;
140 dpp->samples_A [1] = exp2s (temp = log2s (dpp->samples_A [1]));
141 *byteptr++ = temp;
142 *byteptr++ = temp >> 8;
143
144 if (!(wps->wphdr.flags & MONO_FLAG)) {
145 dpp->samples_B [0] = exp2s (temp = log2s (dpp->samples_B [0]));
146 *byteptr++ = temp;
147 *byteptr++ = temp >> 8;
148 dpp->samples_B [1] = exp2s (temp = log2s (dpp->samples_B [1]));
149 *byteptr++ = temp;
150 *byteptr++ = temp >> 8;
151 }
152 }
153 else if (dpp->term < 0) {
154 dpp->samples_A [0] = exp2s (temp = log2s (dpp->samples_A [0]));
155 *byteptr++ = temp;
156 *byteptr++ = temp >> 8;
157 dpp->samples_B [0] = exp2s (temp = log2s (dpp->samples_B [0]));
158 *byteptr++ = temp;
159 *byteptr++ = temp >> 8;
160 }
161 else {
162 int m = 0, cnt = dpp->term;
163
164 while (cnt--) {
165 dpp->samples_A [m] = exp2s (temp = log2s (dpp->samples_A [m]));
166 *byteptr++ = temp;
167 *byteptr++ = temp >> 8;
168
169 if (!(wps->wphdr.flags & MONO_FLAG)) {
170 dpp->samples_B [m] = exp2s (temp = log2s (dpp->samples_B [m]));
171 *byteptr++ = temp;
172 *byteptr++ = temp >> 8;
173 }
174
175 m++;
176 }
177 }
178
179 wcount--;
180 }
181 else {
182 CLEAR (dpp->samples_A);
183 CLEAR (dpp->samples_B);
184 }
185
186 wpmd->byte_length = byteptr - (uchar *) wpmd->data;
187}
188
189// Allocate room for and copy the configuration information into the specified
190// metadata structure. Currently, we just store the upper 3 bytes of
191// config.flags and only in the first block of audio data. Note that this is
192// for informational purposes not required for playback or decoding (like
193// whether high or fast mode was specified).
194
195static void write_config_info (WavpackContext *wpc, WavpackMetadata *wpmd)
196{
197 char *byteptr;
198
199 byteptr = wpmd->data = wpmd->temp_data;
200 wpmd->id = ID_CONFIG_BLOCK;
201 *byteptr++ = (char) (wpc->config.flags >> 8);
202 *byteptr++ = (char) (wpc->config.flags >> 16);
203 *byteptr++ = (char) (wpc->config.flags >> 24);
204 wpmd->byte_length = byteptr - (char *) wpmd->data;
205}
206
207// Pack an entire block of samples (either mono or stereo) into a completed
208// WavPack block. It is assumed that there is sufficient space for the
209// completed block at "wps->blockbuff" and that "wps->blockend" points to the
210// end of the available space. A return value of FALSE indicates an error.
211// Any unsent metadata is transmitted first, then required metadata for this
212// block is sent, and finally the compressed integer data is sent. If a "wpx"
213// stream is required for floating point data or large integer data, then this
214// must be handled outside this function. To find out how much data was written
215// the caller must look at the ckSize field of the written WavpackHeader, NOT
216// the one in the WavpackStream.
217
218int pack_start_block (WavpackContext *wpc)
219{
220 WavpackStream *wps = &wpc->stream;
221 WavpackMetadata wpmd;
222
223 memcpy (wps->blockbuff, &wps->wphdr, sizeof (WavpackHeader));
224
225 ((WavpackHeader *) wps->blockbuff)->ckSize = sizeof (WavpackHeader) - 8;
226 ((WavpackHeader *) wps->blockbuff)->block_index = wps->sample_index;
227 ((WavpackHeader *) wps->blockbuff)->block_samples = 0;
228 ((WavpackHeader *) wps->blockbuff)->crc = 0xffffffff;
229
230 if (wpc->wrapper_bytes) {
231 wpmd.id = ID_RIFF_HEADER;
232 wpmd.byte_length = wpc->wrapper_bytes;
233 wpmd.data = wpc->wrapper_data;
234 copy_metadata (&wpmd, wps->blockbuff, wps->blockend);
235 free_metadata (&wpmd);
236 wpc->wrapper_data = NULL;
237 wpc->wrapper_bytes = 0;
238 }
239
240 write_decorr_terms (wps, &wpmd);
241 copy_metadata (&wpmd, wps->blockbuff, wps->blockend);
242 free_metadata (&wpmd);
243
244 write_decorr_weights (wps, &wpmd);
245 copy_metadata (&wpmd, wps->blockbuff, wps->blockend);
246 free_metadata (&wpmd);
247
248 write_decorr_samples (wps, &wpmd);
249 copy_metadata (&wpmd, wps->blockbuff, wps->blockend);
250 free_metadata (&wpmd);
251
252 write_entropy_vars (wps, &wpmd);
253 copy_metadata (&wpmd, wps->blockbuff, wps->blockend);
254 free_metadata (&wpmd);
255
256 if ((wps->wphdr.flags & INITIAL_BLOCK) && !wps->sample_index) {
257 write_config_info (wpc, &wpmd);
258 copy_metadata (&wpmd, wps->blockbuff, wps->blockend);
259 free_metadata (&wpmd);
260 }
261
262 bs_open_write (&wps->wvbits, wps->blockbuff + ((WavpackHeader *) wps->blockbuff)->ckSize + 12, wps->blockend);
263
264 return TRUE;
265}
266
267static void decorr_stereo_pass (struct decorr_pass *dpp, int32_t *bptr, int32_t *eptr, int m);
268static void decorr_stereo_pass_18 (struct decorr_pass *dpp, int32_t *bptr, int32_t *eptr);
269static void decorr_stereo_pass_17 (struct decorr_pass *dpp, int32_t *bptr, int32_t *eptr);
270static void decorr_stereo_pass_m2 (struct decorr_pass *dpp, int32_t *bptr, int32_t *eptr);
271
272int pack_samples (WavpackContext *wpc, int32_t *buffer, uint32_t sample_count)
273{
274 WavpackStream *wps = &wpc->stream;
275 uint32_t flags = wps->wphdr.flags;
276 struct decorr_pass *dpp;
277 int32_t *bptr, *eptr;
278 int tcount, m;
279 uint32_t crc;
280
281 if (!sample_count)
282 return TRUE;
283
284 eptr = buffer + sample_count * ((flags & MONO_FLAG) ? 1 : 2);
285 m = ((WavpackHeader *) wps->blockbuff)->block_samples & (MAX_TERM - 1);
286 crc = ((WavpackHeader *) wps->blockbuff)->crc;
287
288 /////////////////////// handle lossless mono mode /////////////////////////
289
290 if (!(flags & HYBRID_FLAG) && (flags & MONO_FLAG))
291 for (bptr = buffer; bptr < eptr;) {
292 int32_t code;
293
294 crc = crc * 3 + (code = *bptr);
295
296 for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++) {
297 int32_t sam;
298
299 if (dpp->term > MAX_TERM) {
300 if (dpp->term & 1)
301 sam = 2 * dpp->samples_A [0] - dpp->samples_A [1];
302 else
303 sam = (3 * dpp->samples_A [0] - dpp->samples_A [1]) >> 1;
304
305 dpp->samples_A [1] = dpp->samples_A [0];
306 dpp->samples_A [0] = code;
307 }
308 else {
309 sam = dpp->samples_A [m];
310 dpp->samples_A [(m + dpp->term) & (MAX_TERM - 1)] = code;
311 }
312
313 code -= apply_weight_i (dpp->weight_A, sam);
314 update_weight (dpp->weight_A, 2, sam, code);
315 }
316
317 m = (m + 1) & (MAX_TERM - 1);
318 *bptr++ = code;
319 }
320
321 //////////////////// handle the lossless stereo mode //////////////////////
322
323 else if (!(flags & HYBRID_FLAG) && !(flags & MONO_FLAG)) {
324 if (flags & JOINT_STEREO)
325 for (bptr = buffer; bptr < eptr; bptr += 2) {
326 crc = crc * 9 + (bptr [0] * 3) + bptr [1];
327 bptr [1] += ((bptr [0] -= bptr [1]) >> 1);
328 }
329 else
330 for (bptr = buffer; bptr < eptr; bptr += 2)
331 crc = crc * 9 + (bptr [0] * 3) + bptr [1];
332
333 for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount-- ; dpp++) {
334 if (dpp->term == 17)
335 decorr_stereo_pass_17 (dpp, buffer, eptr);
336 else if (dpp->term == 18)
337 decorr_stereo_pass_18 (dpp, buffer, eptr);
338 else if (dpp->term >= 1 && dpp->term <= 7)
339 decorr_stereo_pass (dpp, buffer, eptr, m);
340 else if (dpp->term == -2)
341 decorr_stereo_pass_m2 (dpp, buffer, eptr);
342 }
343 }
344
345 send_words (buffer, sample_count, flags, &wps->w, &wps->wvbits);
346 ((WavpackHeader *) wps->blockbuff)->crc = crc;
347 ((WavpackHeader *) wps->blockbuff)->block_samples += sample_count;
348 wps->sample_index += sample_count;
349
350 return TRUE;
351}
352
353static void decorr_stereo_pass (struct decorr_pass *dpp, int32_t *bptr, int32_t *eptr, int m)
354{
355 int k = (m + dpp->term) & (MAX_TERM - 1);
356 int32_t sam;
357
358 while (bptr < eptr) {
359 dpp->samples_A [k] = bptr [0];
360 bptr [0] -= apply_weight_i (dpp->weight_A, (sam = dpp->samples_A [m]));
361 update_weight (dpp->weight_A, 2, sam, bptr [0]);
362 bptr++;
363 dpp->samples_B [k] = bptr [0];
364 bptr [0] -= apply_weight_i (dpp->weight_B, (sam = dpp->samples_B [m]));
365 update_weight (dpp->weight_B, 2, sam, bptr [0]);
366 bptr++;
367 m = (m + 1) & (MAX_TERM - 1);
368 k = (k + 1) & (MAX_TERM - 1);
369 }
370}
371
372static void decorr_stereo_pass_18 (struct decorr_pass *dpp, int32_t *bptr, int32_t *eptr)
373{
374 int32_t sam;
375
376 while (bptr < eptr) {
377 sam = (3 * dpp->samples_A [0] - dpp->samples_A [1]) >> 1;
378 dpp->samples_A [1] = dpp->samples_A [0];
379 dpp->samples_A [0] = bptr [0];
380 bptr [0] -= apply_weight_i (dpp->weight_A, sam);
381 update_weight (dpp->weight_A, 2, sam, bptr [0]);
382 bptr++;
383 sam = (3 * dpp->samples_B [0] - dpp->samples_B [1]) >> 1;
384 dpp->samples_B [1] = dpp->samples_B [0];
385 dpp->samples_B [0] = bptr [0];
386 bptr [0] -= apply_weight_i (dpp->weight_B, sam);
387 update_weight (dpp->weight_B, 2, sam, bptr [0]);
388 bptr++;
389 }
390}
391
392static void decorr_stereo_pass_m2 (struct decorr_pass *dpp, int32_t *bptr, int32_t *eptr)
393{
394 int32_t sam_A, sam_B;
395
396 for (; bptr < eptr; bptr += 2) {
397 sam_A = bptr [1];
398 sam_B = dpp->samples_B [0];
399 dpp->samples_B [0] = bptr [0];
400 bptr [0] -= apply_weight_i (dpp->weight_A, sam_A);
401 update_weight_clip (dpp->weight_A, 2, sam_A, bptr [0]);
402 bptr [1] -= apply_weight_i (dpp->weight_B, sam_B);
403 update_weight_clip (dpp->weight_B, 2, sam_B, bptr [1]);
404 }
405}
406
407static void decorr_stereo_pass_17 (struct decorr_pass *dpp, int32_t *bptr, int32_t *eptr)
408{
409 int32_t sam;
410
411 while (bptr < eptr) {
412 sam = 2 * dpp->samples_A [0] - dpp->samples_A [1];
413 dpp->samples_A [1] = dpp->samples_A [0];
414 dpp->samples_A [0] = bptr [0];
415 bptr [0] -= apply_weight_i (dpp->weight_A, sam);
416 update_weight (dpp->weight_A, 2, sam, bptr [0]);
417 bptr++;
418 sam = 2 * dpp->samples_B [0] - dpp->samples_B [1];
419 dpp->samples_B [1] = dpp->samples_B [0];
420 dpp->samples_B [0] = bptr [0];
421 bptr [0] -= apply_weight_i (dpp->weight_B, sam);
422 update_weight (dpp->weight_B, 2, sam, bptr [0]);
423 bptr++;
424 }
425}
426
427int pack_finish_block (WavpackContext *wpc)
428{
429 WavpackStream *wps = &wpc->stream;
430 struct decorr_pass *dpp;
431 uint32_t data_count;
432 int tcount, m;
433
434 m = ((WavpackHeader *) wps->blockbuff)->block_samples & (MAX_TERM - 1);
435
436 if (m)
437 for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++)
438 if (dpp->term > 0 && dpp->term <= MAX_TERM) {
439 int32_t temp_A [MAX_TERM], temp_B [MAX_TERM];
440 int k;
441
442 memcpy (temp_A, dpp->samples_A, sizeof (dpp->samples_A));
443 memcpy (temp_B, dpp->samples_B, sizeof (dpp->samples_B));
444
445 for (k = 0; k < MAX_TERM; k++) {
446 dpp->samples_A [k] = temp_A [m];
447 dpp->samples_B [k] = temp_B [m];
448 m = (m + 1) & (MAX_TERM - 1);
449 }
450 }
451
452 flush_word (&wps->w, &wps->wvbits);
453 data_count = bs_close_write (&wps->wvbits);
454
455 if (data_count) {
456 if (data_count != (uint32_t) -1) {
457 uchar *cptr = wps->blockbuff + ((WavpackHeader *) wps->blockbuff)->ckSize + 8;
458
459 *cptr++ = ID_WV_BITSTREAM | ID_LARGE;
460 *cptr++ = data_count >> 1;
461 *cptr++ = data_count >> 9;
462 *cptr++ = data_count >> 17;
463 ((WavpackHeader *) wps->blockbuff)->ckSize += data_count + 4;
464 }
465 else
466 return FALSE;
467 }
468
469 return TRUE;
470}