Index: apps/lang/english.lang
===================================================================
--- apps/lang/english.lang (revision 28215)
+++ apps/lang/english.lang (working copy)
@@ -904,6 +904,40 @@
+ id: LANG_CROSSFEED_MEIER
+ desc: in sound settings
+ user: core
+
+ *: none
+ swcodec: "Meier"
+
+
+ *: none
+ swcodec: "Meier"
+
+
+ *: none
+ swcodec: "Meier"
+
+
+
+ id: LANG_CROSSFEED_CUSTOM
+ desc: in sound settings
+ user: core
+
+ *: none
+ swcodec: "Custom"
+
+
+ *: none
+ swcodec: "Custom"
+
+
+ *: none
+ swcodec: "Custom"
+
+
+
id: LANG_CROSSFEED_DIRECT_GAIN
desc: in crossfeed settings
user: core
Index: apps/plugins/mpegplayer/mpeg_settings.c
===================================================================
--- apps/plugins/mpegplayer/mpeg_settings.c (revision 28215)
+++ apps/plugins/mpegplayer/mpeg_settings.c (working copy)
@@ -461,7 +461,7 @@
case MPEG_AUDIO_CROSSFEED:
rb->dsp_set_crossfeed((global || settings.crossfeed) ?
- rb->global_settings->crossfeed : false);
+ rb->global_settings->crossfeed : 0);
break;
case MPEG_AUDIO_EQUALIZER:
Index: apps/settings.h
===================================================================
--- apps/settings.h (revision 28215)
+++ apps/settings.h (working copy)
@@ -321,7 +321,7 @@
int replaygain_preamp; /* scale replaygained tracks by this */
/* Crossfeed */
- bool crossfeed; /* enable crossfeed */
+ int crossfeed; /* crossfeed type */
unsigned int crossfeed_direct_gain; /* dB x 10 */
unsigned int crossfeed_cross_gain; /* dB x 10 */
unsigned int crossfeed_hf_attenuation; /* dB x 10 */
Index: apps/dsp.c
===================================================================
--- apps/dsp.c (revision 28215)
+++ apps/dsp.c (working copy)
@@ -189,7 +189,7 @@
/* These will be NULL for the voice codec and is more economical that
way */
channels_process_dsp_fn_type apply_gain;
- channels_process_fn_type apply_crossfeed;
+ channels_process_fn_type crossfeed_process;
channels_process_fn_type eq_process;
channels_process_fn_type channels_process;
channels_process_fn_type compressor_process;
@@ -232,7 +232,7 @@
static long track_peak;
static long album_peak;
static long replaygain;
-static bool crossfeed_enabled;
+static int crossfeed_type;
#define AUDIO_DSP (dsp_conf[CODEC_IDX_AUDIO])
#define VOICE_DSP (dsp_conf[CODEC_IDX_VOICE])
@@ -829,6 +829,42 @@
}
#endif /* DSP_HAVE_ASM_CROSSFEED */
+/* Implementation of the "simple" passive crossfeed circuit by Jan Meier.
+ * See also: http://www.meier-audio.homepage.t-online.de/passivefilter.htm
+ */
+static void meier_crossfeed(int count, int32_t *buf[])
+{
+ int32_t *hist = crossfeed_data.history;
+ int32_t vdiff, vcl, vcr, common;
+ int32_t lout, rout;
+ int32_t coef1, coef2;
+ int i;
+
+ coef1 = (0xffffffff/NATIVE_FREQUENCY) * 2128; /* 1 / (F.Rforward.C) */
+ coef2 = (0xffffffff/NATIVE_FREQUENCY) * 1000; /* 1 / (F.Rcross.C) */
+
+ /* get filter state */
+ vcl = hist[0];
+ vcr = hist[1];
+ vdiff = hist[2];
+ for (i = 0; i < count; i++) {
+ /* calculate new output */
+ lout = buf[0][i] + vcl;
+ rout = buf[1][i] + vcr;
+ buf[0][i] = lout;
+ buf[1][i] = rout;
+ /* update filter state */
+ common = FRACMUL(vdiff, coef2);
+ vcl -= (FRACMUL(vcl, coef1) + common);
+ vcr -= (FRACMUL(vcr, coef1) - common);
+ vdiff = lout - rout;
+ }
+ /* store filter state */
+ hist[0] = vcl;
+ hist[1] = vcr;
+ hist[2] = vdiff;
+}
+
/**
* dsp_set_crossfeed(bool enable)
*
@@ -836,11 +872,20 @@
* needs syncing with changes to the following dsp parameters:
* * dsp->stereo_mode (A)
*/
-void dsp_set_crossfeed(bool enable)
+void dsp_set_crossfeed(int type)
{
- crossfeed_enabled = enable;
- AUDIO_DSP.apply_crossfeed = (enable && AUDIO_DSP.data.num_channels > 1)
- ? apply_crossfeed : NULL;
+ crossfeed_type = type;
+
+ if (AUDIO_DSP.data.num_channels == 1) {
+ type = 0;
+ }
+
+ switch (type) {
+ case 0: AUDIO_DSP.crossfeed_process = NULL; break;
+ case 1: AUDIO_DSP.crossfeed_process = meier_crossfeed; break;
+ case 2: AUDIO_DSP.crossfeed_process = apply_crossfeed; break;
+ }
+ memset(crossfeed_data.history, 0, sizeof(crossfeed_data.history));
}
void dsp_set_crossfeed_direct_gain(int gain)
@@ -1255,8 +1300,8 @@
if (dsp->resample && (chunk = resample(dsp, chunk, t2)) <= 0)
break; /* I'm pretty sure we're downsampling here */
- if (dsp->apply_crossfeed)
- dsp->apply_crossfeed(chunk, t2);
+ if (dsp->crossfeed_process)
+ dsp->crossfeed_process(chunk, t2);
if (dsp->eq_process)
dsp->eq_process(chunk, t2);
@@ -1360,7 +1405,7 @@
sample_input_new_format(dsp);
sample_output_new_format(dsp);
if (dsp == &AUDIO_DSP)
- dsp_set_crossfeed(crossfeed_enabled);
+ dsp_set_crossfeed(crossfeed_type);
}
intptr_t dsp_configure(struct dsp_config *dsp, int setting, intptr_t value)
Index: apps/settings_list.c
===================================================================
--- apps/settings_list.c (revision 28215)
+++ apps/settings_list.c (working copy)
@@ -1294,8 +1294,10 @@
#endif
/* crossfeed */
- OFFON_SETTING(F_SOUNDSETTING, crossfeed, LANG_CROSSFEED, false,
- "crossfeed", dsp_set_crossfeed),
+ CHOICE_SETTING(F_SOUNDSETTING, crossfeed, LANG_CROSSFEED, 0,"crossfeed",
+ "off,meier,custom", dsp_set_crossfeed, 3,
+ ID2P(LANG_OFF), ID2P(LANG_CROSSFEED_MEIER),
+ ID2P(LANG_CROSSFEED_CUSTOM)),
INT_SETTING_NOWRAP(F_SOUNDSETTING, crossfeed_direct_gain,
LANG_CROSSFEED_DIRECT_GAIN, -15,
"crossfeed direct gain", UNIT_DB, -60, 0, 5,
Index: apps/dsp.h
===================================================================
--- apps/dsp.h (revision 28215)
+++ apps/dsp.h (working copy)
@@ -67,7 +67,7 @@
intptr_t value);
int get_replaygain_mode(bool have_track_gain, bool have_album_gain);
void dsp_set_replaygain(void);
-void dsp_set_crossfeed(bool enable);
+void dsp_set_crossfeed(int type);
void dsp_set_crossfeed_direct_gain(int gain);
void dsp_set_crossfeed_cross_params(long lf_gain, long hf_gain,
long cutoff);
Index: apps/plugin.h
===================================================================
--- apps/plugin.h (revision 28215)
+++ apps/plugin.h (working copy)
@@ -638,7 +638,7 @@
void (*audio_set_output_source)(int monitor);
void (*audio_set_input_source)(int source, unsigned flags);
#endif
- void (*dsp_set_crossfeed)(bool enable);
+ void (*dsp_set_crossfeed)(int type);
void (*dsp_set_eq)(bool enable);
void (*dsp_dither_enable)(bool enable);
intptr_t (*dsp_configure)(struct dsp_config *dsp, int setting,