diff options
| author | Thom Johansen <thomj@rockbox.org> | 2006-04-11 13:49:05 +0000 |
|---|---|---|
| committer | Thom Johansen <thomj@rockbox.org> | 2006-04-11 13:49:05 +0000 |
| commit | 8238b49c747afaf462ab5bdd45a37417eeae4dd9 (patch) | |
| tree | 565d7ea84451eaa2eae3afbf6f9e481d95ff5d25 /apps/dsp.c | |
| parent | 6bd1f143facb6b832bd22a22020cfc6ae4540601 (diff) | |
| download | rockbox-8238b49c747afaf462ab5bdd45a37417eeae4dd9.zip rockbox-8238b49c747afaf462ab5bdd45a37417eeae4dd9.tar.gz rockbox-8238b49c747afaf462ab5bdd45a37417eeae4dd9.tar.bz2 rockbox-8238b49c747afaf462ab5bdd45a37417eeae4dd9.tar.xz | |
New crossfeed complete with no volume reducing bugs. Feedback on all the
new options is appreciated. Thanks to Dan Everton for the settings/GUI
code.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@9609 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/dsp.c')
| -rw-r--r-- | apps/dsp.c | 145 |
1 files changed, 60 insertions, 85 deletions
@@ -47,15 +47,6 @@ #define RESAMPLE_BUF_SIZE (256 * 4) /* Enough for 11,025 Hz -> 44,100 Hz*/ #define DEFAULT_REPLAYGAIN 0x01000000 -/* These are the constants for the filters in the crossfeed */ - -#define ATT 0x0CCCCCCDL /* 0.1 */ -#define ATT_COMP 0x73333333L /* 0.9 */ -#define LOW 0x4CCCCCCDL /* 0.6 */ -#define LOW_COMP 0x33333333L /* 0.4 */ -#define HIGH_NEG -0x66666666L /* -0.2 (not unsigned!) */ -#define HIGH_COMP 0x66666666L /* 0.8 */ - #if defined(CPU_COLDFIRE) && !defined(SIMULATOR) /* Multiply two S.31 fractional integers and return the sign bit and the @@ -209,10 +200,11 @@ struct dither_data struct crossfeed_data { - int32_t lowpass[2]; - int32_t highpass[2]; - int32_t delay[2][13]; - int index; + int32_t gain; /* Direct path gain */ + int32_t coefs[3]; /* Coefficients for the shelving filter */ + int32_t history[4]; /* Format is x[n - 1], y[n - 1] for both channels */ + int32_t delay[13][2]; + int index; /* Current index into the delay line */ }; /* Current setup is one lowshelf filters, three peaking filters and one @@ -522,71 +514,71 @@ static long dither_sample(int32_t sample, int32_t bias, int32_t mask, return output; } +void dsp_set_crossfeed(bool enable) +{ + dsp->crossfeed_enabled = enable; +} + +void dsp_set_crossfeed_direct_gain(int gain) +{ + /* Work around bug in get_replaygain_int which returns 0 for 0 dB */ + if (gain == 0) + crossfeed_data.gain = 0x7fffffff; + else + crossfeed_data.gain = get_replaygain_int(gain * -10) << 7; +} + +void dsp_set_crossfeed_cross_params(long lf_gain, long hf_gain, long cutoff) +{ + long g1 = get_replaygain_int(lf_gain * -10) << 3; + long g2 = get_replaygain_int(hf_gain * -10) << 3; + + filter_bishelf_coefs(0xffffffff/NATIVE_FREQUENCY*cutoff, g1, g2, + crossfeed_data.coefs); +} + /* Applies crossfeed to the stereo signal in src. * Crossfeed is a process where listening over speakers is simulated. This * is good for old hard panned stereo records, which might be quite fatiguing * to listen to on headphones with no crossfeed. */ #ifndef DSP_HAVE_ASM_CROSSFEED -static void apply_crossfeed(int32_t* src[], int count) +void apply_crossfeed(int32_t* src[], int count) { - int32_t a; /* accumulator */ - - int32_t low_left = crossfeed_data.lowpass[0]; - int32_t low_right = crossfeed_data.lowpass[1]; - int32_t high_left = crossfeed_data.highpass[0]; - int32_t high_right = crossfeed_data.highpass[1]; - unsigned int index = crossfeed_data.index; - + int32_t *hist_l = &crossfeed_data.history[0]; + int32_t *hist_r = &crossfeed_data.history[2]; + int32_t *delay = &crossfeed_data.delay[0][0]; + int32_t *coefs = &crossfeed_data.coefs[0]; + int32_t gain = crossfeed_data.gain; + int di = crossfeed_data.index; + + int32_t acc; int32_t left, right; - - int32_t* delay_l = crossfeed_data.delay[0]; - int32_t* delay_r = crossfeed_data.delay[1]; - int i; - - for (i = 0; i < count; i++) - { - /* use a low-pass filter on the signal */ + + for (i = 0; i < count; i++) { left = src[0][i]; right = src[1][i]; - - ACC_INIT(a, LOW, low_left); ACC(a, LOW_COMP, left); - low_left = GET_ACC(a); - - ACC_INIT(a, LOW, low_right); ACC(a, LOW_COMP, right); - low_right = GET_ACC(a); - - /* use a high-pass filter on the signal */ - - ACC_INIT(a, HIGH_NEG, high_left); ACC(a, HIGH_COMP, left); - high_left = GET_ACC(a); - - ACC_INIT(a, HIGH_NEG, high_right); ACC(a, HIGH_COMP, right); - high_right = GET_ACC(a); - - /* New data is the high-passed signal + delayed and attenuated - * low-passed signal from the other channel */ - - ACC_INIT(a, ATT, delay_r[index]); ACC(a, ATT_COMP, high_left); - src[0][i] = GET_ACC(a); - - ACC_INIT(a, ATT, delay_l[index]); ACC(a, ATT_COMP, high_right); - src[1][i] = GET_ACC(a); - - /* Store the low-passed signal in the ringbuffer */ - - delay_l[index] = low_left; - delay_r[index] = low_right; - - index = (index + 1) % 13; + + ACC_INIT(acc, delay[di*2], coefs[0]); + ACC(acc, hist_l[0], coefs[1]); + ACC(acc, hist_l[1], coefs[2]); + hist_l[1] = GET_ACC(acc) << 0; + hist_l[0] = delay[di*2]; + ACC_INIT(acc, delay[di*2 + 1], coefs[0]); + ACC(acc, hist_r[0], coefs[1]); + ACC(acc, hist_r[1], coefs[2]); + hist_r[1] = GET_ACC(acc) << 0; + hist_r[0] = delay[di*2 + 1]; + delay[di*2] = left; + delay[di*2 + 1] = right; + src[0][i] = FRACMUL(left, gain) + hist_r[1]; + src[1][i] = FRACMUL(right, gain) + hist_l[1]; + + if (++di > 12) + di = 0; } - - crossfeed_data.index = index; - crossfeed_data.lowpass[0] = low_left; - crossfeed_data.lowpass[1] = low_right; - crossfeed_data.highpass[0] = high_left; - crossfeed_data.highpass[1] = high_right; + crossfeed_data.index = di; } #endif @@ -633,13 +625,8 @@ void dsp_set_eq_coefs(int band) if (q == 0) q = 1; - /* The coef functions assume the EMAC unit is in fractional mode */ - #if defined(CPU_COLDFIRE) && !defined(SIMULATOR) - /* set emac unit for dsp processing, and save old macsr, we're running in - codec thread context at this point, so can't clobber it */ - unsigned long old_macsr = coldfire_get_macsr(); - coldfire_set_macsr(EMAC_FRACTIONAL | EMAC_SATURATE | EMAC_ROUND); - #endif + /* NOTE: The coef functions assume the EMAC unit is in fractional mode, + which it should be, since we're executed from the main thread. */ /* Assume a band is disabled if the gain is zero */ if (gain == 0) { @@ -654,11 +641,6 @@ void dsp_set_eq_coefs(int band) eq_data.enabled[band] = 1; } - - #if defined(CPU_COLDFIRE) && !defined(SIMULATOR) - /* set old macsr again */ - coldfire_set_macsr(old_macsr); - #endif } /* Apply EQ filters to those bands that have got it switched on. */ @@ -1068,13 +1050,6 @@ bool dsp_configure(int setting, void *value) return 1; } -void dsp_set_crossfeed(bool enable) -{ - if (enable) - memset(&crossfeed_data, 0, sizeof(crossfeed_data)); - dsp->crossfeed_enabled = enable; -} - void dsp_set_replaygain(bool always) { dsp = &dsp_conf[current_codec]; |