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,