diff --git a/apps/dsp.c b/apps/dsp.c index e5696bc7cd..b199d4e693 100644 --- a/apps/dsp.c +++ b/apps/dsp.c @@ -192,6 +192,7 @@ struct dsp_config bool new_gain; bool crossfeed_enabled; bool eq_enabled; + long eq_precut; /* Note that this is in S8.23 format. */ }; struct resample_data @@ -589,15 +590,31 @@ static void apply_crossfeed(int32_t* src[], int count) } #endif -/* Synchronize the EQ filters with the global settings */ -void dsp_eq_update_data(bool enabled, int band) +/** + * Use to enable the equalizer and set any pregain. + * + * @param enable true to enable the equalizer + * @param precut to apply in decibels (multiplied by 10) + */ +void dsp_eq_set(bool enable, unsigned int precut) +{ + dsp->eq_enabled = enable; + + /* Needs to be in s8.23 format amplitude for apply_gain() */ + dsp->eq_precut = get_replaygain_int(precut * -10) >> 1; +} + +/** + * Synchronize the equalizer filter coefficients with the global settings. + * + * @param band the equalizer band to synchronize + */ +void dsp_eq_update_filter_coefs(int band) { const int *setting; long gain; unsigned long cutoff, q; - dsp->eq_enabled = enabled; - /* Adjust setting pointer to the band we actually want to change */ setting = &global_settings.eq_band0_cutoff + (band * 3); @@ -640,7 +657,7 @@ static void eq_process(int32_t **x, unsigned num) int i; unsigned int channels = dsp->stereo_mode != STEREO_MONO ? 2 : 1; unsigned shift; - + /* filter configuration currently is 1 low shelf filter, 3 band peaking filters and 1 high shelf filter, in that order. we need to know this so we can choose the correct shift factor. @@ -662,39 +679,51 @@ static void eq_process(int32_t **x, unsigned num) */ static void apply_gain(int32_t* _src[], int _count) { - struct dsp_config *my_dsp = dsp; - if (my_dsp->replaygain) + int32_t** src = _src; + int count = _count; + int32_t* s0 = src[0]; + int32_t* s1 = src[1]; + long gain = 0; + int32_t s; + int i; + int32_t *d; + + if (dsp->replaygain) { - int32_t** src = _src; - int count = _count; - int32_t* s0 = src[0]; - int32_t* s1 = src[1]; - long gain = my_dsp->replaygain; - int32_t s; - int i; - int32_t *d; + gain = dsp->replaygain; + } - if (s0 != s1) - { - d = &sample_buf[SAMPLE_BUF_SIZE / 2]; - src[1] = d; - s = *s1++; + if (dsp->eq_enabled) + { + gain += dsp->eq_precut; /* FIXME: This isn't that easy right? */ + } - for (i = 0; i < count; i++) - FRACMUL_8_LOOP(s, gain, s1, d); - } - else - { - src[1] = &sample_buf[0]; - } + /* Don't bother if the gain is zero */ + if (gain == 0) + { + return; + } - d = &sample_buf[0]; - src[0] = d; - s = *s0++; + if (s0 != s1) + { + d = &sample_buf[SAMPLE_BUF_SIZE / 2]; + src[1] = d; + s = *s1++; for (i = 0; i < count; i++) - FRACMUL_8_LOOP(s, gain, s0, d); + FRACMUL_8_LOOP(s, gain, s1, d); } + else + { + src[1] = &sample_buf[0]; + } + + d = &sample_buf[0]; + src[0] = d; + s = *s0++; + + for (i = 0; i < count; i++) + FRACMUL_8_LOOP(s, gain, s0, d); } void channels_set(int value) @@ -815,7 +844,7 @@ long dsp_process(char* dst, const char* src[], long size) unsigned long old_macsr = coldfire_get_macsr(); coldfire_set_macsr(EMAC_FRACTIONAL | EMAC_SATURATE); #endif - + dsp = &dsp_conf[current_codec]; factor = (dsp->stereo_mode != STEREO_MONO) ? 2 : 1; diff --git a/apps/dsp.h b/apps/dsp.h index 8b8b164d6e..35a1e88744 100644 --- a/apps/dsp.h +++ b/apps/dsp.h @@ -54,7 +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_eq_update_data(bool enabled, int band); +void dsp_eq_set(bool enable, unsigned int precut); +void dsp_eq_update_filter_coefs(int band); void sound_set_pitch(int r); int sound_get_pitch(void); void channels_set(int value); diff --git a/apps/eq_menu.c b/apps/eq_menu.c index 82639a54da..61d38f473c 100644 --- a/apps/eq_menu.c +++ b/apps/eq_menu.c @@ -97,14 +97,14 @@ #endif - +/* Various user interface limits and sizes */ #define EQ_CUTOFF_MIN 20 #define EQ_CUTOFF_MAX 22040 #define EQ_CUTOFF_STEP 10 #define EQ_CUTOFF_FAST_STEP 100 #define EQ_GAIN_MIN (-240) #define EQ_GAIN_MAX 240 -#define EQ_GAIN_STEP 1 +#define EQ_GAIN_STEP 5 #define EQ_GAIN_FAST_STEP 10 #define EQ_Q_MIN 5 #define EQ_Q_MAX 64 @@ -113,20 +113,9 @@ #define EQ_USER_DIVISOR 10 -static bool eq_enabled(void) -{ - int i; - - bool result = set_bool(str(LANG_EQUALIZER_ENABLED), - &global_settings.eq_enabled); - - /* Update all bands */ - for(i = 0; i < 5; i++) { - dsp_eq_update_data(global_settings.eq_enabled, i); - } - - return result; -} +/* + * Utility functions + */ static void eq_gain_format(char* buffer, int buffer_size, int value, const char* unit) { @@ -141,6 +130,44 @@ static void eq_q_format(char* buffer, int buffer_size, int value, const char* un snprintf(buffer, buffer_size, "%d.%d %s", value / EQ_USER_DIVISOR, value % EQ_USER_DIVISOR, unit); } +static void eq_precut_format(char* buffer, int buffer_size, int value, const char* unit) +{ + snprintf(buffer, buffer_size, "%s%d.%d %s", value == 0 ? " " : "-", + value / EQ_USER_DIVISOR, value % EQ_USER_DIVISOR, unit); +} + +/* + * Settings functions + */ + +static bool eq_enabled(void) +{ + int i; + + bool result = set_bool(str(LANG_EQUALIZER_ENABLED), + &global_settings.eq_enabled); + + dsp_eq_set(global_settings.eq_enabled, global_settings.eq_precut); + + /* Update all bands */ + for(i = 0; i < 5; i++) { + dsp_eq_update_filter_coefs(i); + } + + return result; +} + +static bool eq_precut(void) +{ + bool result = set_int(str(LANG_EQUALIZER_PRECUT), str(LANG_UNIT_DB), + UNIT_DB, &global_settings.eq_precut, NULL, 5, 0, 240, + eq_precut_format); + + dsp_eq_set(global_settings.eq_enabled, global_settings.eq_precut); + + return result; +} + /* Possibly dodgy way of simplifying the code a bit. */ #define eq_make_gain_label(buf, bufsize, frequency) snprintf((buf), \ (bufsize), str(LANG_EQUALIZER_GAIN_ITEM), (frequency)) @@ -148,20 +175,20 @@ static void eq_q_format(char* buffer, int buffer_size, int value, const char* un #define eq_set_center(band) \ static bool eq_set_band ## band ## _center(void) \ { \ - bool result = set_int(str(LANG_EQUALIZER_BAND_CENTER), "Hertz", UNIT_HERTZ, \ - &global_settings.eq_band ## band ## _cutoff, NULL, \ + bool result = set_int(str(LANG_EQUALIZER_BAND_CENTER), "Hertz", \ + UNIT_HERTZ, &global_settings.eq_band ## band ## _cutoff, NULL, \ EQ_CUTOFF_STEP, EQ_CUTOFF_MIN, EQ_CUTOFF_MAX, NULL); \ - dsp_eq_update_data(global_settings.eq_enabled, band); \ + dsp_eq_update_filter_coefs(band); \ return result; \ } #define eq_set_cutoff(band) \ static bool eq_set_band ## band ## _cutoff(void) \ { \ - bool result = set_int(str(LANG_EQUALIZER_BAND_CUTOFF), "Hertz", UNIT_HERTZ, \ - &global_settings.eq_band ## band ## _cutoff, NULL, \ + bool result = set_int(str(LANG_EQUALIZER_BAND_CUTOFF), "Hertz", \ + UNIT_HERTZ, &global_settings.eq_band ## band ## _cutoff, NULL, \ EQ_CUTOFF_STEP, EQ_CUTOFF_MIN, EQ_CUTOFF_MAX, NULL); \ - dsp_eq_update_data(global_settings.eq_enabled, band); \ + dsp_eq_update_filter_coefs(band); \ return result; \ } @@ -171,7 +198,7 @@ static bool eq_set_band ## band ## _q(void) \ bool result = set_int(str(LANG_EQUALIZER_BAND_Q), "Q", UNIT_INT, \ &global_settings.eq_band ## band ## _q, NULL, \ EQ_Q_STEP, EQ_Q_MIN, EQ_Q_MAX, eq_q_format); \ - dsp_eq_update_data(global_settings.eq_enabled, band); \ + dsp_eq_update_filter_coefs(band); \ return result; \ } @@ -181,7 +208,7 @@ static bool eq_set_band ## band ## _gain(void) \ bool result = set_int("Band " #band, str(LANG_UNIT_DB), UNIT_DB, \ &global_settings.eq_band ## band ## _gain, NULL, \ EQ_GAIN_STEP, EQ_GAIN_MIN, EQ_GAIN_MAX, eq_gain_format); \ - dsp_eq_update_data(global_settings.eq_enabled, band); \ + dsp_eq_update_filter_coefs(band); \ return result; \ } @@ -666,7 +693,7 @@ bool eq_menu_graphical(void) /* Update the filter if the user changed something */ if (has_changed) { - dsp_eq_update_data(global_settings.eq_enabled, current_band); + dsp_eq_update_filter_coefs(current_band); has_changed = false; } } @@ -706,6 +733,7 @@ static bool eq_save_preset(void) /* TODO: Should we really do this? */ fdprintf(fd, "eq enabled: on\r\n"); + fdprintf(fd, "eq precut: %d\r\n", global_settings.eq_precut); setting = &global_settings.eq_band0_cutoff; @@ -737,6 +765,7 @@ bool eq_menu(void) static const struct menu_item items[] = { { ID2P(LANG_EQUALIZER_ENABLED), eq_enabled }, { ID2P(LANG_EQUALIZER_GRAPHICAL), eq_menu_graphical }, + { ID2P(LANG_EQUALIZER_PRECUT), eq_precut }, { ID2P(LANG_EQUALIZER_GAIN), eq_gain_menu }, { ID2P(LANG_EQUALIZER_ADVANCED), eq_advanced_menu }, { ID2P(LANG_EQUALIZER_SAVE), eq_save_preset }, diff --git a/apps/lang/english.lang b/apps/lang/english.lang index 9923fa9caf..c239b9cdd3 100644 --- a/apps/lang/english.lang +++ b/apps/lang/english.lang @@ -3880,3 +3880,10 @@ desc: in tag cache settings eng: "Updating in background" voice: "Updating in background" new: + +id: LANG_EQUALIZER_PRECUT +desc: in eq settings +eng: "Precut" +voice: "Pre-cut" +new: + diff --git a/apps/settings.c b/apps/settings.c index 6fe9665086..5552eaa70c 100644 --- a/apps/settings.c +++ b/apps/settings.c @@ -570,6 +570,10 @@ 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 */ @@ -1125,10 +1129,11 @@ void settings_apply(void) audio_set_crossfade(global_settings.crossfade); dsp_set_replaygain(true); dsp_set_crossfeed(global_settings.crossfeed); - + + dsp_eq_set(global_settings.eq_enabled, global_settings.eq_precut); /* Update all EQ bands */ for(i = 0; i < 5; i++) { - dsp_eq_update_data(global_settings.eq_enabled, i); + dsp_eq_update_filter_coefs(i); } #endif diff --git a/apps/settings.h b/apps/settings.h index fb8e11ffde..3616434642 100644 --- a/apps/settings.h +++ b/apps/settings.h @@ -432,34 +432,35 @@ struct user_settings #if CONFIG_CODEC == SWCODEC bool eq_enabled; /* Enable equalizer */ - + unsigned int eq_precut; /* dB */ + /* Order is important here, must be cutoff, q, then gain for each band. See dsp_eq_update_data in dsp.c for why. */ - + /* Band 0 settings */ - int eq_band0_cutoff; /* Hz */ - int eq_band0_q; - int eq_band0_gain; /* +/- dB */ - + int eq_band0_cutoff; /* Hz */ + int eq_band0_q; + int eq_band0_gain; /* +/- dB */ + /* Band 1 settings */ - int eq_band1_cutoff; /* Hz */ - int eq_band1_q; - int eq_band1_gain; /* +/- dB */ - + int eq_band1_cutoff; /* Hz */ + int eq_band1_q; + int eq_band1_gain; /* +/- dB */ + /* Band 2 settings */ - int eq_band2_cutoff; /* Hz */ - int eq_band2_q; - int eq_band2_gain; /* +/- dB */ - + int eq_band2_cutoff; /* Hz */ + int eq_band2_q; + int eq_band2_gain; /* +/- dB */ + /* Band 3 settings */ - int eq_band3_cutoff; /* Hz */ - int eq_band3_q; - int eq_band3_gain; /* +/- dB */ - + int eq_band3_cutoff; /* Hz */ + int eq_band3_q; + int eq_band3_gain; /* +/- dB */ + /* Band 4 settings */ - int eq_band4_cutoff; /* Hz */ - int eq_band4_q; - int eq_band4_gain; /* +/- dB */ + int eq_band4_cutoff; /* Hz */ + int eq_band4_q; + int eq_band4_gain; /* +/- dB */ #endif #ifdef HAVE_LCD_COLOR @@ -472,7 +473,7 @@ struct user_settings int bg_color; /* background color native format */ int fg_color; /* foreground color native format */ #endif - bool party_mode; /* party mode - unstoppable music */ + bool party_mode; /* party mode - unstoppable music */ #ifdef CONFIG_BACKLIGHT bool bl_filter_first_keypress; /* filter first keypress when dark? */