diff options
-rw-r--r-- | apps/codecs/libwavpack/pack.c | 270 | ||||
-rw-r--r-- | apps/codecs/libwavpack/wavpack.h | 20 | ||||
-rw-r--r-- | apps/codecs/libwavpack/words.c | 256 | ||||
-rw-r--r-- | apps/codecs/libwavpack/wputils.c | 98 | ||||
-rw-r--r-- | apps/plugins/wav2wv.c | 74 |
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 | ||
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 | } |
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 | ||
366 | void pack_init (WavpackContext *wpc); | 362 | void pack_init (WavpackContext *wpc); |
367 | int pack_block (WavpackContext *wpc, long *buffer); | 363 | int pack_start_block (WavpackContext *wpc); |
364 | int pack_samples (WavpackContext *wpc, long *buffer, ulong sample_count); | ||
365 | int 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); | |||
381 | int read_hybrid_profile (WavpackStream *wps, WavpackMetadata *wpmd); | 379 | int read_hybrid_profile (WavpackStream *wps, WavpackMetadata *wpmd); |
382 | long get_words (long *buffer, int nsamples, ulong flags, | 380 | long get_words (long *buffer, int nsamples, ulong flags, |
383 | struct words_data *w, Bitstream *bs); | 381 | struct words_data *w, Bitstream *bs); |
384 | void send_word_lossless (WavpackStream *wps, long value, int chan); | 382 | void send_word_lossless (long value, int chan, |
385 | void flush_word (WavpackStream *wps); | 383 | struct words_data *w, Bitstream *bs); |
384 | void send_words (long *buffer, int nsamples, ulong flags, | ||
385 | struct words_data *w, Bitstream *bs); | ||
386 | void flush_word (struct words_data *w, Bitstream *bs); | ||
386 | int log2s (long value); | 387 | int log2s (long value); |
387 | long exp2s (int log); | 388 | long exp2s (int log); |
388 | char store_weight (int weight); | 389 | char store_weight (int weight); |
@@ -421,9 +422,10 @@ int WavpackGetBytesPerSample (WavpackContext *wpc); | |||
421 | int WavpackGetNumChannels (WavpackContext *wpc); | 422 | int WavpackGetNumChannels (WavpackContext *wpc); |
422 | int WavpackGetReducedChannels (WavpackContext *wpc); | 423 | int WavpackGetReducedChannels (WavpackContext *wpc); |
423 | WavpackContext *WavpackOpenFileOutput (void); | 424 | WavpackContext *WavpackOpenFileOutput (void); |
424 | void WavpackSetOutputBuffer (WavpackContext *wpc, uchar *begin, uchar *end); | ||
425 | int WavpackSetConfiguration (WavpackContext *wpc, WavpackConfig *config, ulong total_samples); | 425 | int WavpackSetConfiguration (WavpackContext *wpc, WavpackConfig *config, ulong total_samples); |
426 | void WavpackAddWrapper (WavpackContext *wpc, void *data, ulong bcount); | 426 | void WavpackAddWrapper (WavpackContext *wpc, void *data, ulong bcount); |
427 | ulong WavpackPackSamples (WavpackContext *wpc, long *sample_buffer, ulong sample_count); | 427 | int WavpackStartBlock (WavpackContext *wpc, uchar *begin, uchar *end); |
428 | int WavpackPackSamples (WavpackContext *wpc, long *sample_buffer, ulong sample_count); | ||
429 | ulong 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 | ||
69 | const 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 | |||
80 | const 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 | |||
91 | const char nbits_table [] = { | 69 | const 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 | 517 | void 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 | |||
543 | void 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 | ||
649 | void flush_word (WavpackStream *wps) | 633 | void 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 | |||
373 | void 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 | ||
483 | void WavpackAddWrapper (WavpackContext *wpc, void *data, ulong bcount) | 470 | void 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 | |||
480 | int 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 | |||
500 | ulong 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; | 496 | int 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) { | 509 | ulong 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 | |||
97 | static long temp_buffer [TEMP_SAMPLES] IDATA_ATTR; | ||
98 | |||
95 | static int wav2wv (char *filename) | 99 | static 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!"); |