Index: apps/lang/english.lang =================================================================== --- apps/lang/english.lang (revision 28159) +++ 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/settings.h =================================================================== --- apps/settings.h (revision 28159) +++ 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 28159) +++ 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,45 @@ } #endif /* DSP_HAVE_ASM_CROSSFEED */ +static void meier_crossfeed(int count, int32_t *buf[]) +{ + int32_t *hist_l = &crossfeed_data.history[0]; + int32_t *hist_r = &crossfeed_data.history[2]; + int32_t vdiff, vcl, vcr, common; + int32_t left, right; + int i; + int32_t coef1, coef2; + + // 1 / F.Rforward.C + coef1 = (0xffffffff/NATIVE_FREQUENCY) * 2128; + // 1 / F.Rcross.C + coef2 = (0xffffffff/NATIVE_FREQUENCY) * 1000; + + vcl = hist_l[0]; + vcr = hist_r[0]; + left = hist_l[1]; + right = hist_r[1]; + for (i = 0; i < count; i++) { + vdiff = left - right; + + // calculate output + left = buf[0][i] + vcl; + right = buf[1][i] + vcr; + buf[0][i] = left; + buf[1][i] = right; + + // update filter + common = FRACMUL(coef2, vdiff); + vcl -= (FRACMUL(coef1, vcl) + common); + vcr -= (FRACMUL(coef1, vcr) - common); + } + // store filter state + hist_l[0] = vcl; + hist_r[0] = vcr; + hist_l[1] = left; + hist_r[1] = right; +} + /** * dsp_set_crossfeed(bool enable) * @@ -836,11 +875,19 @@ * 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; + } } void dsp_set_crossfeed_direct_gain(int gain) @@ -1255,8 +1302,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 +1407,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 28159) +++ apps/settings_list.c (working copy) @@ -1293,8 +1293,12 @@ #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 28159) +++ 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 28159) +++ 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,