diff options
author | Thom Johansen <thomj@rockbox.org> | 2007-08-29 14:32:52 +0000 |
---|---|---|
committer | Thom Johansen <thomj@rockbox.org> | 2007-08-29 14:32:52 +0000 |
commit | c668de30852552a275b809a24648aa5a887eac65 (patch) | |
tree | 785f4423564a37743fe111eede84c58e034e3468 /apps | |
parent | 8f5f690760bbf9c8dbb3d142b12cbab236e79d26 (diff) | |
download | rockbox-c668de30852552a275b809a24648aa5a887eac65.tar.gz rockbox-c668de30852552a275b809a24648aa5a887eac65.zip |
FS #7286. Do correct rounding of final 16 bit samples before sending to DAC, for you golden-eared people.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@14514 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps')
-rw-r--r-- | apps/dsp.c | 8 | ||||
-rw-r--r-- | apps/dsp_cf.S | 40 | ||||
-rw-r--r-- | apps/plugins/test_codec.c | 13 |
3 files changed, 42 insertions, 19 deletions
diff --git a/apps/dsp.c b/apps/dsp.c index f05c6f14ce..699b0c5c67 100644 --- a/apps/dsp.c +++ b/apps/dsp.c | |||
@@ -414,10 +414,11 @@ static void sample_output_mono(int count, struct dsp_data *data, | |||
414 | { | 414 | { |
415 | const int32_t *s0 = src[0]; | 415 | const int32_t *s0 = src[0]; |
416 | const int scale = data->output_scale; | 416 | const int scale = data->output_scale; |
417 | const int dc_bias = 1 << (scale - 1); | ||
417 | 418 | ||
418 | do | 419 | do |
419 | { | 420 | { |
420 | int32_t lr = clip_sample_16(*s0++ >> scale); | 421 | int32_t lr = clip_sample_16((*s0++ + dc_bias) >> scale); |
421 | *dst++ = lr; | 422 | *dst++ = lr; |
422 | *dst++ = lr; | 423 | *dst++ = lr; |
423 | } | 424 | } |
@@ -433,11 +434,12 @@ static void sample_output_stereo(int count, struct dsp_data *data, | |||
433 | const int32_t *s0 = src[0]; | 434 | const int32_t *s0 = src[0]; |
434 | const int32_t *s1 = src[1]; | 435 | const int32_t *s1 = src[1]; |
435 | const int scale = data->output_scale; | 436 | const int scale = data->output_scale; |
437 | const int dc_bias = 1 << (scale - 1); | ||
436 | 438 | ||
437 | do | 439 | do |
438 | { | 440 | { |
439 | *dst++ = clip_sample_16(*s0++ >> scale); | 441 | *dst++ = clip_sample_16((*s0++ + dc_bias) >> scale); |
440 | *dst++ = clip_sample_16(*s1++ >> scale); | 442 | *dst++ = clip_sample_16((*s1++ + dc_bias) >> scale); |
441 | } | 443 | } |
442 | while (--count > 0); | 444 | while (--count > 0); |
443 | } | 445 | } |
diff --git a/apps/dsp_cf.S b/apps/dsp_cf.S index e4869b7c9a..fec00020b5 100644 --- a/apps/dsp_cf.S +++ b/apps/dsp_cf.S | |||
@@ -415,11 +415,11 @@ channels_process_sound_chan_karaoke: | |||
415 | .align 2 | 415 | .align 2 |
416 | .global sample_output_stereo | 416 | .global sample_output_stereo |
417 | sample_output_stereo: | 417 | sample_output_stereo: |
418 | lea.l -44(%sp), %sp | save registers | 418 | lea.l -48(%sp), %sp | save registers |
419 | move.l %macsr, %d1 | do it now as at many lines will | 419 | move.l %macsr, %d1 | do it now as at many lines will |
420 | movem.l %d1-%d7/%a2-%a5, (%sp) | be the far more common condition | 420 | movem.l %d1-%d7/%a2-%a6, (%sp) | be the far more common condition |
421 | move.l #0x80, %macsr | put emac unit in signed int mode | 421 | move.l #0x80, %macsr | put emac unit in signed int mode |
422 | movem.l 48(%sp), %a0-%a2/%a4 | | 422 | movem.l 52(%sp), %a0-%a2/%a4 | |
423 | lea.l (%a4, %a0.l*4), %a0 | %a0 = end address | 423 | lea.l (%a4, %a0.l*4), %a0 | %a0 = end address |
424 | move.l (%a1), %d1 | %a1 = multiplier: (1 << (16 - scale)) | 424 | move.l (%a1), %d1 | %a1 = multiplier: (1 << (16 - scale)) |
425 | sub.l #16, %d1 | | 425 | sub.l #16, %d1 | |
@@ -427,6 +427,7 @@ sample_output_stereo: | |||
427 | moveq.l #1, %d0 | | 427 | moveq.l #1, %d0 | |
428 | asl.l %d1, %d0 | | 428 | asl.l %d1, %d0 | |
429 | move.l %d0, %a1 | | 429 | move.l %d0, %a1 | |
430 | move.l #0x8000, %a6 | %a6 = rounding term | ||
430 | movem.l (%a2), %a2-%a3 | get L/R channel pointers | 431 | movem.l (%a2), %a2-%a3 | get L/R channel pointers |
431 | moveq.l #28, %d0 | %d0 = second line bound | 432 | moveq.l #28, %d0 | %d0 = second line bound |
432 | add.l %a4, %d0 | | 433 | add.l %a4, %d0 | |
@@ -438,6 +439,8 @@ sample_output_stereo: | |||
438 | bls.b 20f | line loop start | no? start line loop | 439 | bls.b 20f | line loop start | no? start line loop |
439 | 10: | long loop 0 | | 440 | 10: | long loop 0 | |
440 | move.l (%a2)+, %d1 | read longword from L and R | 441 | move.l (%a2)+, %d1 | read longword from L and R |
442 | move.l %a6, %acc0 | | ||
443 | move.l %acc0, %acc1 | | ||
441 | mac.l %d1, %a1, (%a3)+, %d2, %acc0 | shift L to high word | 444 | mac.l %d1, %a1, (%a3)+, %d2, %acc0 | shift L to high word |
442 | mac.l %d2, %a1, %acc1 | shift R to high word | 445 | mac.l %d2, %a1, %acc1 | shift R to high word |
443 | movclr.l %acc0, %d1 | get possibly saturated results | 446 | movclr.l %acc0, %d1 | get possibly saturated results |
@@ -451,6 +454,10 @@ sample_output_stereo: | |||
451 | lea.l -12(%a0), %a5 | %a5 = at or just before last line bound | 454 | lea.l -12(%a0), %a5 | %a5 = at or just before last line bound |
452 | 30: | line loop | | 455 | 30: | line loop | |
453 | move.l (%a3)+, %d4 | get next 4 R samples and scale | 456 | move.l (%a3)+, %d4 | get next 4 R samples and scale |
457 | move.l %a6, %acc0 | | ||
458 | move.l %acc0, %acc1 | | ||
459 | move.l %acc1, %acc2 | | ||
460 | move.l %acc2, %acc3 | | ||
454 | mac.l %d4, %a1, (%a3)+, %d5, %acc0 | with saturation | 461 | mac.l %d4, %a1, (%a3)+, %d5, %acc0 | with saturation |
455 | mac.l %d5, %a1, (%a3)+, %d6, %acc1 | | 462 | mac.l %d5, %a1, (%a3)+, %d6, %acc1 | |
456 | mac.l %d6, %a1, (%a3)+, %d7, %acc2 | | 463 | mac.l %d6, %a1, (%a3)+, %d7, %acc2 | |
@@ -460,6 +467,10 @@ sample_output_stereo: | |||
460 | movclr.l %acc1, %d5 | | 467 | movclr.l %acc1, %d5 | |
461 | movclr.l %acc2, %d6 | | 468 | movclr.l %acc2, %d6 | |
462 | movclr.l %acc3, %d7 | | 469 | movclr.l %acc3, %d7 | |
470 | move.l %a6, %acc0 | | ||
471 | move.l %acc0, %acc1 | | ||
472 | move.l %acc1, %acc2 | | ||
473 | move.l %acc2, %acc3 | | ||
463 | mac.l %d0, %a1, (%a2)+, %d1, %acc0 | get next 4 L samples and scale | 474 | mac.l %d0, %a1, (%a2)+, %d1, %acc0 | get next 4 L samples and scale |
464 | mac.l %d1, %a1, (%a2)+, %d2, %acc1 | with saturation | 475 | mac.l %d1, %a1, (%a2)+, %d2, %acc1 | with saturation |
465 | mac.l %d2, %a1, (%a2)+, %d3, %acc2 | | 476 | mac.l %d2, %a1, (%a2)+, %d3, %acc2 | |
@@ -484,6 +495,8 @@ sample_output_stereo: | |||
484 | bls.b 60f | output end | no? stop | 495 | bls.b 60f | output end | no? stop |
485 | 50: | long loop 1 | | 496 | 50: | long loop 1 | |
486 | move.l (%a2)+, %d1 | handle trailing longwords | 497 | move.l (%a2)+, %d1 | handle trailing longwords |
498 | move.l %a6, %acc0 | | ||
499 | move.l %acc0, %acc1 | | ||
487 | mac.l %d1, %a1, (%a3)+, %d2, %acc0 | the same way as leading ones | 500 | mac.l %d1, %a1, (%a3)+, %d2, %acc0 | the same way as leading ones |
488 | mac.l %d2, %a1, %acc1 | | 501 | mac.l %d2, %a1, %acc1 | |
489 | movclr.l %acc0, %d1 | | 502 | movclr.l %acc0, %d1 | |
@@ -494,9 +507,9 @@ sample_output_stereo: | |||
494 | cmp.l %a4, %a0 | | 507 | cmp.l %a4, %a0 | |
495 | bhi.b 50b | long loop 1 | 508 | bhi.b 50b | long loop 1 |
496 | 60: | output end | | 509 | 60: | output end | |
497 | movem.l (%sp), %d1-%d7/%a2-%a5 | restore registers | 510 | movem.l (%sp), %d1-%d7/%a2-%a6 | restore registers |
498 | move.l %d1, %macsr | | 511 | move.l %d1, %macsr | |
499 | lea.l 44(%sp), %sp | cleanup | 512 | lea.l 48(%sp), %sp | cleanup |
500 | rts | | 513 | rts | |
501 | .size sample_output_stereo, .-sample_output_stereo | 514 | .size sample_output_stereo, .-sample_output_stereo |
502 | 515 | ||
@@ -510,17 +523,18 @@ sample_output_stereo: | |||
510 | .align 2 | 523 | .align 2 |
511 | .global sample_output_mono | 524 | .global sample_output_mono |
512 | sample_output_mono: | 525 | sample_output_mono: |
513 | lea.l -28(%sp), %sp | save registers | 526 | lea.l -32(%sp), %sp | save registers |
514 | move.l %macsr, %d1 | do it now as at many lines will | 527 | move.l %macsr, %d1 | do it now as at many lines will |
515 | movem.l %d1-%d5/%a2-%a3, (%sp) | be the far more common condition | 528 | movem.l %d1-%d5/%a2-%a4, (%sp) | be the far more common condition |
516 | move.l #0x80, %macsr | put emac unit in signed int mode | 529 | move.l #0x80, %macsr | put emac unit in signed int mode |
517 | movem.l 32(%sp), %a0-%a3 | | 530 | movem.l 36(%sp), %a0-%a3 | |
518 | lea.l (%a3, %a0.l*4), %a0 | %a0 = end address | 531 | lea.l (%a3, %a0.l*4), %a0 | %a0 = end address |
519 | move.l (%a1), %d1 | %d5 = multiplier: (1 << (16 - scale)) | 532 | move.l (%a1), %d1 | %d5 = multiplier: (1 << (16 - scale)) |
520 | sub.l #16, %d1 | | 533 | sub.l #16, %d1 | |
521 | neg.l %d1 | | 534 | neg.l %d1 | |
522 | moveq.l #1, %d5 | | 535 | moveq.l #1, %d5 | |
523 | asl.l %d1, %d5 | | 536 | asl.l %d1, %d5 | |
537 | move.l #0x8000, %a4 | %a4 = rounding term | ||
524 | movem.l (%a2), %a2 | get source channel pointer | 538 | movem.l (%a2), %a2 | get source channel pointer |
525 | moveq.l #28, %d0 | %d0 = second line bound | 539 | moveq.l #28, %d0 | %d0 = second line bound |
526 | add.l %a3, %d0 | | 540 | add.l %a3, %d0 | |
@@ -532,6 +546,7 @@ sample_output_mono: | |||
532 | bls.b 20f | line loop start | no? start line loop | 546 | bls.b 20f | line loop start | no? start line loop |
533 | 10: | long loop 0 | | 547 | 10: | long loop 0 | |
534 | move.l (%a2)+, %d1 | read longword from L and R | 548 | move.l (%a2)+, %d1 | read longword from L and R |
549 | move.l %a4, %acc0 | | ||
535 | mac.l %d1, %d5, %acc0 | shift L to high word | 550 | mac.l %d1, %d5, %acc0 | shift L to high word |
536 | movclr.l %acc0, %d1 | get possibly saturated results | 551 | movclr.l %acc0, %d1 | get possibly saturated results |
537 | move.l %d1, %d2 | | 552 | move.l %d1, %d2 | |
@@ -544,6 +559,10 @@ sample_output_mono: | |||
544 | lea.l -12(%a0), %a1 | %a1 = at or just before last line bound | 559 | lea.l -12(%a0), %a1 | %a1 = at or just before last line bound |
545 | 30: | line loop | | 560 | 30: | line loop | |
546 | move.l (%a2)+, %d0 | get next 4 L samples and scale | 561 | move.l (%a2)+, %d0 | get next 4 L samples and scale |
562 | move.l %a4, %acc0 | | ||
563 | move.l %acc0, %acc1 | | ||
564 | move.l %acc1, %acc2 | | ||
565 | move.l %acc2, %acc3 | | ||
547 | mac.l %d0, %d5, (%a2)+, %d1, %acc0 | with saturation | 566 | mac.l %d0, %d5, (%a2)+, %d1, %acc0 | with saturation |
548 | mac.l %d1, %d5, (%a2)+, %d2, %acc1 | | 567 | mac.l %d1, %d5, (%a2)+, %d2, %acc1 | |
549 | mac.l %d2, %d5, (%a2)+, %d3, %acc2 | | 568 | mac.l %d2, %d5, (%a2)+, %d3, %acc2 | |
@@ -573,6 +592,7 @@ sample_output_mono: | |||
573 | bls.b 60f | output end | no? stop | 592 | bls.b 60f | output end | no? stop |
574 | 50: | loop loop 1 | | 593 | 50: | loop loop 1 | |
575 | move.l (%a2)+, %d1 | handle trailing longwords | 594 | move.l (%a2)+, %d1 | handle trailing longwords |
595 | move.l %a4, %acc0 | | ||
576 | mac.l %d1, %d5, %acc0 | the same way as leading ones | 596 | mac.l %d1, %d5, %acc0 | the same way as leading ones |
577 | movclr.l %acc0, %d1 | | 597 | movclr.l %acc0, %d1 | |
578 | move.l %d1, %d2 | | 598 | move.l %d1, %d2 | |
@@ -582,8 +602,8 @@ sample_output_mono: | |||
582 | cmp.l %a3, %a0 | | 602 | cmp.l %a3, %a0 | |
583 | bhi.b 50b | long loop 1 | | 603 | bhi.b 50b | long loop 1 | |
584 | 60: | output end | | 604 | 60: | output end | |
585 | movem.l (%sp), %d1-%d5/%a2-%a3 | restore registers | 605 | movem.l (%sp), %d1-%d5/%a2-%a4 | restore registers |
586 | move.l %d1, %macsr | | 606 | move.l %d1, %macsr | |
587 | lea.l 28(%sp), %sp | cleanup | 607 | lea.l 32(%sp), %sp | cleanup |
588 | rts | | 608 | rts | |
589 | .size sample_output_mono, .-sample_output_mono | 609 | .size sample_output_mono, .-sample_output_mono |
diff --git a/apps/plugins/test_codec.c b/apps/plugins/test_codec.c index c29094b372..4346a23304 100644 --- a/apps/plugins/test_codec.c +++ b/apps/plugins/test_codec.c | |||
@@ -221,7 +221,8 @@ static bool pcmbuf_insert_wav(const void *ch1, const void *ch2, int count) | |||
221 | const int32_t* data1_32; | 221 | const int32_t* data1_32; |
222 | const int32_t* data2_32; | 222 | const int32_t* data2_32; |
223 | unsigned char* p = wavbuffer; | 223 | unsigned char* p = wavbuffer; |
224 | int scale = wavinfo.sampledepth - 15; | 224 | const int scale = wavinfo.sampledepth - 15; |
225 | const int dc_bias = 1 << (scale - 1); | ||
225 | 226 | ||
226 | /* Prevent idle poweroff */ | 227 | /* Prevent idle poweroff */ |
227 | rb->reset_poweroff_timer(); | 228 | rb->reset_poweroff_timer(); |
@@ -266,18 +267,18 @@ static bool pcmbuf_insert_wav(const void *ch1, const void *ch2, int count) | |||
266 | { | 267 | { |
267 | case STEREO_INTERLEAVED: | 268 | case STEREO_INTERLEAVED: |
268 | while (count--) { | 269 | while (count--) { |
269 | int2le16(p, clip_sample((*data1_32++) >> scale)); | 270 | int2le16(p, clip_sample((*data1_32++ + dc_bias) >> scale)); |
270 | p += 2; | 271 | p += 2; |
271 | int2le16(p, clip_sample((*data1_32++) >> scale)); | 272 | int2le16(p, clip_sample((*data1_32++ + dc_bias) >> scale)); |
272 | p += 2; | 273 | p += 2; |
273 | } | 274 | } |
274 | break; | 275 | break; |
275 | 276 | ||
276 | case STEREO_NONINTERLEAVED: | 277 | case STEREO_NONINTERLEAVED: |
277 | while (count--) { | 278 | while (count--) { |
278 | int2le16(p, clip_sample((*data1_32++) >> scale)); | 279 | int2le16(p, clip_sample((*data1_32++ + dc_bias) >> scale)); |
279 | p += 2; | 280 | p += 2; |
280 | int2le16(p, clip_sample((*data2_32++) >> scale)); | 281 | int2le16(p, clip_sample((*data2_32++ + dc_bias) >> scale)); |
281 | p += 2; | 282 | p += 2; |
282 | } | 283 | } |
283 | 284 | ||
@@ -285,7 +286,7 @@ static bool pcmbuf_insert_wav(const void *ch1, const void *ch2, int count) | |||
285 | 286 | ||
286 | case STEREO_MONO: | 287 | case STEREO_MONO: |
287 | while (count--) { | 288 | while (count--) { |
288 | int2le16(p, clip_sample((*data1_32++) >> scale)); | 289 | int2le16(p, clip_sample((*data1_32++ + dc_bias) >> scale)); |
289 | p += 2; | 290 | p += 2; |
290 | } | 291 | } |
291 | break; | 292 | break; |