summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/codecs/libwavpack/pack.c270
-rw-r--r--apps/codecs/libwavpack/wavpack.h20
-rw-r--r--apps/codecs/libwavpack/words.c256
-rw-r--r--apps/codecs/libwavpack/wputils.c98
-rw-r--r--apps/plugins/wav2wv.c74
5 files changed, 369 insertions, 349 deletions
diff --git a/apps/codecs/libwavpack/pack.c b/apps/codecs/libwavpack/pack.c
index e695388d45..ef5feca367 100644
--- a/apps/codecs/libwavpack/pack.c
+++ b/apps/codecs/libwavpack/pack.c
@@ -28,7 +28,7 @@
28// values indicate cross channel decorrelation (in stereo only). 28// values indicate cross channel decorrelation (in stereo only).
29 29
30static const char default_terms [] = { 18,18,2,3,-2,0 }; 30static const char default_terms [] = { 18,18,2,3,-2,0 };
31static const char high_terms [] = { 18,18,2,3,-2,18,2,4,7,5,3,6,8,-1,18,2,0 }; 31static const char high_terms [] = { 18,18,2,3,-2,18,2,4,7,5,3,6,0 };
32static const char fast_terms [] = { 17,17,0 }; 32static const char fast_terms [] = { 17,17,0 };
33 33
34///////////////////////////// executable code //////////////////////////////// 34///////////////////////////// executable code ////////////////////////////////
@@ -205,56 +205,6 @@ static void write_config_info (WavpackContext *wpc, WavpackMetadata *wpmd)
205} 205}
206 206
207// Pack an entire block of samples (either mono or stereo) into a completed 207// Pack an entire block of samples (either mono or stereo) into a completed
208// WavPack block. This function is actually a shell for pack_samples() and
209// performs tasks like handling any shift required by the format, preprocessing
210// of floating point data or integer data over 24 bits wide, and implementing
211// the "extra" mode (via the extra?.c modules). It is assumed that there is
212// sufficient space for the completed block at "wps->blockbuff" and that
213// "wps->blockend" points to the end of the available space. A return value of
214// FALSE indicates an error.
215
216static int pack_samples (WavpackContext *wpc, long *buffer);
217
218int pack_block (WavpackContext *wpc, long *buffer)
219{
220 WavpackStream *wps = &wpc->stream;
221 ulong flags = wps->wphdr.flags, sflags = wps->wphdr.flags;
222 ulong sample_count = wps->wphdr.block_samples;
223
224 if (flags & SHIFT_MASK) {
225 int shift = (flags & SHIFT_MASK) >> SHIFT_LSB;
226 int mag = (flags & MAG_MASK) >> MAG_LSB;
227 ulong cnt = sample_count;
228 long *ptr = buffer;
229
230 if (flags & MONO_FLAG)
231 while (cnt--)
232 *ptr++ >>= shift;
233 else
234 while (cnt--) {
235 *ptr++ >>= shift;
236 *ptr++ >>= shift;
237 }
238
239 if ((mag -= shift) < 0)
240 flags &= ~MAG_MASK;
241 else
242 flags -= (1 << MAG_LSB) * shift;
243
244 wps->wphdr.flags = flags;
245 }
246
247 if (!pack_samples (wpc, buffer)) {
248 wps->wphdr.flags = sflags;
249 return FALSE;
250 }
251 else {
252 wps->wphdr.flags = sflags;
253 return TRUE;
254 }
255}
256
257// Pack an entire block of samples (either mono or stereo) into a completed
258// WavPack block. It is assumed that there is sufficient space for the 208// WavPack block. It is assumed that there is sufficient space for the
259// completed block at "wps->blockbuff" and that "wps->blockend" points to the 209// completed block at "wps->blockbuff" and that "wps->blockend" points to the
260// end of the available space. A return value of FALSE indicates an error. 210// end of the available space. A return value of FALSE indicates an error.
@@ -265,21 +215,18 @@ int pack_block (WavpackContext *wpc, long *buffer)
265// the caller must look at the ckSize field of the written WavpackHeader, NOT 215// the caller must look at the ckSize field of the written WavpackHeader, NOT
266// the one in the WavpackStream. 216// the one in the WavpackStream.
267 217
268static int pack_samples (WavpackContext *wpc, long *buffer) 218int pack_start_block (WavpackContext *wpc)
269{ 219{
270 WavpackStream *wps = &wpc->stream; 220 WavpackStream *wps = &wpc->stream;
271 ulong sample_count = wps->wphdr.block_samples;
272 ulong flags = wps->wphdr.flags, data_count;
273 struct decorr_pass *dpp;
274 WavpackMetadata wpmd; 221 WavpackMetadata wpmd;
275 int tcount, m = 0;
276 ulong crc, i;
277 long *bptr;
278 222
279 crc = 0xffffffff;
280 wps->wphdr.ckSize = sizeof (WavpackHeader) - 8;
281 memcpy (wps->blockbuff, &wps->wphdr, sizeof (WavpackHeader)); 223 memcpy (wps->blockbuff, &wps->wphdr, sizeof (WavpackHeader));
282 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
283 if (wpc->wrapper_bytes) { 230 if (wpc->wrapper_bytes) {
284 wpmd.id = ID_RIFF_HEADER; 231 wpmd.id = ID_RIFF_HEADER;
285 wpmd.byte_length = wpc->wrapper_bytes; 232 wpmd.byte_length = wpc->wrapper_bytes;
@@ -290,9 +237,6 @@ static int pack_samples (WavpackContext *wpc, long *buffer)
290 wpc->wrapper_bytes = 0; 237 wpc->wrapper_bytes = 0;
291 } 238 }
292 239
293 if (!sample_count)
294 return TRUE;
295
296 write_decorr_terms (wps, &wpmd); 240 write_decorr_terms (wps, &wpmd);
297 copy_metadata (&wpmd, wps->blockbuff, wps->blockend); 241 copy_metadata (&wpmd, wps->blockbuff, wps->blockend);
298 free_metadata (&wpmd); 242 free_metadata (&wpmd);
@@ -309,7 +253,7 @@ static int pack_samples (WavpackContext *wpc, long *buffer)
309 copy_metadata (&wpmd, wps->blockbuff, wps->blockend); 253 copy_metadata (&wpmd, wps->blockbuff, wps->blockend);
310 free_metadata (&wpmd); 254 free_metadata (&wpmd);
311 255
312 if ((flags & INITIAL_BLOCK) && !wps->sample_index) { 256 if ((wps->wphdr.flags & INITIAL_BLOCK) && !wps->sample_index) {
313 write_config_info (wpc, &wpmd); 257 write_config_info (wpc, &wpmd);
314 copy_metadata (&wpmd, wps->blockbuff, wps->blockend); 258 copy_metadata (&wpmd, wps->blockbuff, wps->blockend);
315 free_metadata (&wpmd); 259 free_metadata (&wpmd);
@@ -317,13 +261,37 @@ static int pack_samples (WavpackContext *wpc, long *buffer)
317 261
318 bs_open_write (&wps->wvbits, wps->blockbuff + ((WavpackHeader *) wps->blockbuff)->ckSize + 12, wps->blockend); 262 bs_open_write (&wps->wvbits, wps->blockbuff + ((WavpackHeader *) wps->blockbuff)->ckSize + 12, wps->blockend);
319 263
264 return TRUE;
265}
266
267static void decorr_stereo_pass (struct decorr_pass *dpp, long *bptr, long *eptr, int m);
268static void decorr_stereo_pass_18 (struct decorr_pass *dpp, long *bptr, long *eptr);
269static void decorr_stereo_pass_17 (struct decorr_pass *dpp, long *bptr, long *eptr);
270static void decorr_stereo_pass_m2 (struct decorr_pass *dpp, long *bptr, long *eptr);
271
272int pack_samples (WavpackContext *wpc, long *buffer, ulong sample_count)
273{
274 WavpackStream *wps = &wpc->stream;
275 ulong flags = wps->wphdr.flags;
276 struct decorr_pass *dpp;
277 long *bptr, *eptr;
278 int tcount, m;
279 ulong 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
320 /////////////////////// handle lossless mono mode ///////////////////////// 288 /////////////////////// handle lossless mono mode /////////////////////////
321 289
322 if (!(flags & HYBRID_FLAG) && (flags & MONO_FLAG)) 290 if (!(flags & HYBRID_FLAG) && (flags & MONO_FLAG))
323 for (bptr = buffer, i = 0; i < sample_count; ++i) { 291 for (bptr = buffer; bptr < eptr;) {
324 long code; 292 long code;
325 293
326 crc = crc * 3 + (code = *bptr++); 294 crc = crc * 3 + (code = *bptr);
327 295
328 for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++) { 296 for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++) {
329 long sam; 297 long sam;
@@ -347,68 +315,123 @@ static int pack_samples (WavpackContext *wpc, long *buffer)
347 } 315 }
348 316
349 m = (m + 1) & (MAX_TERM - 1); 317 m = (m + 1) & (MAX_TERM - 1);
350 send_word_lossless (wps, code, 0); 318 *bptr++ = code;
351 } 319 }
352 320
353 //////////////////// handle the lossless stereo mode ////////////////////// 321 //////////////////// handle the lossless stereo mode //////////////////////
354 322
355 else if (!(flags & HYBRID_FLAG) && !(flags & MONO_FLAG)) 323 else if (!(flags & HYBRID_FLAG) && !(flags & MONO_FLAG)) {
356 for (bptr = buffer, i = 0; i < sample_count; ++i, bptr += 2) { 324 if (flags & JOINT_STEREO)
357 long left, right, sam_A, sam_B; 325 for (bptr = buffer; bptr < eptr; bptr += 2) {
358 326 crc = crc * 9 + (bptr [0] * 3) + bptr [1];
359 crc = crc * 3 + (left = bptr [0]); 327 bptr [1] += ((bptr [0] -= bptr [1]) >> 1);
360 crc = crc * 3 + (right = bptr [1]); 328 }
361 329 else
362 if (flags & JOINT_STEREO) 330 for (bptr = buffer; bptr < eptr; bptr += 2)
363 right += ((left -= right) >> 1); 331 crc = crc * 9 + (bptr [0] * 3) + bptr [1];
364 332
365 for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount-- ; dpp++) { 333 for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount-- ; dpp++) {
366 if (dpp->term > 0) { 334 if (dpp->term == 17)
367 if (dpp->term > MAX_TERM) { 335 decorr_stereo_pass_17 (dpp, buffer, eptr);
368 if (dpp->term & 1) { 336 else if (dpp->term == 18)
369 sam_A = 2 * dpp->samples_A [0] - dpp->samples_A [1]; 337 decorr_stereo_pass_18 (dpp, buffer, eptr);
370 sam_B = 2 * dpp->samples_B [0] - dpp->samples_B [1]; 338 else if (dpp->term >= 1 && dpp->term <= 7)
371 } 339 decorr_stereo_pass (dpp, buffer, eptr, m);
372 else { 340 else if (dpp->term == -2)
373 sam_A = (3 * dpp->samples_A [0] - dpp->samples_A [1]) >> 1; 341 decorr_stereo_pass_m2 (dpp, buffer, eptr);
374 sam_B = (3 * dpp->samples_B [0] - dpp->samples_B [1]) >> 1; 342 }
375 } 343 }
376
377 dpp->samples_A [1] = dpp->samples_A [0];
378 dpp->samples_B [1] = dpp->samples_B [0];
379 dpp->samples_A [0] = left;
380 dpp->samples_B [0] = right;
381 }
382 else {
383 int k = (m + dpp->term) & (MAX_TERM - 1);
384 344
385 sam_A = dpp->samples_A [m]; 345 send_words (buffer, sample_count, flags, &wps->w, &wps->wvbits);
386 sam_B = dpp->samples_B [m]; 346 ((WavpackHeader *) wps->blockbuff)->crc = crc;
387 dpp->samples_A [k] = left; 347 ((WavpackHeader *) wps->blockbuff)->block_samples += sample_count;
388 dpp->samples_B [k] = right; 348 wps->sample_index += sample_count;
389 }
390 349
391 left -= apply_weight_i (dpp->weight_A, sam_A); 350 return TRUE;
392 right -= apply_weight_i (dpp->weight_B, sam_B); 351}
393 update_weight (dpp->weight_A, 2, sam_A, left);
394 update_weight (dpp->weight_B, 2, sam_B, right);
395 }
396 else {
397 sam_A = (dpp->term == -2) ? right : dpp->samples_A [0];
398 sam_B = (dpp->term == -1) ? left : dpp->samples_B [0];
399 dpp->samples_A [0] = right;
400 dpp->samples_B [0] = left;
401 left -= apply_weight_i (dpp->weight_A, sam_A);
402 right -= apply_weight_i (dpp->weight_B, sam_B);
403 update_weight_clip (dpp->weight_A, 2, sam_A, left);
404 update_weight_clip (dpp->weight_B, 2, sam_B, right);
405 }
406 }
407 352
408 m = (m + 1) & (MAX_TERM - 1); 353static void decorr_stereo_pass (struct decorr_pass *dpp, long *bptr, long *eptr, int m)
409 send_word_lossless (wps, left, 0); 354{
410 send_word_lossless (wps, right, 1); 355 int k = (m + dpp->term) & (MAX_TERM - 1);
411 } 356 long 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, long *bptr, long *eptr)
373{
374 long 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, long *bptr, long *eptr)
393{
394 long 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, long *bptr, long *eptr)
408{
409 long 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 ulong data_count;
432 int tcount, m;
433
434 m = ((WavpackHeader *) wps->blockbuff)->block_samples & (MAX_TERM - 1);
412 435
413 if (m) 436 if (m)
414 for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++) 437 for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++)
@@ -426,7 +449,7 @@ static int pack_samples (WavpackContext *wpc, long *buffer)
426 } 449 }
427 } 450 }
428 451
429 flush_word (wps); 452 flush_word (&wps->w, &wps->wvbits);
430 data_count = bs_close_write (&wps->wvbits); 453 data_count = bs_close_write (&wps->wvbits);
431 454
432 if (data_count) { 455 if (data_count) {
@@ -443,8 +466,5 @@ static int pack_samples (WavpackContext *wpc, long *buffer)
443 return FALSE; 466 return FALSE;
444 } 467 }
445 468
446 ((WavpackHeader *) wps->blockbuff)->crc = crc;
447
448 wps->sample_index += sample_count;
449 return TRUE; 469 return TRUE;
450} 470}
diff --git a/apps/codecs/libwavpack/wavpack.h b/apps/codecs/libwavpack/wavpack.h
index 12212bb0f8..bf9b95424e 100644
--- a/apps/codecs/libwavpack/wavpack.h
+++ b/apps/codecs/libwavpack/wavpack.h
@@ -234,10 +234,6 @@ typedef struct {
234 WavpackStream stream; 234 WavpackStream stream;
235 WavpackConfig config; 235 WavpackConfig config;
236 236
237 WavpackMetadata *metadata;
238 ulong metabytes;
239 int metacount;
240
241 uchar *wrapper_data; 237 uchar *wrapper_data;
242 int wrapper_bytes; 238 int wrapper_bytes;
243 239
@@ -364,7 +360,9 @@ int check_crc_error (WavpackContext *wpc);
364// pack.c 360// pack.c
365 361
366void pack_init (WavpackContext *wpc); 362void pack_init (WavpackContext *wpc);
367int pack_block (WavpackContext *wpc, long *buffer); 363int pack_start_block (WavpackContext *wpc);
364int pack_samples (WavpackContext *wpc, long *buffer, ulong sample_count);
365int pack_finish_block (WavpackContext *wpc);
368 366
369// metadata.c stuff 367// metadata.c stuff
370 368
@@ -381,8 +379,11 @@ void write_entropy_vars (WavpackStream *wps, WavpackMetadata *wpmd);
381int read_hybrid_profile (WavpackStream *wps, WavpackMetadata *wpmd); 379int read_hybrid_profile (WavpackStream *wps, WavpackMetadata *wpmd);
382long get_words (long *buffer, int nsamples, ulong flags, 380long get_words (long *buffer, int nsamples, ulong flags,
383 struct words_data *w, Bitstream *bs); 381 struct words_data *w, Bitstream *bs);
384void send_word_lossless (WavpackStream *wps, long value, int chan); 382void send_word_lossless (long value, int chan,
385void flush_word (WavpackStream *wps); 383 struct words_data *w, Bitstream *bs);
384void send_words (long *buffer, int nsamples, ulong flags,
385 struct words_data *w, Bitstream *bs);
386void flush_word (struct words_data *w, Bitstream *bs);
386int log2s (long value); 387int log2s (long value);
387long exp2s (int log); 388long exp2s (int log);
388char store_weight (int weight); 389char store_weight (int weight);
@@ -421,9 +422,10 @@ int WavpackGetBytesPerSample (WavpackContext *wpc);
421int WavpackGetNumChannels (WavpackContext *wpc); 422int WavpackGetNumChannels (WavpackContext *wpc);
422int WavpackGetReducedChannels (WavpackContext *wpc); 423int WavpackGetReducedChannels (WavpackContext *wpc);
423WavpackContext *WavpackOpenFileOutput (void); 424WavpackContext *WavpackOpenFileOutput (void);
424void WavpackSetOutputBuffer (WavpackContext *wpc, uchar *begin, uchar *end);
425int WavpackSetConfiguration (WavpackContext *wpc, WavpackConfig *config, ulong total_samples); 425int WavpackSetConfiguration (WavpackContext *wpc, WavpackConfig *config, ulong total_samples);
426void WavpackAddWrapper (WavpackContext *wpc, void *data, ulong bcount); 426void WavpackAddWrapper (WavpackContext *wpc, void *data, ulong bcount);
427ulong WavpackPackSamples (WavpackContext *wpc, long *sample_buffer, ulong sample_count); 427int WavpackStartBlock (WavpackContext *wpc, uchar *begin, uchar *end);
428int WavpackPackSamples (WavpackContext *wpc, long *sample_buffer, ulong sample_count);
429ulong WavpackFinishBlock (WavpackContext *wpc);
428 430
429 431
diff --git a/apps/codecs/libwavpack/words.c b/apps/codecs/libwavpack/words.c
index 75d8a86af7..d46bb56911 100644
--- a/apps/codecs/libwavpack/words.c
+++ b/apps/codecs/libwavpack/words.c
@@ -66,28 +66,6 @@
66 66
67///////////////////////////// local table storage //////////////////////////// 67///////////////////////////// local table storage ////////////////////////////
68 68
69const ulong bitset [] = {
70 1L << 0, 1L << 1, 1L << 2, 1L << 3,
71 1L << 4, 1L << 5, 1L << 6, 1L << 7,
72 1L << 8, 1L << 9, 1L << 10, 1L << 11,
73 1L << 12, 1L << 13, 1L << 14, 1L << 15,
74 1L << 16, 1L << 17, 1L << 18, 1L << 19,
75 1L << 20, 1L << 21, 1L << 22, 1L << 23,
76 1L << 24, 1L << 25, 1L << 26, 1L << 27,
77 1L << 28, 1L << 29, 1L << 30, 1L << 31
78};
79
80const ulong bitmask [] = {
81 (1L << 0) - 1, (1L << 1) - 1, (1L << 2) - 1, (1L << 3) - 1,
82 (1L << 4) - 1, (1L << 5) - 1, (1L << 6) - 1, (1L << 7) - 1,
83 (1L << 8) - 1, (1L << 9) - 1, (1L << 10) - 1, (1L << 11) - 1,
84 (1L << 12) - 1, (1L << 13) - 1, (1L << 14) - 1, (1L << 15) - 1,
85 (1L << 16) - 1, (1L << 17) - 1, (1L << 18) - 1, (1L << 19) - 1,
86 (1L << 20) - 1, (1L << 21) - 1, (1L << 22) - 1, (1L << 23) - 1,
87 (1L << 24) - 1, (1L << 25) - 1, (1L << 26) - 1, (1L << 27) - 1,
88 (1L << 28) - 1, (1L << 29) - 1, (1L << 30) - 1, 0x7fffffff
89};
90
91const char nbits_table [] = { 69const char nbits_table [] = {
92 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, // 0 - 15 70 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, // 0 - 15
93 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, // 16 - 31 71 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, // 16 - 31
@@ -536,177 +514,183 @@ static ulong read_code (Bitstream *bs, ulong maxcode)
536 return code; 514 return code;
537} 515}
538 516
539// This function is an optimized version of send_word() that only handles 517void send_words (long *buffer, int nsamples, ulong flags,
540// lossless (error_limit == 0). It does not return a value because it always 518 struct words_data *w, Bitstream *bs)
541// encodes the exact value passed.
542
543void send_word_lossless (WavpackStream *wps, long value, int chan)
544{ 519{
545 register struct words_data *w = &wps->w; 520 register struct entropy_data *c = w->c;
546 register struct entropy_data *c = w->c + chan; 521
547 int sign = (value < 0) ? 1 : 0; 522 if (!(flags & MONO_FLAG))
548 ulong ones_count, low, high; 523 nsamples *= 2;
549 524
550 if (!(wps->w.c [0].median [0] & ~1) && !wps->w.holding_zero && !(wps->w.c [1].median [0] & ~1)) { 525 while (nsamples--) {
551 if (wps->w.zeros_acc) { 526 long value = *buffer++;
552 if (value) 527 int sign = (value < 0) ? 1 : 0;
553 flush_word (wps); 528 ulong ones_count, low, high;
529
530 if (!(flags & MONO_FLAG))
531 c = w->c + (~nsamples & 1);
532
533 if (!(w->c [0].median [0] & ~1) && !w->holding_zero && !(w->c [1].median [0] & ~1)) {
534 if (w->zeros_acc) {
535 if (value)
536 flush_word (w, bs);
537 else {
538 w->zeros_acc++;
539 continue;
540 }
541 }
542 else if (value) {
543 putbit_0 (bs);
544 }
554 else { 545 else {
555 wps->w.zeros_acc++; 546 CLEAR (w->c [0].median);
556 return; 547 CLEAR (w->c [1].median);
548 w->zeros_acc = 1;
549 continue;
557 } 550 }
558 } 551 }
559 else if (value) {
560 putbit_0 (&wps->wvbits);
561 }
562 else {
563 CLEAR (wps->w.c [0].median);
564 CLEAR (wps->w.c [1].median);
565 wps->w.zeros_acc = 1;
566 return;
567 }
568 }
569
570 if (sign)
571 value = ~value;
572 552
573 if ((unsigned long) value < GET_MED (0)) { 553 if (sign)
574 ones_count = low = 0; 554 value = ~value;
575 high = GET_MED (0) - 1;
576 DEC_MED0 ();
577 }
578 else {
579 low = GET_MED (0);
580 INC_MED0 ();
581 555
582 if (value - low < GET_MED (1)) { 556 if ((unsigned long) value < GET_MED (0)) {
583 ones_count = 1; 557 ones_count = low = 0;
584 high = low + GET_MED (1) - 1; 558 high = GET_MED (0) - 1;
585 DEC_MED1 (); 559 DEC_MED0 ();
586 } 560 }
587 else { 561 else {
588 low += GET_MED (1); 562 low = GET_MED (0);
589 INC_MED1 (); 563 INC_MED0 ();
590 564
591 if (value - low < GET_MED (2)) { 565 if (value - low < GET_MED (1)) {
592 ones_count = 2; 566 ones_count = 1;
593 high = low + GET_MED (2) - 1; 567 high = low + GET_MED (1) - 1;
594 DEC_MED2 (); 568 DEC_MED1 ();
595 } 569 }
596 else { 570 else {
597 ones_count = 2 + (value - low) / GET_MED (2); 571 low += GET_MED (1);
598 low += (ones_count - 2) * GET_MED (2); 572 INC_MED1 ();
599 high = low + GET_MED (2) - 1; 573
600 INC_MED2 (); 574 if (value - low < GET_MED (2)) {
575 ones_count = 2;
576 high = low + GET_MED (2) - 1;
577 DEC_MED2 ();
578 }
579 else {
580 ones_count = 2 + (value - low) / GET_MED (2);
581 low += (ones_count - 2) * GET_MED (2);
582 high = low + GET_MED (2) - 1;
583 INC_MED2 ();
584 }
601 } 585 }
602 } 586 }
603 }
604 587
605 if (wps->w.holding_zero) { 588 if (w->holding_zero) {
606 if (ones_count) 589 if (ones_count)
607 wps->w.holding_one++; 590 w->holding_one++;
608 591
609 flush_word (wps); 592 flush_word (w, bs);
610 593
611 if (ones_count) { 594 if (ones_count) {
612 wps->w.holding_zero = 1; 595 w->holding_zero = 1;
613 ones_count--; 596 ones_count--;
597 }
598 else
599 w->holding_zero = 0;
614 } 600 }
615 else 601 else
616 wps->w.holding_zero = 0; 602 w->holding_zero = 1;
617 }
618 else
619 wps->w.holding_zero = 1;
620 603
621 wps->w.holding_one = ones_count * 2; 604 w->holding_one = ones_count * 2;
622 605
623 if (high != low) { 606 if (high != low) {
624 ulong maxcode = high - low, code = value - low; 607 ulong maxcode = high - low, code = value - low;
625 int bitcount = count_bits (maxcode); 608 int bitcount = count_bits (maxcode);
626 ulong extras = bitset [bitcount] - maxcode - 1; 609 ulong extras = (1L << bitcount) - maxcode - 1;
627 610
628 if (code < extras) { 611 if (code < extras) {
629 wps->w.pend_data |= code << wps->w.pend_count; 612 w->pend_data |= code << w->pend_count;
630 wps->w.pend_count += bitcount - 1; 613 w->pend_count += bitcount - 1;
631 } 614 }
632 else { 615 else {
633 wps->w.pend_data |= ((code + extras) >> 1) << wps->w.pend_count; 616 w->pend_data |= ((code + extras) >> 1) << w->pend_count;
634 wps->w.pend_count += bitcount - 1; 617 w->pend_count += bitcount - 1;
635 wps->w.pend_data |= ((code + extras) & 1) << wps->w.pend_count++; 618 w->pend_data |= ((code + extras) & 1) << w->pend_count++;
619 }
636 } 620 }
637 }
638 621
639 wps->w.pend_data |= ((long) sign << wps->w.pend_count++); 622 w->pend_data |= ((long) sign << w->pend_count++);
640 623
641 if (!wps->w.holding_zero) 624 if (!w->holding_zero)
642 flush_word (wps); 625 flush_word (w, bs);
626 }
643} 627}
644 628
645// Used by send_word() and send_word_lossless() to actually send most the 629// Used by send_word() and send_word_lossless() to actually send most the
646// accumulated data onto the bitstream. This is also called directly from 630// accumulated data onto the bitstream. This is also called directly from
647// clients when all words have been sent. 631// clients when all words have been sent.
648 632
649void flush_word (WavpackStream *wps) 633void flush_word (struct words_data *w, Bitstream *bs)
650{ 634{
651 if (wps->w.zeros_acc) { 635 int cbits;
652 int cbits = count_bits (wps->w.zeros_acc); 636
637 if (w->zeros_acc) {
638 cbits = count_bits (w->zeros_acc);
653 639
654 while (cbits--) { 640 while (cbits--) {
655 putbit_1 (&wps->wvbits); 641 putbit_1 (bs);
656 } 642 }
657 643
658 putbit_0 (&wps->wvbits); 644 putbit_0 (bs);
659 645
660 while (wps->w.zeros_acc > 1) { 646 while (w->zeros_acc > 1) {
661 putbit (wps->w.zeros_acc & 1, &wps->wvbits); 647 putbit (w->zeros_acc & 1, bs);
662 wps->w.zeros_acc >>= 1; 648 w->zeros_acc >>= 1;
663 } 649 }
664 650
665 wps->w.zeros_acc = 0; 651 w->zeros_acc = 0;
666 } 652 }
667 653
668 if (wps->w.holding_one) { 654 if (w->holding_one) {
669 if (wps->w.holding_one >= LIMIT_ONES) { 655 if (w->holding_one >= LIMIT_ONES) {
670 int cbits; 656 putbits ((1L << LIMIT_ONES) - 1, LIMIT_ONES + 1, bs);
671 657 w->holding_one -= LIMIT_ONES;
672 putbits ((1L << LIMIT_ONES) - 1, LIMIT_ONES + 1, &wps->wvbits); 658 cbits = count_bits (w->holding_one);
673 wps->w.holding_one -= LIMIT_ONES;
674 cbits = count_bits (wps->w.holding_one);
675 659
676 while (cbits--) { 660 while (cbits--) {
677 putbit_1 (&wps->wvbits); 661 putbit_1 (bs);
678 } 662 }
679 663
680 putbit_0 (&wps->wvbits); 664 putbit_0 (bs);
681 665
682 while (wps->w.holding_one > 1) { 666 while (w->holding_one > 1) {
683 putbit (wps->w.holding_one & 1, &wps->wvbits); 667 putbit (w->holding_one & 1, bs);
684 wps->w.holding_one >>= 1; 668 w->holding_one >>= 1;
685 } 669 }
686 670
687 wps->w.holding_zero = 0; 671 w->holding_zero = 0;
688 } 672 }
689 else 673 else
690 putbits (bitmask [wps->w.holding_one], wps->w.holding_one, &wps->wvbits); 674 putbits ((1L << w->holding_one) - 1, w->holding_one, bs);
691 675
692 wps->w.holding_one = 0; 676 w->holding_one = 0;
693 } 677 }
694 678
695 if (wps->w.holding_zero) { 679 if (w->holding_zero) {
696 putbit_0 (&wps->wvbits); 680 putbit_0 (bs);
697 wps->w.holding_zero = 0; 681 w->holding_zero = 0;
698 } 682 }
699 683
700 if (wps->w.pend_count) { 684 if (w->pend_count) {
701 685
702 while (wps->w.pend_count > 24) { 686 while (w->pend_count > 24) {
703 putbit (wps->w.pend_data & 1, &wps->wvbits); 687 putbit (w->pend_data & 1, bs);
704 wps->w.pend_data >>= 1; 688 w->pend_data >>= 1;
705 wps->w.pend_count--; 689 w->pend_count--;
706 } 690 }
707 691
708 putbits (wps->w.pend_data, wps->w.pend_count, &wps->wvbits); 692 putbits (w->pend_data, w->pend_count, bs);
709 wps->w.pend_data = wps->w.pend_count = 0; 693 w->pend_data = w->pend_count = 0;
710 } 694 }
711} 695}
712 696
diff --git a/apps/codecs/libwavpack/wputils.c b/apps/codecs/libwavpack/wputils.c
index 7f2ab14c44..479c18028f 100644
--- a/apps/codecs/libwavpack/wputils.c
+++ b/apps/codecs/libwavpack/wputils.c
@@ -365,17 +365,6 @@ WavpackContext *WavpackOpenFileOutput (void)
365 return &wpc; 365 return &wpc;
366} 366}
367 367
368// Set the output buffer limits. This must be done before calling
369// WavpackPackSamples(), but also may be done afterward to adjust
370// the usable buffer. Note that writing CANNOT wrap in the buffer; the
371// entire output block must fit in the buffer.
372
373void WavpackSetOutputBuffer (WavpackContext *wpc, uchar *begin, uchar *end)
374{
375 wpc->stream.blockbuff = begin;
376 wpc->stream.blockend = end;
377}
378
379// Set configuration for writing WavPack files. This must be done before 368// Set configuration for writing WavPack files. This must be done before
380// sending any actual samples, however it is okay to send wrapper or other 369// sending any actual samples, however it is okay to send wrapper or other
381// metadata before calling this. The "config" structure contains the following 370// metadata before calling this. The "config" structure contains the following
@@ -450,35 +439,33 @@ int WavpackSetConfiguration (WavpackContext *wpc, WavpackConfig *config, ulong t
450 if (!(config->flags & CONFIG_JOINT_OVERRIDE) || (config->flags & CONFIG_JOINT_STEREO)) 439 if (!(config->flags & CONFIG_JOINT_OVERRIDE) || (config->flags & CONFIG_JOINT_STEREO))
451 flags |= JOINT_STEREO; 440 flags |= JOINT_STEREO;
452 441
442 flags |= INITIAL_BLOCK | FINAL_BLOCK;
443
444 if (num_chans == 1) {
445 flags &= ~(JOINT_STEREO | CROSS_DECORR | HYBRID_BALANCE);
446 flags |= MONO_FLAG;
447 }
448
449 flags &= ~MAG_MASK;
450 flags += (1 << MAG_LSB) * ((flags & BYTES_STORED) * 8 + 7);
451
453 memcpy (wps->wphdr.ckID, "wvpk", 4); 452 memcpy (wps->wphdr.ckID, "wvpk", 4);
454 wps->wphdr.ckSize = sizeof (WavpackHeader) - 8; 453 wps->wphdr.ckSize = sizeof (WavpackHeader) - 8;
455 wps->wphdr.total_samples = wpc->total_samples; 454 wps->wphdr.total_samples = wpc->total_samples;
456 wps->wphdr.version = 0x403; 455 wps->wphdr.version = 0x403;
457 wps->wphdr.flags = flags; 456 wps->wphdr.flags = flags;
458 457
459 wps->wphdr.flags |= INITIAL_BLOCK;
460 wps->wphdr.flags |= FINAL_BLOCK;
461
462 if (num_chans == 1) {
463 wps->wphdr.flags &= ~(JOINT_STEREO | CROSS_DECORR | HYBRID_BALANCE);
464 wps->wphdr.flags |= MONO_FLAG;
465 }
466
467 pack_init (wpc); 458 pack_init (wpc);
468 return TRUE; 459 return TRUE;
469} 460}
470 461
471// Add wrapper (currently RIFF only) to WavPack blocks. This should be called 462// Add wrapper (currently RIFF only) to WavPack blocks. This should be called
472// before sending any audio samples for the RIFF header or after all samples 463// before sending any audio samples. If the exact contents of the RIFF header
473// have been sent for any RIFF trailer. WavpackFlushSamples() should be called 464// are not known because, for example, the file duration is uncertain or
474// between sending the last samples and calling this for trailer data to make 465// trailing chunks are possible, simply write a "dummy" header of the correct
475// sure that headers and trailers don't get mixed up in very short files. If 466// length. When all data has been written it will be possible to read the
476// the exact contents of the RIFF header are not known because, for example, 467// first block written and update the header directly. An example of this can
477// the file duration is uncertain or trailing chunks are possible, simply write 468// be found in the Audition filter.
478// a "dummy" header of the correct length. When all data has been written it
479// will be possible to read the first block written and update the header
480// directly. An example of this can be found in the Audition filter. A
481// return of FALSE indicates an error.
482 469
483void WavpackAddWrapper (WavpackContext *wpc, void *data, ulong bcount) 470void WavpackAddWrapper (WavpackContext *wpc, void *data, ulong bcount)
484{ 471{
@@ -486,38 +473,45 @@ void WavpackAddWrapper (WavpackContext *wpc, void *data, ulong bcount)
486 wpc->wrapper_bytes = bcount; 473 wpc->wrapper_bytes = bcount;
487} 474}
488 475
476// Start a WavPack block to be stored in the specified buffer. This must be
477// called before calling WavpackPackSamples(). Note that writing CANNOT wrap
478// in the buffer; the entire output block must fit in the buffer.
479
480int WavpackStartBlock (WavpackContext *wpc, uchar *begin, uchar *end)
481{
482 wpc->stream.blockbuff = begin;
483 wpc->stream.blockend = end;
484 return pack_start_block (wpc);
485}
486
489// Pack the specified samples. Samples must be stored in longs in the native 487// Pack the specified samples. Samples must be stored in longs in the native
490// endian format of the executing processor. The number of samples specified 488// endian format of the executing processor. The number of samples specified
491// indicates composite samples (sometimes called "frames"). So, the actual 489// indicates composite samples (sometimes called "frames"). So, the actual
492// number of data points would be this "sample_count" times the number of 490// number of data points would be this "sample_count" times the number of
493// channels. Note that samples are accumulated here until enough exist to 491// channels. The caller must decide how many samples to place in each
494// create a complete WavPack block (or several blocks for multichannel audio). 492// WavPack block (1/2 second is common), but this function may be called as
495// If an application wants to break a block at a specific sample, then it must 493// many times as desired to build the final block (and performs the actual
496// simply call WavpackFlushSamples() to force an early termination. Completed 494// compression during the call). A return of FALSE indicates an error.
497// WavPack blocks are send to the function provided in the initial call to
498// WavpackOpenFileOutput(). A return of FALSE indicates an error.
499
500ulong WavpackPackSamples (WavpackContext *wpc, long *sample_buffer, ulong sample_count)
501{
502 WavpackStream *wps = &wpc->stream;
503 ulong flags = wps->wphdr.flags;
504 ulong bcount;
505 int result;
506 495
507 flags &= ~MAG_MASK; 496int WavpackPackSamples (WavpackContext *wpc, long *sample_buffer, ulong sample_count)
508 flags += (1 << MAG_LSB) * ((flags & BYTES_STORED) * 8 + 7); 497{
498 if (!sample_count || pack_samples (wpc, sample_buffer, sample_count))
499 return TRUE;
509 500
510 wps->wphdr.block_index = wps->sample_index; 501 strcpy_loc (wpc->error_message, "output buffer overflowed!");
511 wps->wphdr.block_samples = sample_count; 502 return FALSE;
512 wps->wphdr.flags = flags; 503}
513 504
514 result = pack_block (wpc, sample_buffer); 505// Finish the WavPack block being built, returning the total size of the
506// block in bytes. Note that the possible conversion of the WavPack header to
507// little-endian takes place here.
515 508
516 if (!result) { 509ulong WavpackFinishBlock (WavpackContext *wpc)
517 strcpy_loc (wpc->error_message, "output buffer overflowed!"); 510{
518 return 0; 511 WavpackStream *wps = &wpc->stream;
519 } 512 ulong bcount;
520 513
514 pack_finish_block (wpc);
521 bcount = ((WavpackHeader *) wps->blockbuff)->ckSize + 8; 515 bcount = ((WavpackHeader *) wps->blockbuff)->ckSize + 8;
522 native_to_little_endian ((WavpackHeader *) wps->blockbuff, WavpackHeaderFormat); 516 native_to_little_endian ((WavpackHeader *) wps->blockbuff, WavpackHeaderFormat);
523 517
diff --git a/apps/plugins/wav2wv.c b/apps/plugins/wav2wv.c
index 24a7f8be6d..4cb7b14f2a 100644
--- a/apps/plugins/wav2wv.c
+++ b/apps/plugins/wav2wv.c
@@ -92,6 +92,10 @@ static void wvupdate (long start_tick,
92#endif 92#endif
93} 93}
94 94
95#define TEMP_SAMPLES 4096
96
97static long temp_buffer [TEMP_SAMPLES] IDATA_ATTR;
98
95static int wav2wv (char *filename) 99static int wav2wv (char *filename)
96{ 100{
97 int in_fd, out_fd, num_chans, error = false, last_buttons; 101 int in_fd, out_fd, num_chans, error = false, last_buttons;
@@ -144,7 +148,6 @@ static int wav2wv (char *filename)
144 } 148 }
145 149
146 wpc = WavpackOpenFileOutput (); 150 wpc = WavpackOpenFileOutput ();
147 WavpackSetOutputBuffer (wpc, output_buffer, output_buffer + 0x100000);
148 151
149 rb->memset (&config, 0, sizeof (config)); 152 rb->memset (&config, 0, sizeof (config));
150 config.bits_per_sample = 16; 153 config.bits_per_sample = 16;
@@ -153,6 +156,8 @@ static int wav2wv (char *filename)
153 num_chans = config.num_channels = native_header.NumChannels; 156 num_chans = config.num_channels = native_header.NumChannels;
154 total_samples = native_header.data_ckSize / native_header.BlockAlign; 157 total_samples = native_header.data_ckSize / native_header.BlockAlign;
155 158
159// config.flags |= CONFIG_HIGH_FLAG;
160
156 if (!WavpackSetConfiguration (wpc, &config, total_samples)) { 161 if (!WavpackSetConfiguration (wpc, &config, total_samples)) {
157 rb->splash(HZ*2, true, "internal error!"); 162 rb->splash(HZ*2, true, "internal error!");
158 rb->close (in_fd); 163 rb->close (in_fd);
@@ -178,7 +183,7 @@ static int wav2wv (char *filename)
178 wvupdate (start_tick, native_header.SampleRate, total_samples, 0, 0, 0); 183 wvupdate (start_tick, native_header.SampleRate, total_samples, 0, 0, 0);
179 184
180 for (samples_remaining = total_samples; samples_remaining;) { 185 for (samples_remaining = total_samples; samples_remaining;) {
181 unsigned long samples_count, bytes_count; 186 unsigned long samples_count, samples_to_pack, bytes_count;
182 int cnt, buttons; 187 int cnt, buttons;
183 long value, *lp; 188 long value, *lp;
184 char *cp; 189 char *cp;
@@ -197,33 +202,48 @@ static int wav2wv (char *filename)
197 } 202 }
198 203
199 total_bytes_read += bytes_count; 204 total_bytes_read += bytes_count;
200 cp = (char *) input_buffer + bytes_count; 205 WavpackStartBlock (wpc, output_buffer, output_buffer + 0x100000);
201 lp = input_buffer + samples_count * num_chans; 206 samples_to_pack = samples_count;
202 cnt = samples_count; 207 cp = (char *) input_buffer;
203 208
204 if (num_chans == 2) 209 while (samples_to_pack) {
205 while (cnt--) { 210 unsigned long samples_this_pass = TEMP_SAMPLES / num_chans;
206 value = *--cp << 8; 211
207 value += *--cp & 0xff; 212 if (samples_this_pass > samples_to_pack)
208 *--lp = value; 213 samples_this_pass = samples_to_pack;
209 value = *--cp << 8; 214
210 value += *--cp & 0xff; 215 lp = temp_buffer;
211 *--lp = value; 216 cnt = samples_this_pass;
212 } 217
213 else 218 if (num_chans == 2)
214 while (cnt--) { 219 while (cnt--) {
215 value = *--cp << 8; 220 value = *cp++ & 0xff;
216 value += *--cp & 0xff; 221 value += *cp++ << 8;
217 *--lp = value; 222 *lp++ = value;
218 } 223 value = *cp++ & 0xff;
219 224 value += *cp++ << 8;
220 bytes_count = WavpackPackSamples (wpc, input_buffer, samples_count); 225 *lp++ = value;
226 }
227 else
228 while (cnt--) {
229 value = *cp++ & 0xff;
230 value += *cp++ << 8;
231 *lp++ = value;
232 }
233
234 if (!WavpackPackSamples (wpc, temp_buffer, samples_this_pass)) {
235 rb->splash(HZ*2, true, "internal error!");
236 error = true;
237 break;
238 }
239
240 samples_to_pack -= samples_this_pass;
241 }
221 242
222 if (!bytes_count) { 243 if (error)
223 rb->splash(HZ*2, true, "internal error!");
224 error = true;
225 break; 244 break;
226 } 245
246 bytes_count = WavpackFinishBlock (wpc);
227 247
228 if (rb->write (out_fd, output_buffer, bytes_count) != (long) bytes_count) { 248 if (rb->write (out_fd, output_buffer, bytes_count) != (long) bytes_count) {
229 rb->splash(HZ*2, true, "could not write file!"); 249 rb->splash(HZ*2, true, "could not write file!");