diff options
Diffstat (limited to 'apps/dsp.c')
-rw-r--r-- | apps/dsp.c | 92 |
1 files changed, 9 insertions, 83 deletions
diff --git a/apps/dsp.c b/apps/dsp.c index c5bbc8fbe9..6e6f702a30 100644 --- a/apps/dsp.c +++ b/apps/dsp.c | |||
@@ -28,6 +28,10 @@ | |||
28 | #include "replaygain.h" | 28 | #include "replaygain.h" |
29 | #include "debug.h" | 29 | #include "debug.h" |
30 | 30 | ||
31 | #ifndef SIMULATOR | ||
32 | #include <dsp_asm.h> | ||
33 | #endif | ||
34 | |||
31 | /* The "dither" code to convert the 24-bit samples produced by libmad was | 35 | /* The "dither" code to convert the 24-bit samples produced by libmad was |
32 | * taken from the coolplayer project - coolplayer.sourceforge.net | 36 | * taken from the coolplayer project - coolplayer.sourceforge.net |
33 | */ | 37 | */ |
@@ -517,90 +521,12 @@ static long dither_sample(int32_t sample, int32_t bias, int32_t mask, | |||
517 | return output; | 521 | return output; |
518 | } | 522 | } |
519 | 523 | ||
520 | /* Apply a constant gain to the samples (e.g., for ReplayGain). May update | 524 | /* Applies crossfeed to the stereo signal in src. |
521 | * the src array if gain was applied. | 525 | * Crossfeed is a process where listening over speakers is simulated. This |
522 | * Note that this must be called before the resampler. | 526 | * is good for old hard panned stereo records, which might be quite fatiguing |
527 | * to listen to on headphones with no crossfeed. | ||
523 | */ | 528 | */ |
524 | #if defined(CPU_COLDFIRE) && !defined(SIMULATOR) | 529 | #ifndef DSP_HAVE_ASM_CROSSFEED |
525 | static const long crossfeed_coefs[6] ICONST_ATTR = { | ||
526 | LOW, LOW_COMP, HIGH_NEG, HIGH_COMP, ATT, ATT_COMP | ||
527 | }; | ||
528 | |||
529 | static void apply_crossfeed(int32_t* src[], int count) | ||
530 | { | ||
531 | asm volatile ( | ||
532 | "lea.l crossfeed_data, %%a1 \n" | ||
533 | "lea.l (16, %%a1), %%a0 \n" | ||
534 | "movem.l (%%a1), %%d0-%%d3 \n" | ||
535 | "move.l (120, %%a1), %%d4 \n" | ||
536 | /* fetch left, right, LOW and LOW_COMP for first iteration */ | ||
537 | "move.l (%[src0]), %%d5 \n" | ||
538 | "move.l (%[src1]), %%d6 \n" | ||
539 | "move.l (%[coef])+, %%a1 \n" | ||
540 | "move.l (%[coef])+, %%a2 \n" | ||
541 | /* Register usage in loop: | ||
542 | * a0 = &delay[0][0], a1 & a2 = coefs | ||
543 | * d0 = low_left, d1 = low_right, | ||
544 | * d2 = high_left, d3 = high_right, | ||
545 | * d4 = delay line index, | ||
546 | * d5 = src[0][i], d6 = src[1][i]. | ||
547 | * The rest are described in asm constraint list. | ||
548 | */ | ||
549 | ".cfloop:" | ||
550 | /* LOW*low_left + LOW_COMP*left */ | ||
551 | "mac.l %%a1, %%d0, %%acc0 \n" | ||
552 | "mac.l %%a2, %%d5, %%acc0 \n" | ||
553 | /* LOW*low_right + LOW_COMP*right */ | ||
554 | "mac.l %%a1, %%d1, (%[coef])+, %%a1, %%acc1 \n" /* a1 = HIGH_NEG */ | ||
555 | "mac.l %%a2, %%d6, (%[coef])+, %%a2, %%acc1 \n" /* a2 = HIGH_COMP */ | ||
556 | "movclr.l %%acc0, %%d0 \n" /* get low_left */ | ||
557 | "movclr.l %%acc1, %%d1 \n" /* get low_right */ | ||
558 | /* HIGH_NEG*high_left + HIGH_COMP*left */ | ||
559 | "mac.l %%a1, %%d2, %%acc0 \n" | ||
560 | "mac.l %%a2, %%d5, %%acc0 \n" | ||
561 | /* HIGH_NEG*high_right + HIGH_COMP*right */ | ||
562 | "mac.l %%a1, %%d3, (%[coef])+, %%a1, %%acc1 \n" /* a1 = ATT */ | ||
563 | "mac.l %%a2, %%d6, (%[coef])+, %%a2, %%acc1 \n" /* a2 = ATT_COMP */ | ||
564 | "lea.l (-6*4, %[coef]), %[coef] \n" /* coef = &coefs[0] */ | ||
565 | "move.l (%%a0, %%d4*4), %%a3 \n" /* a3=delay[0][idx] */ | ||
566 | "move.l (52, %%a0, %%d4*4), %%d5 \n" /* d5=delay[1][idx] */ | ||
567 | "movclr.l %%acc0, %%d2 \n" /* get high_left */ | ||
568 | "movclr.l %%acc1, %%d3 \n" /* get high_right */ | ||
569 | /* ATT*delay_r + ATT_COMP*high_left */ | ||
570 | "mac.l %%a1, %%d5, (4, %[src0]), %%d5, %%acc0\n" /* d5 = src[0][i+1] */ | ||
571 | "mac.l %%a2, %%d2, (4, %[src1]), %%d6, %%acc0\n" /* d6 = src[1][i+1] */ | ||
572 | /* ATT*delay_l + ATT_COMP*high_right */ | ||
573 | "mac.l %%a1, %%a3, (%[coef])+, %%a1, %%acc1 \n" /* a1 = LOW */ | ||
574 | "mac.l %%a2, %%d3, (%[coef])+, %%a2, %%acc1 \n" /* a2 = LOW_COMP */ | ||
575 | |||
576 | /* save crossfed samples to output */ | ||
577 | "movclr.l %%acc0, %%a3 \n" | ||
578 | "move.l %%a3, (%[src0])+ \n" /* src[0][i++] = out_l */ | ||
579 | "movclr.l %%acc1, %%a3 \n" | ||
580 | "move.l %%a3, (%[src1])+ \n" /* src[1][i++] = out_r */ | ||
581 | "move.l %%d0, (%%a0, %%d4*4) \n" /* delay[0][index] = low_left */ | ||
582 | "move.l %%d1, (52, %%a0, %%d4*4)\n" /* delay[1][index] = low_right */ | ||
583 | "addq.l #1, %%d4 \n" /* index++ */ | ||
584 | "cmp.l #13, %%d4 \n" /* if (index >= 13) { */ | ||
585 | "jlt .nowrap \n" | ||
586 | "clr.l %%d4 \n" /* index = 0 */ | ||
587 | ".nowrap: \n" /* } */ | ||
588 | "subq.l #1, %[count] \n" | ||
589 | "jne .cfloop \n" | ||
590 | /* save data back to struct */ | ||
591 | "lea.l crossfeed_data, %%a1 \n" | ||
592 | "movem.l %%d0-%%d3, (%%a1) \n" | ||
593 | "move.l %%d4, (120, %%a1) \n" | ||
594 | /* NOTE: We _just_ have enough registers for our use here, clobber just | ||
595 | one more and GCC will fail. */ | ||
596 | : | ||
597 | : [count] "d" (count), | ||
598 | [src0] "a" (src[0]), [src1] "a" (src[1]), [coef] "a" (crossfeed_coefs) | ||
599 | : "d0", "d1", "d2", "d3", "d4", "d5", "d6", | ||
600 | "a0", "a1", "a2", "a3" | ||
601 | ); | ||
602 | } | ||
603 | #else | ||
604 | static void apply_crossfeed(int32_t* src[], int count) | 530 | static void apply_crossfeed(int32_t* src[], int count) |
605 | { | 531 | { |
606 | int32_t a; /* accumulator */ | 532 | int32_t a; /* accumulator */ |