diff options
author | Dave Bryant <bryant@rockbox.org> | 2005-07-09 23:14:41 +0000 |
---|---|---|
committer | Dave Bryant <bryant@rockbox.org> | 2005-07-09 23:14:41 +0000 |
commit | 85e03767f7f59eabfdb2e6aaffdebb63e48a0d00 (patch) | |
tree | d2553b044d4a88d2ee49a3e358b74759e9d16f14 /apps/codecs/libwavpack/pack.c | |
parent | d1af08f9cb347009f57b282b734ae5f5abd878da (diff) | |
download | rockbox-85e03767f7f59eabfdb2e6aaffdebb63e48a0d00.tar.gz rockbox-85e03767f7f59eabfdb2e6aaffdebb63e48a0d00.zip |
Reorganized encoder to allow compressing blocks in smaller chunks and
improved efficiency somewhat by looping through data in tighter passes.
Code is basically ready for an attempt at direct recording.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@7088 a1c6a512-1295-4272-9138-f99709370657
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 | } |