summaryrefslogtreecommitdiff
path: root/apps/codecs/libwavpack/pack.c
diff options
context:
space:
mode:
authorDave Bryant <bryant@rockbox.org>2005-07-09 23:14:41 +0000
committerDave Bryant <bryant@rockbox.org>2005-07-09 23:14:41 +0000
commit85e03767f7f59eabfdb2e6aaffdebb63e48a0d00 (patch)
treed2553b044d4a88d2ee49a3e358b74759e9d16f14 /apps/codecs/libwavpack/pack.c
parentd1af08f9cb347009f57b282b734ae5f5abd878da (diff)
downloadrockbox-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.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}