summaryrefslogtreecommitdiff
path: root/apps/codecs/libwavpack/pack.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/codecs/libwavpack/pack.c')
-rw-r--r--apps/codecs/libwavpack/pack.c270
1 files changed, 145 insertions, 125 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}