summaryrefslogtreecommitdiff
path: root/apps/dsp.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/dsp.c')
-rw-r--r--apps/dsp.c112
1 files changed, 111 insertions, 1 deletions
diff --git a/apps/dsp.c b/apps/dsp.c
index d0f8b6d6d1..c490ed3824 100644
--- a/apps/dsp.c
+++ b/apps/dsp.c
@@ -41,6 +41,15 @@
41#define RESAMPLE_BUF_SIZE (256 * 4) /* Enough for 11,025 Hz -> 44,100 Hz*/ 41#define RESAMPLE_BUF_SIZE (256 * 4) /* Enough for 11,025 Hz -> 44,100 Hz*/
42#define DEFAULT_REPLAYGAIN 0x01000000 42#define DEFAULT_REPLAYGAIN 0x01000000
43 43
44/* These are the constants for the filters in the crossfeed */
45
46#define ATT 0x0CCCCCCDL /* 0.1 */
47#define ATT_COMP 0x73333333L /* 0.9 */
48#define LOW 0x4CCCCCCDL /* 0.6 */
49#define LOW_COMP 0x33333333L /* 0.4 */
50#define HIGH_NEG 0x9999999AL /* -0.2 */
51#define HIGH_COMP 0x66666666L /* 0.8 */
52
44#if defined(CPU_COLDFIRE) && !defined(SIMULATOR) 53#if defined(CPU_COLDFIRE) && !defined(SIMULATOR)
45 54
46/* Multiply two S.31 fractional integers and return the sign bit and the 55/* Multiply two S.31 fractional integers and return the sign bit and the
@@ -86,6 +95,20 @@
86 (t << 8) | (u & 0xff); \ 95 (t << 8) | (u & 0xff); \
87}) 96})
88 97
98
99#define ACC(acc, x, y) \
100 (void)acc; \
101 asm volatile ("mac.l %[a], %[b], %%acc0" \
102 : : [a] "i,r" (x), [b] "i,r" (y));
103#define GET_ACC(acc) \
104({ \
105 long t; \
106 (void)acc; \
107 asm volatile ("movclr.l %%acc0, %[t]" \
108 : [t] "=r" (t)); \
109 t; \
110})
111
89#else 112#else
90 113
91#define FRACMUL(x, y) (long) (((((long long) (x)) * ((long long) (y))) >> 31)) 114#define FRACMUL(x, y) (long) (((((long long) (x)) * ((long long) (y))) >> 31))
@@ -115,6 +138,7 @@ struct dsp_config
115 int frac_bits; 138 int frac_bits;
116 bool dither_enabled; 139 bool dither_enabled;
117 bool new_gain; 140 bool new_gain;
141 bool crossfeed_enabled;
118}; 142};
119 143
120struct resample_data 144struct resample_data
@@ -130,9 +154,18 @@ struct dither_data
130 long random; 154 long random;
131}; 155};
132 156
157struct crossfeed_data
158{
159 long lowpass[2];
160 long highpass[2];
161 long delay[2][13];
162 int index;
163};
164
133static struct dsp_config dsp_conf[2] IBSS_ATTR; 165static struct dsp_config dsp_conf[2] IBSS_ATTR;
134static struct dither_data dither_data[2] IBSS_ATTR; 166static struct dither_data dither_data[2] IBSS_ATTR;
135static struct resample_data resample_data[2][2] IBSS_ATTR; 167static struct resample_data resample_data[2][2] IBSS_ATTR;
168static struct crossfeed_data crossfeed_data IBSS_ATTR;
136 169
137extern int current_codec; 170extern int current_codec;
138struct dsp_config *dsp; 171struct dsp_config *dsp;
@@ -145,7 +178,6 @@ struct dsp_config *dsp;
145static long sample_buf[SAMPLE_BUF_SIZE] IBSS_ATTR; 178static long sample_buf[SAMPLE_BUF_SIZE] IBSS_ATTR;
146static long resample_buf[RESAMPLE_BUF_SIZE] IBSS_ATTR; 179static long resample_buf[RESAMPLE_BUF_SIZE] IBSS_ATTR;
147 180
148
149/* Convert at most count samples to the internal format, if needed. Returns 181/* Convert at most count samples to the internal format, if needed. Returns
150 * number of samples ready for further processing. Updates src to point 182 * number of samples ready for further processing. Updates src to point
151 * past the samples "consumed" and dst is set to point to the samples to 183 * past the samples "consumed" and dst is set to point to the samples to
@@ -410,6 +442,76 @@ static long dither_sample(long sample, long bias, long mask,
410 * the src array if gain was applied. 442 * the src array if gain was applied.
411 * Note that this must be called before the resampler. 443 * Note that this must be called before the resampler.
412 */ 444 */
445static void apply_crossfeed(long* src[], int count)
446{
447
448 if (dsp->crossfeed_enabled && src[0] != src[1])
449 {
450 long long a;
451
452 long low_left = crossfeed_data.lowpass[0];
453 long low_right = crossfeed_data.lowpass[1];
454 long high_left = crossfeed_data.highpass[0];
455 long high_right = crossfeed_data.highpass[1];
456 unsigned int index = crossfeed_data.index;
457
458 long left, right;
459
460 long * delay_l = crossfeed_data.delay[0];
461 long * delay_r = crossfeed_data.delay[1];
462
463 int i;
464
465 for (i = 0; i < count; i++)
466 {
467 /* use a low-pass filter on the signal */
468 left = src[0][i];
469 right = src[1][i];
470
471 ACC(a, LOW, low_left); ACC(a, LOW_COMP, left);
472 low_left = GET_ACC(a);
473
474 ACC(a, LOW, low_right); ACC(a, LOW_COMP, right);
475 low_right = GET_ACC(a);
476
477 /* use a high-pass filter on the signal */
478
479 ACC(a, HIGH_NEG, high_left); ACC(a, HIGH_COMP, left);
480 high_left = GET_ACC(a);
481
482 ACC(a, HIGH_NEG, high_right); ACC(a, HIGH_COMP, right);
483 high_right = GET_ACC(a);
484
485 /* New data is the high-passed signal + delayed and attenuated
486 * low-passed signal from the other channel */
487
488 ACC(a, ATT, delay_r[index]); ACC(a, ATT_COMP, high_left);
489 src[0][i] = GET_ACC(a);
490
491 ACC(a, ATT, delay_l[index]); ACC(a, ATT_COMP, high_right);
492 src[1][i] = GET_ACC(a);
493
494 /* Store the low-passed signal in the ringbuffer */
495
496 delay_l[index] = low_left;
497 delay_r[index] = low_right;
498
499 index = (index + 1) % 13;
500 }
501
502 crossfeed_data.index = index;
503 crossfeed_data.lowpass[0] = low_left;
504 crossfeed_data.lowpass[1] = low_right;
505 crossfeed_data.highpass[0] = high_left;
506 crossfeed_data.highpass[1] = high_right;
507
508 }
509}
510
511/* Apply a constant gain to the samples (e.g., for ReplayGain). May update
512 * the src array if gain was applied.
513 * Note that this must be called before the resampler.
514 */
413static void apply_gain(long* src[], int count) 515static void apply_gain(long* src[], int count)
414{ 516{
415 if (dsp->replaygain) 517 if (dsp->replaygain)
@@ -509,6 +611,7 @@ long dsp_process(char* dst, char* src[], long size)
509 size -= samples; 611 size -= samples;
510 apply_gain(tmp, samples); 612 apply_gain(tmp, samples);
511 samples = resample(tmp, samples); 613 samples = resample(tmp, samples);
614 apply_crossfeed(tmp, samples);
512 write_samples((short*) dst, tmp, samples); 615 write_samples((short*) dst, tmp, samples);
513 written += samples; 616 written += samples;
514 dst += samples * sizeof(short) * 2; 617 dst += samples * sizeof(short) * 2;
@@ -698,6 +801,13 @@ bool dsp_configure(int setting, void *value)
698 return 1; 801 return 1;
699} 802}
700 803
804void dsp_set_crossfeed(bool enable)
805{
806 if (enable)
807 memset(&crossfeed_data, 0, sizeof(crossfeed_data));
808 dsp->crossfeed_enabled = enable;
809}
810
701void dsp_set_replaygain(bool always) 811void dsp_set_replaygain(bool always)
702{ 812{
703 dsp = &dsp_conf[current_codec]; 813 dsp = &dsp_conf[current_codec];