diff options
Diffstat (limited to 'apps/codecs/libwavpack/pack.c')
-rw-r--r-- | apps/codecs/libwavpack/pack.c | 270 |
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 | ||
30 | static const char default_terms [] = { 18,18,2,3,-2,0 }; | 30 | static const char default_terms [] = { 18,18,2,3,-2,0 }; |
31 | static const char high_terms [] = { 18,18,2,3,-2,18,2,4,7,5,3,6,8,-1,18,2,0 }; | 31 | static const char high_terms [] = { 18,18,2,3,-2,18,2,4,7,5,3,6,0 }; |
32 | static const char fast_terms [] = { 17,17,0 }; | 32 | static 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 | |||
216 | static int pack_samples (WavpackContext *wpc, long *buffer); | ||
217 | |||
218 | int 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 | ||
268 | static int pack_samples (WavpackContext *wpc, long *buffer) | 218 | int 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 | |||
267 | static void decorr_stereo_pass (struct decorr_pass *dpp, long *bptr, long *eptr, int m); | ||
268 | static void decorr_stereo_pass_18 (struct decorr_pass *dpp, long *bptr, long *eptr); | ||
269 | static void decorr_stereo_pass_17 (struct decorr_pass *dpp, long *bptr, long *eptr); | ||
270 | static void decorr_stereo_pass_m2 (struct decorr_pass *dpp, long *bptr, long *eptr); | ||
271 | |||
272 | int 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); | 353 | static 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 | |||
372 | static 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 | |||
392 | static 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 | |||
407 | static 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 | |||
427 | int 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 | } |