Allow customizing EQ filter types

Allows any EQ band to be set to any of Low Shelf, Peak, or High Shelf, instead of hardcoding the types per band.

Change-Id: I470ab916359092ba465e7b6331baed3bf11b2fc9
This commit is contained in:
Skye 2026-07-20 21:52:07 +09:00 • committed by Solomon Peachy
parent 1007216fc4
commit e764656ab7
6 changed files with 231 additions and 92 deletions

View file

@ -1091,10 +1091,10 @@
desc: in the equalizer settings menu desc: in the equalizer settings menu
user: core user: core
<source> <source>
*: "Peak Filter %d" *: "Peak Filter"
</source> </source>
<dest> <dest>
*: "Peak Filter %d" *: "Peak Filter"
</dest> </dest>
<voice> <voice>
*: "Peak filter" *: "Peak filter"
@ -17169,3 +17169,31 @@
*: "Finished" *: "Finished"
</voice> </voice>
</phrase> </phrase>
<phrase>
id: LANG_EQUALIZER_BAND
desc: in the equalizer settings menu
user: core
<source>
*: "Filter %d"
</source>
<dest>
*: "Filter %d"
</dest>
<voice>
*: "Filter"
</voice>
</phrase>
<phrase>
id: LANG_EQUALIZER_FILTER_TYPE
desc: in the equalizer settings menu
user: core
<source>
*: "Filter Type"
</source>
<dest>
*: "Filter Type"
</dest>
<voice>
*: "Filter Type"
</voice>
</phrase>

View file

@ -180,6 +180,17 @@ static const struct int_setting cutoff_int_setting = {
.get_talk_id = NULL, .get_talk_id = NULL,
}; };
static const struct choice_setting type_choice_setting = {
.option_callback = NULL,
.count = 3,
.cfg_vals = "low_shelf,peaking,high_shelf",
{.desc = (const unsigned char*[]) {
ID2P(LANG_EQUALIZER_BAND_LOW_SHELF),
ID2P(LANG_EQUALIZER_BAND_PEAK),
ID2P(LANG_EQUALIZER_BAND_HIGH_SHELF),
}}
};
static int simplelist_action_callback(int action, struct gui_synclist *lists) static int simplelist_action_callback(int action, struct gui_synclist *lists)
{ {
(void)lists; (void)lists;
@ -234,7 +245,7 @@ static void selection_to_banditem(int selection, int expanded_band, int *band, i
*item = 0; *item = 0;
*band = selection; *band = selection;
} }
else if (diff < 4) else if (diff < 5)
{ {
*item = selection - expanded_band; *item = selection - expanded_band;
*band = expanded_band; *band = expanded_band;
@ -242,7 +253,7 @@ static void selection_to_banditem(int selection, int expanded_band, int *band, i
else else
{ {
*item = 0; *item = 0;
*band = expanded_band + diff - 3; *band = expanded_band + diff - 4;
} }
} }
@ -257,23 +268,13 @@ static char *advancedmenu_item_get_name(int selected_item, void *data, char *buf
switch (item) switch (item)
{ {
case 0: /* Band title */ case 0: /* Band title */
if (band == 0) snprintf(buffer, len, str(LANG_EQUALIZER_BAND), band);
return str(LANG_EQUALIZER_BAND_LOW_SHELF); return buffer;
else if (band == EQ_NUM_BANDS - 1)
return str(LANG_EQUALIZER_BAND_HIGH_SHELF);
else
{
snprintf(buffer, len, str(LANG_EQUALIZER_BAND_PEAK), band);
return buffer;
}
break;
case 1: /* cutoff */ case 1: /* cutoff */
if (band == 0) if (global_settings.eq_band_settings[band].type == EQ_FILTER_PEAK)
lang = LANG_EQUALIZER_BAND_CUTOFF;
else if (band == EQ_NUM_BANDS - 1)
lang = LANG_EQUALIZER_BAND_CUTOFF;
else
lang = LANG_EQUALIZER_BAND_CENTER; lang = LANG_EQUALIZER_BAND_CENTER;
else
lang = LANG_EQUALIZER_BAND_CUTOFF;
break; break;
case 2: /* Q */ case 2: /* Q */
lang = LANG_EQUALIZER_BAND_Q; lang = LANG_EQUALIZER_BAND_Q;
@ -281,6 +282,9 @@ static char *advancedmenu_item_get_name(int selected_item, void *data, char *buf
case 3: /* Gain */ case 3: /* Gain */
lang = LANG_GAIN; lang = LANG_GAIN;
break; break;
case 4: /* Type */
lang = LANG_EQUALIZER_FILTER_TYPE;
break;
} }
if(lang < 0) if(lang < 0)
@ -305,24 +309,14 @@ static int advancedmenu_speak_item(int selected_item, void *data)
switch (item) switch (item)
{ {
case 0: /* Band title */ case 0: /* Band title */
if (band == 0) talk_id(LANG_EQUALIZER_BAND, false);
lang = LANG_EQUALIZER_BAND_LOW_SHELF; talk_number(band, true);
else if (band == EQ_NUM_BANDS - 1) return -1;
lang = LANG_EQUALIZER_BAND_HIGH_SHELF;
else
{
talk_id(LANG_EQUALIZER_BAND_PEAK, false);
talk_number(band, true);
return -1;
}
break;
case 1: /* cutoff */ case 1: /* cutoff */
if (band == 0) if (global_settings.eq_band_settings[band].type == EQ_FILTER_PEAK)
lang = LANG_EQUALIZER_BAND_CUTOFF;
else if (band == EQ_NUM_BANDS - 1)
lang = LANG_EQUALIZER_BAND_CUTOFF;
else
lang = LANG_EQUALIZER_BAND_CENTER; lang = LANG_EQUALIZER_BAND_CENTER;
else
lang = LANG_EQUALIZER_BAND_CUTOFF;
break; break;
case 2: /* Q */ case 2: /* Q */
lang = LANG_EQUALIZER_BAND_Q; lang = LANG_EQUALIZER_BAND_Q;
@ -368,7 +362,6 @@ static int eq_do_advanced_menu(void * param)
info.action_callback = simplelist_action_callback; info.action_callback = simplelist_action_callback;
info.selection = -1; info.selection = -1;
info.title_icon = Icon_EQ; info.title_icon = Icon_EQ;
setting.flags = F_BANFROMQS|F_INT_SETTING|F_T_INT|F_NO_WRAP;
while (true) while (true)
{ {
@ -388,7 +381,7 @@ static int eq_do_advanced_menu(void * param)
} }
else else
{ {
extra = 3; extra = 4;
selected_band = band; selected_band = band;
} }
info.selection = band; info.selection = band;
@ -396,7 +389,8 @@ static int eq_do_advanced_menu(void * param)
continue; continue;
} }
case 1: /* cutoff */ case 1: /* cutoff */
if (band == 0 || band == EQ_NUM_BANDS - 1) setting.flags = F_BANFROMQS|F_INT_SETTING|F_T_INT|F_NO_WRAP;
if (global_settings.eq_band_settings[band].type != EQ_FILTER_PEAK)
setting.lang_id = LANG_EQUALIZER_BAND_CUTOFF; setting.lang_id = LANG_EQUALIZER_BAND_CUTOFF;
else else
setting.lang_id = LANG_EQUALIZER_BAND_CENTER; setting.lang_id = LANG_EQUALIZER_BAND_CENTER;
@ -405,17 +399,26 @@ static int eq_do_advanced_menu(void * param)
setting.setting = &global_settings.eq_band_settings[band].cutoff; setting.setting = &global_settings.eq_band_settings[band].cutoff;
break; break;
case 2: /* Q */ case 2: /* Q */
setting.flags = F_BANFROMQS|F_INT_SETTING|F_T_INT|F_NO_WRAP;
setting.lang_id = LANG_EQUALIZER_BAND_Q; setting.lang_id = LANG_EQUALIZER_BAND_Q;
setting.default_val.int_ = eq_defaults[band].q; setting.default_val.int_ = eq_defaults[band].q;
setting.int_setting = &q_int_setting; setting.int_setting = &q_int_setting;
setting.setting = &global_settings.eq_band_settings[band].q; setting.setting = &global_settings.eq_band_settings[band].q;
break; break;
case 3: /* Gain */ case 3: /* Gain */
setting.flags = F_BANFROMQS|F_INT_SETTING|F_T_INT|F_NO_WRAP;
setting.lang_id = LANG_GAIN; setting.lang_id = LANG_GAIN;
setting.default_val.int_ = eq_defaults[band].gain; setting.default_val.int_ = eq_defaults[band].gain;
setting.int_setting = &gain_int_setting; setting.int_setting = &gain_int_setting;
setting.setting = &global_settings.eq_band_settings[band].gain; setting.setting = &global_settings.eq_band_settings[band].gain;
break; break;
case 4: /* Type */
setting.flags = F_BANFROMQS|F_CHOICE_SETTING|F_T_INT;
setting.lang_id = LANG_EQUALIZER_FILTER_TYPE;
setting.default_val.int_ = eq_defaults[band].type;
setting.choice_setting = &type_choice_setting;
setting.setting = &global_settings.eq_band_settings[band].type;
break;
} }
pcmbuf_set_low_latency(true); pcmbuf_set_low_latency(true);
advancedmenu_item_get_name(info.selection, &selected_band, title, MAX_PATH); advancedmenu_item_get_name(info.selection, &selected_band, title, MAX_PATH);
@ -430,21 +433,17 @@ MENUITEM_FUNCTION(advanced_menu, 0, ID2P(LANG_EQUALIZER_ADVANCED),
eq_do_advanced_menu, NULL, Icon_EQ); eq_do_advanced_menu, NULL, Icon_EQ);
enum eq_slider_mode { enum eq_slider_mode {
TYPE,
GAIN, GAIN,
CUTOFF, CUTOFF,
Q, Q,
}; };
enum eq_type {
LOW_SHELF,
PEAK,
HIGH_SHELF
};
/* Draw the UI for a whole EQ band */ /* Draw the UI for a whole EQ band */
static int draw_eq_slider(struct screen * screen, int x, int y, static int draw_eq_slider(struct screen * screen, int x, int y,
int width, int cutoff, int q, int gain, bool selected, int width, int cutoff, int q, int gain, bool selected,
enum eq_slider_mode mode, int band, int scrollbar_size) enum eq_slider_mode mode, int band, int scrollbar_size,
enum eq_filter_type type)
{ {
char buf[26]; char buf[26];
int steps, min_item, max_item; int steps, min_item, max_item;
@ -453,6 +452,11 @@ static int draw_eq_slider(struct screen * screen, int x, int y,
int w, h; int w, h;
switch(mode) { switch(mode) {
case TYPE:
steps = 5;
min_item = (type * 2);
max_item = (type * 2) + 1;
break;
case Q: case Q:
steps = EQ_Q_MAX - EQ_Q_MIN; steps = EQ_Q_MAX - EQ_Q_MIN;
min_item = q - EQ_Q_STEP - EQ_Q_MIN; min_item = q - EQ_Q_STEP - EQ_Q_MIN;
@ -476,11 +480,17 @@ static int draw_eq_slider(struct screen * screen, int x, int y,
y1 = y + 2; y1 = y + 2;
/* Print out the band label */ /* Print out the band label */
if (band == 0) { if (mode == TYPE && selected)
screen->putsxy(x1, y1, "LS: "); screen->set_drawmode(DRMODE_SOLID | DRMODE_INVERSEVID);
else
screen->set_drawmode(DRMODE_SOLID);
if (type == EQ_FILTER_LOW_SHELF) {
snprintf(buf, sizeof(buf), "LS%d:", band);
screen->putsxy(x1, y1, buf);
/*screen->getstringsize("LS:", &w, &h); UNUSED*/ /*screen->getstringsize("LS:", &w, &h); UNUSED*/
} else if (band == EQ_NUM_BANDS - 1) { } else if (type == EQ_FILTER_HIGH_SHELF) {
screen->putsxy(x1, y1, "HS: "); snprintf(buf, sizeof(buf), "HS%d:", band);
screen->putsxy(x1, y1, buf);
/*screen->getstringsize("HS:", &w, &h); UNUSED*/ /*screen->getstringsize("HS:", &w, &h); UNUSED*/
} else { } else {
snprintf(buf, sizeof(buf), "PK%d:", band); snprintf(buf, sizeof(buf), "PK%d:", band);
@ -557,6 +567,7 @@ static void draw_eq_sliders(struct screen * screen, int x, int y,
int cutoff = setting->cutoff; int cutoff = setting->cutoff;
int q = setting->q; int q = setting->q;
int gain = setting->gain; int gain = setting->gain;
enum eq_filter_type type = setting->type;
if (i == start_item + nb_eq_sliders) if (i == start_item + nb_eq_sliders)
break; break;
@ -564,7 +575,7 @@ static void draw_eq_sliders(struct screen * screen, int x, int y,
if (i >= start_item) { if (i >= start_item) {
height += draw_eq_slider(screen, x, height, screen->lcdwidth - x - 1, height += draw_eq_slider(screen, x, height, screen->lcdwidth - x - 1,
cutoff, q, gain, i == current_band, mode, cutoff, q, gain, i == current_band, mode,
i, scrollbar_size); i, scrollbar_size, type);
/* add a margin */ /* add a margin */
height++; height++;
} }
@ -629,7 +640,18 @@ int eq_menu_graphical(void)
screens[i].clear_display(); screens[i].clear_display();
/* Set pointer to the band data currently editable */ /* Set pointer to the band data currently editable */
if (mode == GAIN) { if (mode == TYPE) {
/* type */
setting = (int*) &global_settings.eq_band_settings[current_band].type;
step = 1;
fast_step = 1;
min = EQ_FILTER_LOW_SHELF;
max = EQ_FILTER_HIGH_SHELF;
screens[i].putsxyf(0, 0, str(LANG_SYSFONT_EQUALIZER_EDIT_MODE),
str(LANG_EQUALIZER_FILTER_TYPE), "");
} else if (mode == GAIN) {
/* gain */ /* gain */
setting = &global_settings.eq_band_settings[current_band].gain; setting = &global_settings.eq_band_settings[current_band].gain;
@ -734,7 +756,7 @@ int eq_menu_graphical(void)
case ACTION_STD_OK: case ACTION_STD_OK:
mode++; mode++;
if (mode > Q) if (mode > Q)
mode = GAIN; /* wrap around */ mode = TYPE; /* wrap around */
break; break;
case ACTION_STD_CANCEL: case ACTION_STD_CANCEL:
@ -785,6 +807,7 @@ static struct browse_folder_info eqs = { EQS_DIR, SHOW_CFG };
static void eq_reset_defaults(void) static void eq_reset_defaults(void)
{ {
for (int i = 0; i < EQ_NUM_BANDS; i++) { for (int i = 0; i < EQ_NUM_BANDS; i++) {
global_settings.eq_band_settings[i].type = eq_defaults[i].type;
global_settings.eq_band_settings[i].cutoff = eq_defaults[i].cutoff; global_settings.eq_band_settings[i].cutoff = eq_defaults[i].cutoff;
global_settings.eq_band_settings[i].q = eq_defaults[i].q; global_settings.eq_band_settings[i].q = eq_defaults[i].q;
global_settings.eq_band_settings[i].gain = eq_defaults[i].gain; global_settings.eq_band_settings[i].gain = eq_defaults[i].gain;

View file

@ -676,16 +676,16 @@ static int32_t get_precut_talkid(int value, int unit)
#endif /* __PCTOOL__ */ #endif /* __PCTOOL__ */
struct eq_band_setting eq_defaults[EQ_NUM_BANDS] = { struct eq_band_setting eq_defaults[EQ_NUM_BANDS] = {
{ 32, 7, 0 }, { EQ_FILTER_LOW_SHELF, 32, 7, 0 },
{ 64, 10, 0 }, { EQ_FILTER_PEAK, 64, 10, 0 },
{ 125, 10, 0 }, { EQ_FILTER_PEAK, 125, 10, 0 },
{ 250, 10, 0 }, { EQ_FILTER_PEAK, 250, 10, 0 },
{ 500, 10, 0 }, { EQ_FILTER_PEAK, 500, 10, 0 },
{ 1000, 10, 0 }, { EQ_FILTER_PEAK, 1000, 10, 0 },
{ 2000, 10, 0 }, { EQ_FILTER_PEAK, 2000, 10, 0 },
{ 4000, 10, 0 }, { EQ_FILTER_PEAK, 4000, 10, 0 },
{ 8000, 10, 0 }, { EQ_FILTER_PEAK, 8000, 10, 0 },
{ 16000, 7, 0 }, { EQ_FILTER_HIGH_SHELF, 16000, 7, 0 },
}; };
static const int wps_context_menu_default = static const int wps_context_menu_default =
@ -704,7 +704,7 @@ static const int tree_hotkey_default = HOTKEY_OFF;
#endif #endif
#ifndef __PCTOOL__ #ifndef __PCTOOL__
static void eq_load_from_cfg(void *setting, char *value) static void eq_load_from_cfg(void *setting, char *value, bool new)
{ {
struct eq_band_setting *eq = setting; struct eq_band_setting *eq = setting;
char *val_end, *end; char *val_end, *end;
@ -728,14 +728,68 @@ static void eq_load_from_cfg(void *setting, char *value)
/* gain */ /* gain */
value = end + 1; value = end + 1;
if (value > val_end) return; if (value > val_end) return;
if (new)
{
end = strchr(value, ',');
if (!end) return;
}
eq->gain = atoi(value); eq->gain = atoi(value);
if (!new) return;
/* type */
value = end + 1;
if (value > val_end) return;
value = skip_whitespace(value);
if (strcasecmp(value, "LOW_SHELF") == 0)
eq->type = EQ_FILTER_LOW_SHELF;
else if (strcasecmp(value, "PEAK") == 0)
eq->type = EQ_FILTER_PEAK;
else if (strcasecmp(value, "HIGH_SHELF") == 0)
eq->type = EQ_FILTER_HIGH_SHELF;
}
static void eq_load_from_cfg_old_low_shelf(void *setting, char *value)
{
eq_load_from_cfg(setting, value, false);
((struct eq_band_setting *)setting)->type = EQ_FILTER_LOW_SHELF;
}
static void eq_load_from_cfg_old_peak(void *setting, char *value)
{
eq_load_from_cfg(setting, value, false);
((struct eq_band_setting *)setting)->type = EQ_FILTER_PEAK;
}
static void eq_load_from_cfg_old_high_shelf(void *setting, char *value)
{
eq_load_from_cfg(setting, value, false);
((struct eq_band_setting *)setting)->type = EQ_FILTER_HIGH_SHELF;
}
static void eq_load_from_cfg_new(void *setting, char *value)
{
eq_load_from_cfg(setting, value, true);
} }
static char* eq_write_to_cfg(void *setting, char *buf, int buf_len) static char* eq_write_to_cfg(void *setting, char *buf, int buf_len)
{ {
struct eq_band_setting *eq = setting; struct eq_band_setting *eq = setting;
snprintf(buf, buf_len, "%d, %d, %d", eq->cutoff, eq->q, eq->gain); const char *type = "PEAK";
switch (eq->type)
{
case EQ_FILTER_LOW_SHELF:
type = "LOW_SHELF";
break;
case EQ_FILTER_PEAK:
type = "PEAK";
break;
case EQ_FILTER_HIGH_SHELF:
type = "HIGH_SHELF";
break;
}
snprintf(buf, buf_len, "%d, %d, %d, %s", eq->cutoff, eq->q, eq->gain, type);
return buf; return buf;
} }
@ -1835,21 +1889,39 @@ const struct settings_list settings[] = {
"eq precut", UNIT_DB, 0, 240, 1, eq_precut_format, "eq precut", UNIT_DB, 0, 240, 1, eq_precut_format,
get_precut_talkid, dsp_set_eq_precut), get_precut_talkid, dsp_set_eq_precut),
#define EQ_BAND_OLD(id, string, type) \
CUSTOM_SETTING(F_EQSETTING|F_DEPRECATED, eq_band_settings[id], -1, \
&eq_defaults[id], string, \
eq_load_from_cfg_old_##type, eq_write_to_cfg, \
eq_is_changed, eq_set_default)
EQ_BAND_OLD(0, "eq low shelf filter", low_shelf),
EQ_BAND_OLD(1, "eq peak filter 1", peak),
EQ_BAND_OLD(2, "eq peak filter 2", peak),
EQ_BAND_OLD(3, "eq peak filter 3", peak),
EQ_BAND_OLD(4, "eq peak filter 4", peak),
EQ_BAND_OLD(5, "eq peak filter 5", peak),
EQ_BAND_OLD(6, "eq peak filter 6", peak),
EQ_BAND_OLD(7, "eq peak filter 7", peak),
EQ_BAND_OLD(8, "eq peak filter 8", peak),
EQ_BAND_OLD(9, "eq high shelf filter", high_shelf),
#undef EQ_BAND_OLD
#define EQ_BAND(id, string) \ #define EQ_BAND(id, string) \
CUSTOM_SETTING(F_EQSETTING, eq_band_settings[id], -1, \ CUSTOM_SETTING(F_EQSETTING, eq_band_settings[id], -1, \
&eq_defaults[id], string, \ &eq_defaults[id], string, \
eq_load_from_cfg, eq_write_to_cfg, \ eq_load_from_cfg_new, eq_write_to_cfg, \
eq_is_changed, eq_set_default) eq_is_changed, eq_set_default)
EQ_BAND(0, "eq low shelf filter"), EQ_BAND(0, "eq filter 0"),
EQ_BAND(1, "eq peak filter 1"), EQ_BAND(1, "eq filter 1"),
EQ_BAND(2, "eq peak filter 2"), EQ_BAND(2, "eq filter 2"),
EQ_BAND(3, "eq peak filter 3"), EQ_BAND(3, "eq filter 3"),
EQ_BAND(4, "eq peak filter 4"), EQ_BAND(4, "eq filter 4"),
EQ_BAND(5, "eq peak filter 5"), EQ_BAND(5, "eq filter 5"),
EQ_BAND(6, "eq peak filter 6"), EQ_BAND(6, "eq filter 6"),
EQ_BAND(7, "eq peak filter 7"), EQ_BAND(7, "eq filter 7"),
EQ_BAND(8, "eq peak filter 8"), EQ_BAND(8, "eq filter 8"),
EQ_BAND(9, "eq high shelf filter"), EQ_BAND(9, "eq filter 9"),
#undef EQ_BAND #undef EQ_BAND
/* dithering */ /* dithering */

View file

@ -71,15 +71,22 @@ static void update_band_filter(int band, unsigned int fout)
functions */ functions */
typeof (filter_pk_coefs) *coef_gen = filter_pk_coefs; typeof (filter_pk_coefs) *coef_gen = filter_pk_coefs;
/* Only first and last bands are not peaking filters */
if (band == 0)
coef_gen = filter_ls_coefs;
else if (band == EQ_NUM_BANDS-1)
coef_gen = filter_hs_coefs;
const struct eq_band_setting *setting = &settings[band]; const struct eq_band_setting *setting = &settings[band];
struct dsp_filter *filter = &eq_data.filters[band]; struct dsp_filter *filter = &eq_data.filters[band];
switch (setting->type)
{
case EQ_FILTER_LOW_SHELF:
coef_gen = filter_ls_coefs;
break;
case EQ_FILTER_PEAK:
coef_gen = filter_pk_coefs;
break;
case EQ_FILTER_HIGH_SHELF:
coef_gen = filter_hs_coefs;
break;
}
coef_gen(fp_div(setting->cutoff, fout, 32), setting->q ?: 1, coef_gen(fp_div(setting->cutoff, fout, 32), setting->q ?: 1,
setting->gain, filter); setting->gain, filter);
} }

View file

@ -23,8 +23,16 @@
/* => support from 3 to 32 bands */ /* => support from 3 to 32 bands */
#define EQ_NUM_BANDS 10 #define EQ_NUM_BANDS 10
enum eq_filter_type
{
EQ_FILTER_LOW_SHELF = 0,
EQ_FILTER_PEAK,
EQ_FILTER_HIGH_SHELF,
};
struct eq_band_setting struct eq_band_setting
{ {
enum eq_filter_type type;
int cutoff; /* Hz */ int cutoff; /* Hz */
int q; int q;
int gain; /* +/- dB */ int gain; /* +/- dB */

View file

@ -315,7 +315,7 @@ change to customise your listening experience.
\section{\label{ref:EQ}Equalizer} \section{\label{ref:EQ}Equalizer}
\screenshot{configure_rockbox/images/ss-equalizer}{The graphical equalizer}{} \screenshot{configure_rockbox/images/ss-equalizer}{The graphical equalizer}{}
Rockbox features a parametric equalizer (EQ). In contrast to non-parametric Rockbox features a parametric equalizer (EQ). In contrast to non-parametric
equalizers, a parametric EQ enables adjusting the center frequency, gain, and equalizers, a parametric EQ enables adjusting the type, center frequency, gain, and
width of EQ bands separately. The ability to adjust the frequency and width width of EQ bands separately. The ability to adjust the frequency and width
of bands enables more precise control of the EQ frequency response while of bands enables more precise control of the EQ frequency response while
avoiding the use of a large number of bands (often 12+) needed in a avoiding the use of a large number of bands (often 12+) needed in a
@ -338,10 +338,11 @@ change to customise your listening experience.
than are required will waste battery and introduce additional rounding than are required will waste battery and introduce additional rounding
noise. For best results, use the fewest number of bands required.} noise. For best results, use the fewest number of bands required.}
Rockbox's parametric EQ is composed of up to ten different bands: Rockbox's parametric EQ is composed of up to ten EQ bands consisting of any combination of three different filter types:
\begin{description} \begin{description}
\item[Band 0: Low shelf filter.] \item[Low shelf filter.]
The low shelf filter boosts or lowers all frequencies below a certain Low shelf filters boost or lower all frequencies below a certain
frequency limit, much as the ``bass'' control found on ordinary frequency limit, much as the ``bass'' control found on ordinary
stereo systems does. stereo systems does.
Adjust the ``cutoff'' frequency parameter to decide where the shelving Adjust the ``cutoff'' frequency parameter to decide where the shelving
@ -354,12 +355,12 @@ change to customise your listening experience.
The ``Q'' parameter should always be set to 0.7 for the shelving The ``Q'' parameter should always be set to 0.7 for the shelving
filters. Higher values will add a small boost around the cutoff filters. Higher values will add a small boost around the cutoff
frequency that is almost always undesirable. frequency that is almost always undesirable.
\item[Bands 1-8: Peaking filters.] \item[Peaking filters.]
Peaking EQ filters boost or lower a frequency range centered at the Peaking EQ filters boost or lower a frequency range centered at the
centre frequency chosen. centre frequency chosen.
Graphic equalizers in home stereos are usually peaking Graphic equalizers in home stereos are usually peaking
filters. The peaking filters in Rockbox's EQ lets you adjust three filters. The peaking filters in Rockbox's EQ lets you adjust three
different parameters for EQ bands 1 through 8. The ``centre'' parameter different parameters. The ``centre'' parameter
controls the centre frequency of the frequency range that is affected controls the centre frequency of the frequency range that is affected
as described above. as described above.
The ``gain'' parameter controls how much each band is adjusted, and The ``gain'' parameter controls how much each band is adjusted, and
@ -368,11 +369,11 @@ change to customise your listening experience.
frequency range is. Higher Q values will affect a narrower band of frequency range is. Higher Q values will affect a narrower band of
frequencies, while lower Q values will affect a wider band of frequencies, while lower Q values will affect a wider band of
frequencies. frequencies.
\item[Band 9: High shelf filter.] \item[High shelf filter.]
A high shelf filter boosts or lowers all frequencies above a certain A high shelf filter boosts or lowers all frequencies above a certain
frequency limit, much as the ``treble'' control found on ordinary frequency limit, much as the ``treble'' control found on ordinary
stereo systems does. stereo systems does.
The high shelf filter is adjusted the same way as the low shelf filter, A high shelf filter is adjusted the same way as A low shelf filter,
except that it works on the high end of the frequency spectrum rather except that it works on the high end of the frequency spectrum rather
than the low end. than the low end.
\end{description} \end{description}
@ -385,7 +386,7 @@ change to customise your listening experience.
\item[Graphical EQ.] \item[Graphical EQ.]
This option brings up a graphic EQ screen, which allows adjustment of each of This option brings up a graphic EQ screen, which allows adjustment of each of
the three parameters described above (gain, centre frequency, and Q) for each the four parameters described above (gain, centre frequency, Q, and type) for each
of the five EQ bands. of the five EQ bands.
\begin{btnmap} \begin{btnmap}
@ -476,8 +477,8 @@ change to customise your listening experience.
\opt{IRIVER_RC_H100_PAD}{\ButtonRCSelect} \opt{IRIVER_RC_H100_PAD}{\ButtonRCSelect}
\opt{GIGABEAT_RC_PAD,IAUDIO_RC_PAD}{\ButtonRCPlay} \opt{GIGABEAT_RC_PAD,IAUDIO_RC_PAD}{\ButtonRCPlay}
&} &}
Toggles the cursor among the three parameters (gain, centre frequency, Toggles the cursor among the four parameters (type, gain, centre
Q) for the selected EQ band frequency, Q) for the selected EQ band
\\ \\
% %
\opt{IRIVER_H100_PAD,IRIVER_H300_PAD}{\ButtonMode} \opt{IRIVER_H100_PAD,IRIVER_H300_PAD}{\ButtonMode}