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
This commit is contained in:
parent
6bd1f143fa
commit
8238b49c74
145
apps/dsp.c
145
apps/dsp.c
|
@ -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];
|
||||
|
|
|
@ -54,6 +54,8 @@ int dsp_stereo_mode(void);
|
|||
bool dsp_configure(int setting, void *value);
|
||||
void dsp_set_replaygain(bool always);
|
||||
void dsp_set_crossfeed(bool enable);
|
||||
void dsp_set_crossfeed_direct_gain(int gain);
|
||||
void dsp_set_crossfeed_cross_params(long lf_gain, long hf_gain, long cutoff);
|
||||
void dsp_set_eq(bool enable);
|
||||
void dsp_set_eq_precut(int precut);
|
||||
void dsp_set_eq_coefs(int band);
|
||||
|
|
102
apps/dsp_cf.S
102
apps/dsp_cf.S
|
@ -17,15 +17,6 @@
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
.section .idata,"aw",@progbits
|
||||
crossfeed_coefs:
|
||||
.long 0x4CCCCCCD | LOW
|
||||
.long 0x33333333 | LOW_COMP
|
||||
.long -0x66666666 | HIGH_NEG
|
||||
.long 0x66666666 | HIGH_COMP
|
||||
.long 0x0CCCCCCD | ATT
|
||||
.long 0x73333333 | ATT_COMP
|
||||
|
||||
.section .text
|
||||
.global apply_crossfeed
|
||||
apply_crossfeed:
|
||||
|
@ -36,68 +27,57 @@ apply_crossfeed:
|
|||
move.l (44+8, %sp), %d7 | d7 = count
|
||||
|
||||
lea.l crossfeed_data, %a1
|
||||
lea.l crossfeed_coefs, %a6
|
||||
lea.l (16, %a1), %a0 | a0 = &delay[0][0]
|
||||
movem.l (%a1), %d0-%d3 | fetch filter history samples
|
||||
move.l (120, %a1), %d4 | fetch delay line index
|
||||
move.l (%a4), %d5 | d5 = left sample
|
||||
move.l (%a5), %d6 | d6 = right sample
|
||||
move.l (%a6)+, %a1 | a1 = LOW value
|
||||
move.l (%a6)+, %a2 | a2 = LOW_COMP value
|
||||
lea.l (8*4, %a1), %a0 | a0 = &delay[0][0]
|
||||
move.l (%a1)+, %a6 | a6 = direct gain
|
||||
movem.l (3*4, %a1), %d0-%d3 | fetch filter history samples
|
||||
move.l (33*4, %a1), %d4 | fetch delay line index
|
||||
movem.l (%a1), %a1-%a3 | load filter coefs
|
||||
move.l %d4, %d5
|
||||
lsl.l #3, %d5
|
||||
add.l %d5, %a0 | point a0 to current delay position
|
||||
| lea.l (%d4*4, %a0), %a0
|
||||
| lea.l (%d4*4, %a0), %a0 | point a0 to current delay position
|
||||
/* Register usage in loop:
|
||||
* a0 = &delay[0][0], a1 & a2 = coefs, a3 = temp storage,
|
||||
* a4 = src[0], a5 = src[1], a6 = &crossfeed_coefs[0],
|
||||
* d0 = low_left, d1 = low_right,
|
||||
* d2 = high_left, d3 = high_right,
|
||||
* a0 = &delay[index][0], a1..a3 = b0, b1, a1 (filter coefs),
|
||||
* a4 = src[0], a5 = src[1], a6 = direct gain,
|
||||
* d0..d3 = history
|
||||
* d4 = delay line index,
|
||||
* d5 = src[0][i], d6 = src[1][i].
|
||||
* d5,d6 = temp.
|
||||
* d7 = count
|
||||
*/
|
||||
.cfloop:
|
||||
| LOW*low_left + LOW_COMP*left
|
||||
mac.l %a1, %d0, %acc0
|
||||
mac.l %a2, %d5, %acc0
|
||||
| LOW*low_right + LOW_COMP*right
|
||||
mac.l %a1, %d1, (%a6)+, %a1, %acc1 | a1 = HIGH_NEG
|
||||
mac.l %a2, %d6, (%a6)+, %a2, %acc1 | a2 = HIGH_COMP
|
||||
movclr.l %acc0, %d0 | get low_left
|
||||
movclr.l %acc1, %d1 | get low_right
|
||||
| HIGH_NEG*high_left + HIGH_COMP*left
|
||||
mac.l %a1, %d2, %acc0
|
||||
mac.l %a2, %d5, %acc0
|
||||
| HIGH_NEG*high_right + HIGH_COMP*right
|
||||
mac.l %a1, %d3, (%a6)+, %a1, %acc1 | a1 = ATT
|
||||
mac.l %a2, %d6, (%a6)+, %a2, %acc1 | a2 = ATT_COMP
|
||||
lea.l (-6*4, %a6), %a6 | coef = &coefs[0]
|
||||
move.l (%a0, %d4*4), %a3 | a3 = delay[0][idx]
|
||||
move.l (52, %a0, %d4*4), %d5 | d5 = delay[1][idx]
|
||||
movclr.l %acc0, %d2 | get high_left
|
||||
movclr.l %acc1, %d3 | get high_right
|
||||
| ATT*delay_r + ATT_COMP*high_left
|
||||
mac.l %a1, %d5, (4, %a4), %d5, %acc0 | d5 = src[0][i+1]
|
||||
mac.l %a2, %d2, (4, %a5), %d6, %acc0 | d6 = src[1][i+1]
|
||||
| ATT*delay_l + ATT_COMP*high_right
|
||||
mac.l %a1, %a3, (%a6)+, %a1, %acc1 | a1 = LOW
|
||||
mac.l %a2, %d3, (%a6)+, %a2, %acc1 | a2 = LOW_COMP
|
||||
|
||||
| save crossfed samples to output
|
||||
movclr.l %acc0, %a3
|
||||
move.l %a3, (%a4)+ | src[0][i++] = out_l
|
||||
movclr.l %acc1, %a3
|
||||
move.l %a3, (%a5)+ | src[1][i++] = out_r
|
||||
move.l %d0, (%a0, %d4*4) | delay[0][index] = low_left
|
||||
move.l %d1, (52, %a0, %d4*4) | delay[1][index] = low_right */
|
||||
addq.l #1, %d4 | index++ */
|
||||
cmp.l #13, %d4 | if (index >= 13) {
|
||||
mac.l %a2, %d0, (4, %a0), %d0, %acc0 | acc = b1*dr[n - 1] d0 = dr[n]
|
||||
mac.l %a1, %d0, %acc0 | acc += b0*dr[n]
|
||||
mac.l %a3, %d1, (%a4), %d5, %acc0 | acc += a1*y_l[n - 1], load left input
|
||||
move.l %acc0, %d1 | get filtered delayed sample
|
||||
mac.l %a6, %d5, %acc0 | acc += gain*x_l[n]
|
||||
movclr.l %acc0, %d6
|
||||
move.l %d6, (%a4)+ | write result
|
||||
|
||||
mac.l %a2, %d2, (%a0), %d2, %acc0 | acc = b1*dl[n - 1], d2 = dl[n]
|
||||
move.l %d5, (%a0)+ | save left input to delay line
|
||||
mac.l %a1, %d2, %acc0 | acc += b0*dl[n]
|
||||
mac.l %a3, %d3, (%a5), %d5, %acc0 | acc += a1*y_r[n - 1], load right input
|
||||
move.l %acc0, %d3 | get filtered delayed sample
|
||||
mac.l %a6, %d5, %acc0 | acc += gain*x_r[n]
|
||||
move.l %d5, (%a0)+ | save right input to delay line
|
||||
movclr.l %acc0, %d6
|
||||
move.l %d6, (%a5)+ | write result
|
||||
|
||||
addq.l #1, %d4 | index++
|
||||
moveq.l #13, %d6
|
||||
cmp.l %d6, %d4 | wrap index to 0 if it overflows
|
||||
jlt .nowrap
|
||||
clr.l %d4 | index = 0
|
||||
.nowrap: | }
|
||||
moveq.l #13*8, %d4
|
||||
sub.l %d4, %a0 | wrap back delay line ptr as well
|
||||
clr.l %d4
|
||||
.nowrap:
|
||||
subq.l #1, %d7
|
||||
jne .cfloop
|
||||
| save data back to struct
|
||||
lea.l crossfeed_data, %a1
|
||||
lea.l crossfeed_data + 4*4, %a1
|
||||
movem.l %d0-%d3, (%a1)
|
||||
move.l %d4, (120, %a1)
|
||||
move.l %d4, (30*4, %a1)
|
||||
movem.l (%sp), %d2-%d7/%a2-%a6
|
||||
lea.l (44, %sp), %sp
|
||||
rts
|
||||
|
|
28
apps/eq.c
28
apps/eq.c
|
@ -187,6 +187,34 @@ static long dbtoA(long db)
|
|||
return (dbtoatab[pos] << 16) + frac*diff;
|
||||
}
|
||||
|
||||
/* Calculate first order shelving filter coefficients.
|
||||
cutoff is a value from 0 to 0x80000000, where 0 represents 0 hz and
|
||||
0x80000000 represents nyquist (samplerate/2).
|
||||
ad is gain at 0 hz, and an is gain at Nyquist frequency. Both are s3.27
|
||||
format.
|
||||
c is a pointer where the coefs will be stored. The coefs are s0.31 format.
|
||||
Note that the filter is not compatible with the eq_filter routine.
|
||||
*/
|
||||
void filter_bishelf_coefs(unsigned long cutoff, long ad, long an, int32_t *c)
|
||||
{
|
||||
const long one = 1 << 27;
|
||||
long a0, a1;
|
||||
long b0, b1;
|
||||
long s, cs;
|
||||
s = fsincos(cutoff, &cs) >> 4;
|
||||
cs = one + (cs >> 4);
|
||||
|
||||
/* For max A = 4 (24 dB) */
|
||||
b0 = (FRACMUL(an, cs) << 4) + (FRACMUL(ad, s) << 4);
|
||||
b1 = (FRACMUL(ad, s) << 4) - (FRACMUL(an, cs) << 4);
|
||||
a0 = s + cs;
|
||||
a1 = s - cs;
|
||||
|
||||
c[0] = DIV64(b0, a0, 31);
|
||||
c[1] = DIV64(b1, a0, 31);
|
||||
c[2] = -DIV64(a1, a0, 31);
|
||||
}
|
||||
|
||||
/* Calculate second order section peaking filter coefficients.
|
||||
cutoff is a value from 0 to 0x80000000, where 0 represents 0 hz and
|
||||
0x80000000 represents nyquist (samplerate/2).
|
||||
|
|
|
@ -33,6 +33,7 @@ struct eqfilter {
|
|||
int32_t history[2][4];
|
||||
};
|
||||
|
||||
void filter_bishelf_coefs(unsigned long cutoff, long ad, long an, int32_t *c);
|
||||
void eq_pk_coefs(unsigned long cutoff, unsigned long Q, long db, int32_t *c);
|
||||
void eq_ls_coefs(unsigned long cutoff, unsigned long Q, long db, int32_t *c);
|
||||
void eq_hs_coefs(unsigned long cutoff, unsigned long Q, long db, int32_t *c);
|
||||
|
|
|
@ -8408,3 +8408,69 @@
|
|||
*: "pixels"
|
||||
</voice>
|
||||
</phrase>
|
||||
<phrase>
|
||||
id: LANG_CROSSFEED_DIRECT_GAIN
|
||||
desc: in crossfeed settings
|
||||
user:
|
||||
<source>
|
||||
*: "Direct Gain"
|
||||
</source>
|
||||
<dest>
|
||||
*: "Direct Gain"
|
||||
</dest>
|
||||
<voice>
|
||||
*: "Direct gain"
|
||||
</voice>
|
||||
</phrase>
|
||||
<phrase>
|
||||
id: LANG_CROSSFEED_CROSS_GAIN
|
||||
desc: in crossfeed settings
|
||||
<source>
|
||||
*: "Cross Gain"
|
||||
</source>
|
||||
<dest>
|
||||
*: "Cross Gain"
|
||||
</dest>
|
||||
<voice>
|
||||
*: "Cross gain"
|
||||
</voice>
|
||||
</phrase>
|
||||
<phrase>
|
||||
id: LANG_CROSSFEED_HF_ATTENUATION
|
||||
desc: in crossfeed settings
|
||||
<source>
|
||||
*: "High-Frequency Attenuation"
|
||||
</source>
|
||||
<dest>
|
||||
*: "High-Frequency Attenuation"
|
||||
</dest>
|
||||
<voice>
|
||||
*: "High-frequency attenuation"
|
||||
</voice>
|
||||
</phrase>
|
||||
<phrase>
|
||||
id: LANG_CROSSFEED_HF_CUTOFF
|
||||
desc: in crossfeed settings
|
||||
<source>
|
||||
*: "High-Frequency Cutoff"
|
||||
</source>
|
||||
<dest>
|
||||
*: "High-Frequency Cutoff"
|
||||
</dest>
|
||||
<voice>
|
||||
*: "High-frequency cutoff"
|
||||
</voice>
|
||||
</phrase>
|
||||
<phrase>
|
||||
id: LANG_UNIT_HERTZ
|
||||
desc: in sound settings
|
||||
<source>
|
||||
*: "Hz"
|
||||
</source>
|
||||
<dest>
|
||||
*: "Hz"
|
||||
</dest>
|
||||
<voice>
|
||||
*: ""
|
||||
</voice>
|
||||
</phrase>
|
||||
|
|
|
@ -94,7 +94,7 @@ const char rec_base_directory[] = REC_BASE_DIR;
|
|||
#include "dsp.h"
|
||||
#endif
|
||||
|
||||
#define CONFIG_BLOCK_VERSION 39
|
||||
#define CONFIG_BLOCK_VERSION 40
|
||||
#define CONFIG_BLOCK_SIZE 512
|
||||
#define RTC_BLOCK_SIZE 44
|
||||
|
||||
|
@ -488,6 +488,10 @@ static const struct bit_entry hd_bits[] =
|
|||
{4, S_O(crossfade_fade_out_duration), 0, "crossfade fade out duration", NULL},
|
||||
{1, S_O(crossfade_fade_out_mixmode), 0, "crossfade fade out mode", "crossfade,mix"},
|
||||
{1, S_O(crossfeed), false, "crossfeed", off_on },
|
||||
{6, S_O(crossfeed_direct_gain), 15, "crossfeed direct gain", NULL },
|
||||
{7, S_O(crossfeed_cross_gain), 60, "crossfeed cross gain", NULL },
|
||||
{8, S_O(crossfeed_hf_attenuation), 160, "crossfeed hf attenuation", NULL },
|
||||
{11, S_O(crossfeed_hf_cutoff), 700, "crossfeed hf cutoff", NULL },
|
||||
#endif
|
||||
#ifdef HAVE_DIRCACHE
|
||||
{1, S_O(dircache), false, "dircache", off_on },
|
||||
|
@ -538,6 +542,7 @@ static const struct bit_entry hd_bits[] =
|
|||
"warn when erasing dynamic playlist", off_on },
|
||||
#if CONFIG_CODEC == SWCODEC
|
||||
{1, S_O(eq_enabled), false, "eq enabled", off_on },
|
||||
{8, S_O(eq_precut), 0, "eq precut", NULL },
|
||||
/* 0..32768 Hz */
|
||||
{15, S_O(eq_band0_cutoff), 60, "eq band 0 cutoff", NULL },
|
||||
{15, S_O(eq_band1_cutoff), 200, "eq band 1 cutoff", NULL },
|
||||
|
@ -579,10 +584,6 @@ static const struct bit_entry hd_bits[] =
|
|||
{1, S_O(tagcache_ram), 0, "tagcache_ram", off_on },
|
||||
#endif
|
||||
|
||||
#if (CONFIG_CODEC == SWCODEC)
|
||||
{8, S_O(eq_precut), 0, "eq precut", NULL },
|
||||
#endif
|
||||
|
||||
/* If values are just added to the end, no need to bump the version. */
|
||||
/* new stuff to be added at the end */
|
||||
|
||||
|
@ -1159,6 +1160,11 @@ void settings_apply(void)
|
|||
audio_set_crossfade(global_settings.crossfade);
|
||||
dsp_set_replaygain(true);
|
||||
dsp_set_crossfeed(global_settings.crossfeed);
|
||||
dsp_set_crossfeed_direct_gain(global_settings.crossfeed_direct_gain);
|
||||
dsp_set_crossfeed_cross_params(global_settings.crossfeed_cross_gain,
|
||||
global_settings.crossfeed_cross_gain
|
||||
+ global_settings.crossfeed_hf_attenuation,
|
||||
global_settings.crossfeed_hf_cutoff);
|
||||
|
||||
dsp_set_eq(global_settings.eq_enabled);
|
||||
dsp_set_eq_precut(global_settings.eq_precut);
|
||||
|
|
|
@ -417,7 +417,13 @@ struct user_settings
|
|||
shuffle is on, album gain otherwise */
|
||||
int replaygain_preamp; /* scale replaygained tracks by this */
|
||||
int beep; /* system beep volume when changing tracks etc. */
|
||||
bool crossfeed; /* enable crossfeed */
|
||||
|
||||
/* Crossfeed settings */
|
||||
bool crossfeed; /* enable crossfeed */
|
||||
unsigned int crossfeed_direct_gain; /* - dB x 10 */
|
||||
unsigned int crossfeed_cross_gain; /* - dB x 10 */
|
||||
unsigned int crossfeed_hf_attenuation; /* - dB x 10 */
|
||||
unsigned int crossfeed_hf_cutoff; /* Frequency in Hz */
|
||||
#endif
|
||||
#ifdef HAVE_DIRCACHE
|
||||
bool dircache; /* enable directory cache */
|
||||
|
|
|
@ -125,7 +125,14 @@ static bool treble(void)
|
|||
#endif
|
||||
|
||||
#if CONFIG_CODEC == SWCODEC
|
||||
static bool crossfeed(void)
|
||||
static void crossfeed_format(char* buffer, int buffer_size, int value,
|
||||
const char* unit)
|
||||
{
|
||||
snprintf(buffer, buffer_size, "%s%d.%d %s", value == 0 ? " " : "-",
|
||||
value / 10, value % 10, unit);
|
||||
}
|
||||
|
||||
static bool crossfeed_enabled(void)
|
||||
{
|
||||
bool result = set_bool_options(str(LANG_CROSSFEED),
|
||||
&global_settings.crossfeed,
|
||||
|
@ -134,6 +141,75 @@ static bool crossfeed(void)
|
|||
NULL);
|
||||
|
||||
dsp_set_crossfeed(global_settings.crossfeed);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool crossfeed_direct_gain(void)
|
||||
{
|
||||
return set_int(str(LANG_CROSSFEED_DIRECT_GAIN), str(LANG_UNIT_DB),
|
||||
UNIT_DB, &global_settings.crossfeed_direct_gain,
|
||||
&dsp_set_crossfeed_direct_gain, 5, 0, 60, crossfeed_format);
|
||||
}
|
||||
|
||||
static void crossfeed_cross_gain_helper(int val)
|
||||
{
|
||||
dsp_set_crossfeed_cross_params(val,
|
||||
val + global_settings.crossfeed_hf_attenuation,
|
||||
global_settings.crossfeed_hf_cutoff);
|
||||
}
|
||||
|
||||
static bool crossfeed_cross_gain(void)
|
||||
{
|
||||
return set_int(str(LANG_CROSSFEED_CROSS_GAIN), str(LANG_UNIT_DB),
|
||||
UNIT_DB, &global_settings.crossfeed_cross_gain,
|
||||
&crossfeed_cross_gain_helper, 5, 30, 120, crossfeed_format);
|
||||
}
|
||||
|
||||
static void crossfeed_hf_att_helper(int val)
|
||||
{
|
||||
dsp_set_crossfeed_cross_params(global_settings.crossfeed_cross_gain,
|
||||
global_settings.crossfeed_cross_gain + val,
|
||||
global_settings.crossfeed_hf_cutoff);
|
||||
}
|
||||
|
||||
static bool crossfeed_hf_attenuation(void)
|
||||
{
|
||||
return set_int(str(LANG_CROSSFEED_HF_ATTENUATION), str(LANG_UNIT_DB),
|
||||
UNIT_DB, &global_settings.crossfeed_hf_attenuation,
|
||||
&crossfeed_hf_att_helper, 5, 60, 240, crossfeed_format);
|
||||
}
|
||||
|
||||
static void crossfeed_hf_cutoff_helper(int val)
|
||||
{
|
||||
dsp_set_crossfeed_cross_params(global_settings.crossfeed_cross_gain,
|
||||
global_settings.crossfeed_cross_gain + global_settings.crossfeed_hf_attenuation, val);
|
||||
}
|
||||
|
||||
static bool crossfeed_hf_cutoff(void)
|
||||
{
|
||||
return set_int(str(LANG_CROSSFEED_HF_CUTOFF), str(LANG_UNIT_HERTZ),
|
||||
UNIT_HERTZ, &global_settings.crossfeed_hf_cutoff, &crossfeed_hf_cutoff_helper, 100, 500, 2000,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static bool crossfeed_menu(void)
|
||||
{
|
||||
int m;
|
||||
bool result;
|
||||
static const struct menu_item items[] = {
|
||||
{ ID2P(LANG_CROSSFEED), crossfeed_enabled },
|
||||
{ ID2P(LANG_CROSSFEED_DIRECT_GAIN), crossfeed_direct_gain },
|
||||
{ ID2P(LANG_CROSSFEED_CROSS_GAIN), crossfeed_cross_gain },
|
||||
{ ID2P(LANG_CROSSFEED_HF_ATTENUATION), crossfeed_hf_attenuation },
|
||||
{ ID2P(LANG_CROSSFEED_HF_CUTOFF), crossfeed_hf_cutoff },
|
||||
};
|
||||
|
||||
m=menu_init(items, sizeof(items) / sizeof(*items), NULL,
|
||||
NULL, NULL, NULL);
|
||||
result = menu_run(m);
|
||||
menu_exit(m);
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
@ -414,7 +490,7 @@ bool sound_menu(void)
|
|||
{ ID2P(LANG_CHANNEL_MENU), chanconf },
|
||||
{ ID2P(LANG_STEREO_WIDTH), stereo_width },
|
||||
#if CONFIG_CODEC == SWCODEC
|
||||
{ ID2P(LANG_CROSSFEED), crossfeed },
|
||||
{ ID2P(LANG_CROSSFEED), crossfeed_menu },
|
||||
{ ID2P(LANG_EQUALIZER), eq_menu },
|
||||
#endif
|
||||
#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
|
||||
|
|
|
@ -516,6 +516,10 @@ void system_init(void)
|
|||
"movclr.l %%acc2, %%d0\n\t"
|
||||
"movclr.l %%acc3, %%d0\n\t"
|
||||
: : : "d0");
|
||||
/* Set EMAC unit to saturating and rounding fractional mode, since that's
|
||||
what'll be the most useful for most things which the main thread
|
||||
will do. */
|
||||
coldfire_set_macsr(EMAC_FRACTIONAL | EMAC_SATURATE | EMAC_ROUND);
|
||||
}
|
||||
|
||||
void system_reboot (void)
|
||||
|
|
Loading…
Reference in New Issue