diff options
Diffstat (limited to 'apps')
-rw-r--r-- | apps/SOURCES | 1 | ||||
-rw-r--r-- | apps/dsp.c | 61 | ||||
-rw-r--r-- | apps/dsp.h | 1 | ||||
-rw-r--r-- | apps/eq.c | 8 | ||||
-rw-r--r-- | apps/eq_menu.c | 678 | ||||
-rw-r--r-- | apps/eq_menu.h | 28 | ||||
-rw-r--r-- | apps/lang/english.lang | 91 | ||||
-rw-r--r-- | apps/onplay.c | 22 | ||||
-rw-r--r-- | apps/settings.c | 23 | ||||
-rw-r--r-- | apps/settings.h | 34 | ||||
-rw-r--r-- | apps/sound_menu.c | 2 |
11 files changed, 941 insertions, 8 deletions
diff --git a/apps/SOURCES b/apps/SOURCES index 35f78c455e..ef65789588 100644 --- a/apps/SOURCES +++ b/apps/SOURCES | |||
@@ -78,4 +78,5 @@ eq_cf.S | |||
78 | #elif defined(CPU_ARM) && !defined(SIMULATOR) | 78 | #elif defined(CPU_ARM) && !defined(SIMULATOR) |
79 | eq_arm.S | 79 | eq_arm.S |
80 | #endif | 80 | #endif |
81 | eq_menu.c | ||
81 | #endif | 82 | #endif |
diff --git a/apps/dsp.c b/apps/dsp.c index 789cf72b20..e4d28bd083 100644 --- a/apps/dsp.c +++ b/apps/dsp.c | |||
@@ -145,6 +145,7 @@ struct dsp_config | |||
145 | bool dither_enabled; | 145 | bool dither_enabled; |
146 | bool new_gain; | 146 | bool new_gain; |
147 | bool crossfeed_enabled; | 147 | bool crossfeed_enabled; |
148 | bool eq_enabled; | ||
148 | }; | 149 | }; |
149 | 150 | ||
150 | struct resample_data | 151 | struct resample_data |
@@ -618,6 +619,61 @@ static void apply_crossfeed(long* src[], int count) | |||
618 | } | 619 | } |
619 | #endif | 620 | #endif |
620 | 621 | ||
622 | #define EQ_CUTOFF_USER2REAL(x) (0xffffffff / NATIVE_FREQUENCY * (x)) | ||
623 | #define EQ_Q_USER2REAL(x) (((x) << 16) / 10) | ||
624 | #define EQ_GAIN_USER2REAL(x) (((x) << 16) / 10) | ||
625 | |||
626 | /* Synchronize the EQ filters with the global settings */ | ||
627 | void dsp_eq_update_data(bool enabled) | ||
628 | { | ||
629 | int i; | ||
630 | int *setting; | ||
631 | int gain, cutoff, q, maxgain; | ||
632 | |||
633 | dsp->eq_enabled = enabled; | ||
634 | setting = &global_settings.eq_band0_cutoff; | ||
635 | maxgain = 0; | ||
636 | |||
637 | #if defined(CPU_COLDFIRE) && !defined(SIMULATOR) | ||
638 | /* set emac unit for dsp processing, and save old macsr, we're running in | ||
639 | codec thread context at this point, so can't clobber it */ | ||
640 | unsigned long old_macsr = coldfire_get_macsr(); | ||
641 | coldfire_set_macsr(EMAC_FRACTIONAL | EMAC_SATURATE); | ||
642 | #endif | ||
643 | |||
644 | /* Iterate over each band and update the appropriate filter */ | ||
645 | for(i = 0; i < 5; i++) { | ||
646 | cutoff = *setting++; | ||
647 | q = *setting++; | ||
648 | gain = *setting++; | ||
649 | |||
650 | /* Keep track of maxgain for the pre-amp */ | ||
651 | if (gain > maxgain) | ||
652 | maxgain = gain; | ||
653 | |||
654 | if (gain == 0) { | ||
655 | eq_data.enabled[i] = 0; | ||
656 | } else { | ||
657 | if (i == 0) | ||
658 | eq_ls_coefs(EQ_CUTOFF_USER2REAL(cutoff), EQ_Q_USER2REAL(q), | ||
659 | EQ_GAIN_USER2REAL(gain), eq_data.filters[0].coefs); | ||
660 | else if (i == 4) | ||
661 | eq_hs_coefs(EQ_CUTOFF_USER2REAL(cutoff), EQ_Q_USER2REAL(q), | ||
662 | EQ_GAIN_USER2REAL(gain), eq_data.filters[4].coefs); | ||
663 | else | ||
664 | eq_pk_coefs(EQ_CUTOFF_USER2REAL(cutoff), EQ_Q_USER2REAL(q), | ||
665 | EQ_GAIN_USER2REAL(gain), eq_data.filters[i].coefs); | ||
666 | |||
667 | eq_data.enabled[i] = 1; | ||
668 | } | ||
669 | } | ||
670 | |||
671 | #if defined(CPU_COLDFIRE) && !defined(SIMULATOR) | ||
672 | /* set old macsr again */ | ||
673 | coldfire_set_macsr(old_macsr); | ||
674 | #endif | ||
675 | } | ||
676 | |||
621 | /* Apply EQ filters to those bands that have got it switched on. */ | 677 | /* Apply EQ filters to those bands that have got it switched on. */ |
622 | static void eq_process(long **x, unsigned num) | 678 | static void eq_process(long **x, unsigned num) |
623 | { | 679 | { |
@@ -745,9 +801,8 @@ long dsp_process(char* dst, char* src[], long size) | |||
745 | samples = resample(tmp, samples); | 801 | samples = resample(tmp, samples); |
746 | if (dsp->crossfeed_enabled && dsp->stereo_mode != STEREO_MONO) | 802 | if (dsp->crossfeed_enabled && dsp->stereo_mode != STEREO_MONO) |
747 | apply_crossfeed(tmp, samples); | 803 | apply_crossfeed(tmp, samples); |
748 | /* TODO: Might want to wrap this with a generic eq_enabled when the | 804 | if (dsp->eq_enabled) |
749 | settings are in place */ | 805 | eq_process(tmp, samples); |
750 | eq_process(tmp, samples); | ||
751 | write_samples((short*) dst, tmp, samples); | 806 | write_samples((short*) dst, tmp, samples); |
752 | written += samples; | 807 | written += samples; |
753 | dst += samples * sizeof(short) * 2; | 808 | dst += samples * sizeof(short) * 2; |
diff --git a/apps/dsp.h b/apps/dsp.h index f86a4d9989..364c8d80f5 100644 --- a/apps/dsp.h +++ b/apps/dsp.h | |||
@@ -54,6 +54,7 @@ int dsp_stereo_mode(void); | |||
54 | bool dsp_configure(int setting, void *value); | 54 | bool dsp_configure(int setting, void *value); |
55 | void dsp_set_replaygain(bool always); | 55 | void dsp_set_replaygain(bool always); |
56 | void dsp_set_crossfeed(bool enable); | 56 | void dsp_set_crossfeed(bool enable); |
57 | void dsp_eq_update_data(bool enabled); | ||
57 | void sound_set_pitch(int r); | 58 | void sound_set_pitch(int r); |
58 | int sound_get_pitch(void); | 59 | int sound_get_pitch(void); |
59 | #endif | 60 | #endif |
@@ -32,11 +32,11 @@ | |||
32 | */ | 32 | */ |
33 | 33 | ||
34 | #define DIV64(x, y, z) (long)(((long long)(x) << (z))/(y)) | 34 | #define DIV64(x, y, z) (long)(((long long)(x) << (z))/(y)) |
35 | /* TODO: This macro requires the EMAC unit to be in fractional mode | 35 | /* This macro requires the EMAC unit to be in fractional mode |
36 | when the coef generator routines are called. If this can be guaranteeed, | 36 | when the coef generator routines are called. If this can't be guaranteeed, |
37 | then remove the "&& 0" below for faster coef calculation on Coldfire. | 37 | then add "&& 0" below. This will use a slower coef calculation on Coldfire. |
38 | */ | 38 | */ |
39 | #if defined(CPU_COLDFIRE) && !defined(SIMULATOR) && 0 | 39 | #if defined(CPU_COLDFIRE) && !defined(SIMULATOR) |
40 | #define FRACMUL(x, y) \ | 40 | #define FRACMUL(x, y) \ |
41 | ({ \ | 41 | ({ \ |
42 | long t; \ | 42 | long t; \ |
diff --git a/apps/eq_menu.c b/apps/eq_menu.c new file mode 100644 index 0000000000..0e3355fcd9 --- /dev/null +++ b/apps/eq_menu.c | |||
@@ -0,0 +1,678 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2006 Dan Everton | ||
11 | * | ||
12 | * All files in this archive are subject to the GNU General Public License. | ||
13 | * See the file COPYING in the source tree root for full license agreement. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | |||
20 | #include "config.h" | ||
21 | #include <stdio.h> | ||
22 | #include <stdbool.h> | ||
23 | #include <string.h> | ||
24 | #include "eq_menu.h" | ||
25 | #include "system.h" | ||
26 | #include "kernel.h" | ||
27 | #include "lcd.h" | ||
28 | #include "menu.h" | ||
29 | #include "button.h" | ||
30 | #include "mp3_playback.h" | ||
31 | #include "settings.h" | ||
32 | #include "statusbar.h" | ||
33 | #include "screens.h" | ||
34 | #include "icons.h" | ||
35 | #include "font.h" | ||
36 | #include "widgets.h" | ||
37 | #include "lang.h" | ||
38 | #include "sprintf.h" | ||
39 | #include "talk.h" | ||
40 | #include "misc.h" | ||
41 | #include "sound.h" | ||
42 | #include "splash.h" | ||
43 | #include "dsp.h" | ||
44 | #include "tree.h" | ||
45 | #include "talk.h" | ||
46 | #include "screen_access.h" | ||
47 | #include "keyboard.h" | ||
48 | |||
49 | /* Key definitions */ | ||
50 | #if (CONFIG_KEYPAD == IRIVER_H100_PAD || \ | ||
51 | CONFIG_KEYPAD == IRIVER_H300_PAD) | ||
52 | |||
53 | #define EQ_BTN_NEXT_BAND BUTTON_DOWN | ||
54 | #define EQ_BTN_PREV_BAND BUTTON_UP | ||
55 | #define EQ_BTN_CHANGE_MODE BUTTON_SELECT | ||
56 | #define EQ_BTN_EXIT BUTTON_OFF | ||
57 | |||
58 | #elif (CONFIG_KEYPAD == IPOD_4G_PAD) | ||
59 | |||
60 | #define EQ_BTN_NEXT_BAND BUTTON_SCROLL_FWD | ||
61 | #define EQ_BTN_PREV_BAND BUTTON_SCROLL_BACK | ||
62 | #define EQ_BTN_CHANGE_MODE BUTTON_SELECT | ||
63 | #define EQ_BTN_EXIT BUTTON_MENU | ||
64 | |||
65 | #endif | ||
66 | |||
67 | |||
68 | #define EQ_CUTOFF_MIN 20 | ||
69 | #define EQ_CUTOFF_MAX 22040 | ||
70 | #define EQ_CUTOFF_STEP 10 | ||
71 | #define EQ_GAIN_MIN (-240) | ||
72 | #define EQ_GAIN_MAX 240 | ||
73 | #define EQ_GAIN_STEP 1 | ||
74 | #define EQ_Q_MIN 5 | ||
75 | #define EQ_Q_MAX 64 | ||
76 | #define EQ_Q_STEP 1 | ||
77 | |||
78 | #define EQ_USER_DIVISOR 10 | ||
79 | |||
80 | static bool eq_enabled(void) | ||
81 | { | ||
82 | bool result = set_bool(str(LANG_EQUALIZER_ENABLED), | ||
83 | &global_settings.eq_enabled); | ||
84 | |||
85 | dsp_eq_update_data(global_settings.eq_enabled); | ||
86 | |||
87 | return result; | ||
88 | } | ||
89 | |||
90 | static void eq_gain_format(char* buffer, int buffer_size, int value, const char* unit) | ||
91 | { | ||
92 | int v = abs(value); | ||
93 | |||
94 | snprintf(buffer, buffer_size, "%s%d.%d %s", value < 0 ? "-" : "", | ||
95 | v / EQ_USER_DIVISOR, v % EQ_USER_DIVISOR, unit); | ||
96 | } | ||
97 | |||
98 | static void eq_q_format(char* buffer, int buffer_size, int value, const char* unit) | ||
99 | { | ||
100 | snprintf(buffer, buffer_size, "%d.%d %s", value / EQ_USER_DIVISOR, value % EQ_USER_DIVISOR, unit); | ||
101 | } | ||
102 | |||
103 | /* Possibly dodgy way of simplifying the code a bit. */ | ||
104 | #define eq_make_gain_label(buf, bufsize, frequency) snprintf((buf), \ | ||
105 | (bufsize), str(LANG_EQUALIZER_GAIN_ITEM), (frequency)) | ||
106 | |||
107 | #define eq_set_cutoff(band) \ | ||
108 | static bool eq_set_band ## band ## _cutoff(void) \ | ||
109 | { \ | ||
110 | bool result = set_int(str(LANG_EQUALIZER_BAND_CUTOFF), "Hertz", UNIT_HERTZ, \ | ||
111 | &global_settings.eq_band ## band ## _cutoff, NULL, \ | ||
112 | EQ_CUTOFF_STEP, EQ_CUTOFF_MIN, EQ_CUTOFF_MAX, NULL); \ | ||
113 | dsp_eq_update_data(global_settings.eq_enabled); \ | ||
114 | return result; \ | ||
115 | } | ||
116 | |||
117 | #define eq_set_q(band) \ | ||
118 | static bool eq_set_band ## band ## _q(void) \ | ||
119 | { \ | ||
120 | bool result = set_int(str(LANG_EQUALIZER_BAND_Q), "Q", UNIT_INT, \ | ||
121 | &global_settings.eq_band ## band ## _q, NULL, \ | ||
122 | EQ_Q_STEP, EQ_Q_MIN, EQ_Q_MAX, eq_q_format); \ | ||
123 | dsp_eq_update_data(global_settings.eq_enabled); \ | ||
124 | return result; \ | ||
125 | } | ||
126 | |||
127 | #define eq_set_gain(band) \ | ||
128 | static bool eq_set_band ## band ## _gain(void) \ | ||
129 | { \ | ||
130 | bool result = set_int("Band " #band, str(LANG_UNIT_DB), UNIT_DB, \ | ||
131 | &global_settings.eq_band ## band ## _gain, NULL, \ | ||
132 | EQ_GAIN_STEP, EQ_GAIN_MIN, EQ_GAIN_MAX, eq_gain_format); \ | ||
133 | dsp_eq_update_data(global_settings.eq_enabled); \ | ||
134 | return result; \ | ||
135 | } | ||
136 | |||
137 | eq_set_cutoff(0); | ||
138 | eq_set_cutoff(1); | ||
139 | eq_set_cutoff(2); | ||
140 | eq_set_cutoff(3); | ||
141 | eq_set_cutoff(4); | ||
142 | |||
143 | eq_set_q(0); | ||
144 | eq_set_q(1); | ||
145 | eq_set_q(2); | ||
146 | eq_set_q(3); | ||
147 | eq_set_q(4); | ||
148 | |||
149 | eq_set_gain(0); | ||
150 | eq_set_gain(1); | ||
151 | eq_set_gain(2); | ||
152 | eq_set_gain(3); | ||
153 | eq_set_gain(4); | ||
154 | |||
155 | static bool eq_gain_menu(void) | ||
156 | { | ||
157 | int m, i; | ||
158 | int *setting; | ||
159 | bool result; | ||
160 | char gain_label[5][24]; | ||
161 | static struct menu_item items[5] = { | ||
162 | { NULL, eq_set_band0_gain }, | ||
163 | { NULL, eq_set_band1_gain }, | ||
164 | { NULL, eq_set_band2_gain }, | ||
165 | { NULL, eq_set_band3_gain }, | ||
166 | { NULL, eq_set_band4_gain }, | ||
167 | }; | ||
168 | |||
169 | setting = &global_settings.eq_band0_cutoff; | ||
170 | |||
171 | /* Construct menu labels */ | ||
172 | for(i = 0; i < 5; i++) { | ||
173 | eq_make_gain_label(gain_label[i], sizeof(gain_label[i]), | ||
174 | *setting); | ||
175 | items[i].desc = gain_label[i]; | ||
176 | |||
177 | /* Skip to next band */ | ||
178 | setting += 3; | ||
179 | } | ||
180 | |||
181 | m=menu_init( items, sizeof(items) / sizeof(*items), NULL, | ||
182 | NULL, NULL, NULL); | ||
183 | result = menu_run(m); | ||
184 | menu_exit(m); | ||
185 | |||
186 | return result; | ||
187 | } | ||
188 | |||
189 | static bool eq_set_band0(void) | ||
190 | { | ||
191 | int m; | ||
192 | bool result; | ||
193 | static const struct menu_item items[] = { | ||
194 | { ID2P(LANG_EQUALIZER_BAND_CUTOFF), eq_set_band0_cutoff }, | ||
195 | { ID2P(LANG_EQUALIZER_BAND_Q), eq_set_band0_q }, | ||
196 | { ID2P(LANG_EQUALIZER_BAND_GAIN), eq_set_band0_gain }, | ||
197 | }; | ||
198 | |||
199 | m=menu_init( items, sizeof(items) / sizeof(*items), NULL, | ||
200 | NULL, NULL, NULL); | ||
201 | result = menu_run(m); | ||
202 | menu_exit(m); | ||
203 | |||
204 | return result; | ||
205 | } | ||
206 | |||
207 | static bool eq_set_band1(void) | ||
208 | { | ||
209 | int m; | ||
210 | bool result; | ||
211 | static const struct menu_item items[] = { | ||
212 | { ID2P(LANG_EQUALIZER_BAND_CUTOFF), eq_set_band1_cutoff }, | ||
213 | { ID2P(LANG_EQUALIZER_BAND_Q), eq_set_band1_q }, | ||
214 | { ID2P(LANG_EQUALIZER_BAND_GAIN), eq_set_band1_gain }, | ||
215 | }; | ||
216 | |||
217 | m=menu_init( items, sizeof(items) / sizeof(*items), NULL, | ||
218 | NULL, NULL, NULL); | ||
219 | result = menu_run(m); | ||
220 | menu_exit(m); | ||
221 | |||
222 | return result; | ||
223 | } | ||
224 | |||
225 | static bool eq_set_band2(void) | ||
226 | { | ||
227 | int m; | ||
228 | bool result; | ||
229 | static const struct menu_item items[] = { | ||
230 | { ID2P(LANG_EQUALIZER_BAND_CUTOFF), eq_set_band2_cutoff }, | ||
231 | { ID2P(LANG_EQUALIZER_BAND_Q), eq_set_band2_q }, | ||
232 | { ID2P(LANG_EQUALIZER_BAND_GAIN), eq_set_band2_gain }, | ||
233 | }; | ||
234 | |||
235 | m=menu_init( items, sizeof(items) / sizeof(*items), NULL, | ||
236 | NULL, NULL, NULL); | ||
237 | result = menu_run(m); | ||
238 | menu_exit(m); | ||
239 | |||
240 | return result; | ||
241 | } | ||
242 | |||
243 | static bool eq_set_band3(void) | ||
244 | { | ||
245 | int m; | ||
246 | bool result; | ||
247 | static const struct menu_item items[] = { | ||
248 | { ID2P(LANG_EQUALIZER_BAND_CUTOFF), eq_set_band3_cutoff }, | ||
249 | { ID2P(LANG_EQUALIZER_BAND_Q), eq_set_band3_q }, | ||
250 | { ID2P(LANG_EQUALIZER_BAND_GAIN), eq_set_band3_gain }, | ||
251 | }; | ||
252 | |||
253 | m=menu_init( items, sizeof(items) / sizeof(*items), NULL, | ||
254 | NULL, NULL, NULL); | ||
255 | result = menu_run(m); | ||
256 | menu_exit(m); | ||
257 | |||
258 | return result; | ||
259 | } | ||
260 | |||
261 | static bool eq_set_band4(void) | ||
262 | { | ||
263 | int m; | ||
264 | bool result; | ||
265 | static const struct menu_item items[] = { | ||
266 | { ID2P(LANG_EQUALIZER_BAND_CUTOFF), eq_set_band4_cutoff }, | ||
267 | { ID2P(LANG_EQUALIZER_BAND_Q), eq_set_band4_q }, | ||
268 | { ID2P(LANG_EQUALIZER_BAND_GAIN), eq_set_band4_gain }, | ||
269 | }; | ||
270 | |||
271 | m=menu_init( items, sizeof(items) / sizeof(*items), NULL, | ||
272 | NULL, NULL, NULL); | ||
273 | result = menu_run(m); | ||
274 | menu_exit(m); | ||
275 | |||
276 | return result; | ||
277 | } | ||
278 | |||
279 | static bool eq_advanced_menu(void) | ||
280 | { | ||
281 | int m, i; | ||
282 | bool result; | ||
283 | char peak_band_label[3][32]; | ||
284 | static struct menu_item items[] = { | ||
285 | { ID2P(LANG_EQUALIZER_BAND_LOW_SHELF), eq_set_band0 }, | ||
286 | { NULL, eq_set_band1 }, | ||
287 | { NULL, eq_set_band2 }, | ||
288 | { NULL, eq_set_band3 }, | ||
289 | { ID2P(LANG_EQUALIZER_BAND_HIGH_SHELF), eq_set_band4 }, | ||
290 | }; | ||
291 | |||
292 | /* Construct menu labels */ | ||
293 | for(i = 1; i < 4; i++) { | ||
294 | snprintf(peak_band_label[i-1], sizeof(peak_band_label[i-1]), | ||
295 | str(LANG_EQUALIZER_BAND_PEAK), i); | ||
296 | items[i].desc = peak_band_label[i-1]; | ||
297 | } | ||
298 | |||
299 | m=menu_init( items, sizeof(items) / sizeof(*items), NULL, | ||
300 | NULL, NULL, NULL); | ||
301 | result = menu_run(m); | ||
302 | menu_exit(m); | ||
303 | |||
304 | return result; | ||
305 | } | ||
306 | |||
307 | #define SLIDER_KNOB_HEIGHT 6 | ||
308 | #define SLIDER_KNOB_WIDTH 4 | ||
309 | |||
310 | enum eq_slider_mode { | ||
311 | GAIN, | ||
312 | CUTOFF, | ||
313 | Q, | ||
314 | }; | ||
315 | |||
316 | enum eq_type { | ||
317 | LOW_SHELF, | ||
318 | PEAK, | ||
319 | HIGH_SHELF | ||
320 | }; | ||
321 | |||
322 | /* Draw a slider */ | ||
323 | static void draw_slider(const struct screen * screen, int x, int y, | ||
324 | int width, int steps, int current_step) | ||
325 | { | ||
326 | |||
327 | int knob_x = (width / steps) * current_step + (SLIDER_KNOB_WIDTH / 2); | ||
328 | |||
329 | /* Draw groove */ | ||
330 | screen->fillrect(x, y + 2, width, 2); | ||
331 | |||
332 | /* Draw knob */ | ||
333 | screen->fillrect(x + knob_x, y, SLIDER_KNOB_WIDTH, SLIDER_KNOB_HEIGHT); | ||
334 | } | ||
335 | |||
336 | /* Draw the UI for a whole EQ band */ | ||
337 | static int draw_eq_slider(const struct screen * screen, int x, int y, | ||
338 | int width, int cutoff, int q, int gain, bool selected, | ||
339 | enum eq_slider_mode mode, enum eq_type type) | ||
340 | { | ||
341 | char buf[26]; | ||
342 | const char separator[2] = " "; | ||
343 | int steps = (abs(EQ_GAIN_MIN) + abs(EQ_GAIN_MAX)) / EQ_USER_DIVISOR; | ||
344 | int abs_q = abs(q); | ||
345 | int abs_gain = abs(gain); | ||
346 | int current_x, total_height, separator_width, separator_height; | ||
347 | int w, h; | ||
348 | |||
349 | /* Start two pixels in, one for border, one for margin */ | ||
350 | current_x = x + 2; | ||
351 | |||
352 | /* Figure out how large our separator string is */ | ||
353 | screen->getstringsize(separator, &separator_width, &separator_height); | ||
354 | |||
355 | /* Total height includes margins, text, and line selector */ | ||
356 | total_height = separator_height + SLIDER_KNOB_HEIGHT + 2 + 3; | ||
357 | |||
358 | /* Print out the band label */ | ||
359 | if (type == LOW_SHELF) { | ||
360 | screen->putsxy(current_x, y + 2, "LS:"); | ||
361 | screen->getstringsize("LS:", &w, &h); | ||
362 | } else if (type == HIGH_SHELF) { | ||
363 | screen->putsxy(current_x, y + 2, "HS:"); | ||
364 | screen->getstringsize("HS:", &w, &h); | ||
365 | } else { | ||
366 | screen->putsxy(current_x, y + 2, "PK:"); | ||
367 | screen->getstringsize("PK:", &w, &h); | ||
368 | } | ||
369 | current_x += w; | ||
370 | |||
371 | /* Print separator */ | ||
372 | screen->set_drawmode(DRMODE_SOLID); | ||
373 | screen->putsxy(current_x, y + 2, separator); | ||
374 | current_x += separator_width; | ||
375 | |||
376 | /* Print out gain part of status line */ | ||
377 | snprintf(buf, sizeof(buf), "%s%2d.%ddB", gain < 0 ? "-" : " ", | ||
378 | abs_gain / EQ_USER_DIVISOR, abs_gain % EQ_USER_DIVISOR); | ||
379 | |||
380 | if (mode == GAIN && selected) | ||
381 | screen->set_drawmode(DRMODE_SOLID | DRMODE_INVERSEVID); | ||
382 | |||
383 | screen->putsxy(current_x, y + 2, buf); | ||
384 | screen->getstringsize(buf, &w, &h); | ||
385 | current_x += w; | ||
386 | |||
387 | /* Print separator */ | ||
388 | screen->set_drawmode(DRMODE_SOLID); | ||
389 | screen->putsxy(current_x, y + 2, separator); | ||
390 | current_x += separator_width; | ||
391 | |||
392 | /* Print out cutoff part of status line */ | ||
393 | snprintf(buf, sizeof(buf), "%5dHz", cutoff); | ||
394 | |||
395 | if (mode == CUTOFF && selected) | ||
396 | screen->set_drawmode(DRMODE_SOLID | DRMODE_INVERSEVID); | ||
397 | |||
398 | screen->putsxy(current_x, y + 2, buf); | ||
399 | screen->getstringsize(buf, &w, &h); | ||
400 | current_x += w; | ||
401 | |||
402 | /* Print separator */ | ||
403 | screen->set_drawmode(DRMODE_SOLID); | ||
404 | screen->putsxy(current_x, y + 2, separator); | ||
405 | current_x += separator_width; | ||
406 | |||
407 | /* Print out Q part of status line */ | ||
408 | snprintf(buf, sizeof(buf), "%d.%d Q", abs_q / EQ_USER_DIVISOR, | ||
409 | abs_q % EQ_USER_DIVISOR); | ||
410 | |||
411 | if (mode == Q && selected) | ||
412 | screen->set_drawmode(DRMODE_SOLID | DRMODE_INVERSEVID); | ||
413 | |||
414 | screen->putsxy(current_x, y + 2, buf); | ||
415 | screen->getstringsize(buf, &w, &h); | ||
416 | current_x += w; | ||
417 | |||
418 | screen->set_drawmode(DRMODE_SOLID); | ||
419 | |||
420 | /* Draw selection box */ | ||
421 | if (selected) { | ||
422 | screen->drawrect(x, y, width, total_height); | ||
423 | } | ||
424 | |||
425 | /* Draw horizontal slider */ | ||
426 | draw_slider(screen, x + 3, y + h + 3, width - 6, steps, | ||
427 | (EQ_GAIN_MAX + gain) / EQ_USER_DIVISOR); | ||
428 | |||
429 | return total_height; | ||
430 | } | ||
431 | |||
432 | /* Draw's all the EQ sliders. Returns the total height of the sliders drawn */ | ||
433 | static int draw_eq_sliders(int current_band, enum eq_slider_mode mode) | ||
434 | { | ||
435 | int i, gain, q, cutoff; | ||
436 | int height = 2; /* Two pixel margin */ | ||
437 | int slider_width = screens[SCREEN_MAIN].width - 4; /* two pixel margin on each side */ | ||
438 | int *setting = &global_settings.eq_band0_cutoff; | ||
439 | enum eq_type type; | ||
440 | |||
441 | for( i = 0; i < 5; ++i) | ||
442 | { | ||
443 | cutoff = *setting++; | ||
444 | q = *setting++; | ||
445 | gain = *setting++; | ||
446 | |||
447 | if (i == 0) { | ||
448 | type = LOW_SHELF; | ||
449 | } else if (i == 4) { | ||
450 | type = HIGH_SHELF; | ||
451 | } else { | ||
452 | type = PEAK; | ||
453 | } | ||
454 | |||
455 | height += draw_eq_slider(&(screens[SCREEN_MAIN]), 2, height, | ||
456 | slider_width, cutoff, q, gain, i == current_band, mode, type); | ||
457 | |||
458 | /* add a margin */ | ||
459 | height += 2; | ||
460 | } | ||
461 | |||
462 | return height; | ||
463 | } | ||
464 | |||
465 | /* Provides a graphical means of editing the EQ settings */ | ||
466 | bool eq_menu_graphical(void) | ||
467 | { | ||
468 | bool exit_request = false; | ||
469 | bool result = true; | ||
470 | bool has_changed = false; | ||
471 | int button; | ||
472 | int *setting; | ||
473 | int current_band, y, step, min, max, voice_unit; | ||
474 | enum eq_slider_mode mode; | ||
475 | enum eq_type current_type; | ||
476 | char buf[24]; | ||
477 | |||
478 | screens[SCREEN_MAIN].setfont(FONT_SYSFIXED); | ||
479 | screens[SCREEN_MAIN].clear_display(); | ||
480 | |||
481 | /* Start off editing gain on the first band */ | ||
482 | mode = GAIN; | ||
483 | current_type = LOW_SHELF; | ||
484 | current_band = 0; | ||
485 | |||
486 | while (!exit_request) { | ||
487 | /* Clear the screen. The drawing routines expect this */ | ||
488 | screens[SCREEN_MAIN].clear_display(); | ||
489 | |||
490 | /* Draw equalizer band details */ | ||
491 | y = draw_eq_sliders(current_band, mode); | ||
492 | |||
493 | /* Set pointer to the band data currently editable */ | ||
494 | if (mode == GAIN) { | ||
495 | /* gain */ | ||
496 | setting = &global_settings.eq_band0_gain; | ||
497 | setting += current_band * 3; | ||
498 | |||
499 | step = EQ_GAIN_STEP; | ||
500 | min = EQ_GAIN_MIN; | ||
501 | max = EQ_GAIN_MAX; | ||
502 | voice_unit = UNIT_DB; | ||
503 | |||
504 | snprintf(buf, sizeof(buf), str(LANG_EQUALIZER_EDIT_MODE), | ||
505 | str(LANG_EQUALIZER_BAND_GAIN)); | ||
506 | |||
507 | screens[SCREEN_MAIN].putsxy(2, y, buf); | ||
508 | } else if (mode == CUTOFF) { | ||
509 | /* cutoff */ | ||
510 | setting = &global_settings.eq_band0_cutoff; | ||
511 | setting += current_band * 3; | ||
512 | |||
513 | step = EQ_CUTOFF_STEP; | ||
514 | min = EQ_CUTOFF_MIN; | ||
515 | max = EQ_CUTOFF_MAX; | ||
516 | voice_unit = UNIT_HERTZ; | ||
517 | |||
518 | snprintf(buf, sizeof(buf), str(LANG_EQUALIZER_EDIT_MODE), | ||
519 | str(LANG_EQUALIZER_BAND_CUTOFF)); | ||
520 | |||
521 | screens[SCREEN_MAIN].putsxy(2, y, buf); | ||
522 | } else { | ||
523 | /* Q */ | ||
524 | setting = &global_settings.eq_band0_q; | ||
525 | setting += current_band * 3; | ||
526 | |||
527 | step = EQ_Q_STEP; | ||
528 | min = EQ_Q_MIN; | ||
529 | max = EQ_Q_MAX; | ||
530 | voice_unit = UNIT_INT; | ||
531 | |||
532 | snprintf(buf, sizeof(buf), str(LANG_EQUALIZER_EDIT_MODE), | ||
533 | str(LANG_EQUALIZER_BAND_Q)); | ||
534 | |||
535 | screens[SCREEN_MAIN].putsxy(2, y, buf); | ||
536 | } | ||
537 | |||
538 | screens[SCREEN_MAIN].update(); | ||
539 | |||
540 | button = button_get_w_tmo(HZ/10); | ||
541 | |||
542 | switch (button) { | ||
543 | case BUTTON_LEFT: | ||
544 | case BUTTON_LEFT | BUTTON_REPEAT: | ||
545 | *(setting) -= step; | ||
546 | has_changed = true; | ||
547 | if (*(setting) < min) | ||
548 | *(setting) = min; | ||
549 | break; | ||
550 | |||
551 | case BUTTON_RIGHT: | ||
552 | case BUTTON_RIGHT | BUTTON_REPEAT: | ||
553 | *(setting) += step; | ||
554 | has_changed = true; | ||
555 | if (*(setting) > max) | ||
556 | *(setting) = max; | ||
557 | break; | ||
558 | |||
559 | case EQ_BTN_PREV_BAND: | ||
560 | case EQ_BTN_PREV_BAND | BUTTON_REPEAT: | ||
561 | current_band--; | ||
562 | if (current_band < 0) | ||
563 | current_band = 4; /* wrap around */ | ||
564 | break; | ||
565 | |||
566 | case EQ_BTN_NEXT_BAND: | ||
567 | case EQ_BTN_NEXT_BAND | BUTTON_REPEAT: | ||
568 | current_band++; | ||
569 | if (current_band > 4) | ||
570 | current_band = 0; /* wrap around */ | ||
571 | break; | ||
572 | |||
573 | case EQ_BTN_CHANGE_MODE: | ||
574 | case EQ_BTN_CHANGE_MODE | BUTTON_REPEAT: | ||
575 | mode++; | ||
576 | if (mode > Q) | ||
577 | mode = GAIN; /* wrap around */ | ||
578 | break; | ||
579 | |||
580 | case EQ_BTN_EXIT: | ||
581 | case EQ_BTN_EXIT | BUTTON_REPEAT: | ||
582 | exit_request = true; | ||
583 | result = false; | ||
584 | break; | ||
585 | |||
586 | default: | ||
587 | if(default_event_handler(button) == SYS_USB_CONNECTED) { | ||
588 | exit_request = true; | ||
589 | result = true; | ||
590 | } | ||
591 | break; | ||
592 | } | ||
593 | |||
594 | /* Update the filter if the user changed something */ | ||
595 | if (has_changed) | ||
596 | dsp_eq_update_data(global_settings.eq_enabled); | ||
597 | } | ||
598 | |||
599 | /* Reset screen settings */ | ||
600 | screens[SCREEN_MAIN].setfont(FONT_UI); | ||
601 | screens[SCREEN_MAIN].clear_display(); | ||
602 | |||
603 | return result; | ||
604 | } | ||
605 | |||
606 | /* Preset saver. | ||
607 | * TODO: Can the settings system be used to do this instead? | ||
608 | */ | ||
609 | static bool eq_save_preset(void) | ||
610 | { | ||
611 | int fd, i; | ||
612 | char filename[MAX_PATH]; | ||
613 | int *setting; | ||
614 | |||
615 | create_numbered_filename(filename, EQS_DIR, "eq", ".cfg", 2); | ||
616 | |||
617 | /* allow user to modify filename */ | ||
618 | while (true) { | ||
619 | if (!kbd_input(filename, sizeof filename)) { | ||
620 | fd = creat(filename,0); | ||
621 | if (fd < 0) | ||
622 | gui_syncsplash(HZ, true, str(LANG_FAILED)); | ||
623 | else | ||
624 | break; | ||
625 | } | ||
626 | else { | ||
627 | gui_syncsplash(HZ, true, str(LANG_RESET_DONE_CANCEL)); | ||
628 | return false; | ||
629 | } | ||
630 | } | ||
631 | |||
632 | /* TODO: Should we really do this? */ | ||
633 | fdprintf(fd, "eq enabled: yes\r\n"); | ||
634 | |||
635 | setting = &global_settings.eq_band0_cutoff; | ||
636 | |||
637 | for(i = 0; i < 5; ++i) { | ||
638 | fdprintf(fd, "eq band %d cutoff: %d\r\n", i, *setting++); | ||
639 | fdprintf(fd, "eq band %d q: %d\r\n", i, *setting++); | ||
640 | fdprintf(fd, "eq band %d gain: %d\r\n", i, *setting++); | ||
641 | } | ||
642 | |||
643 | close(fd); | ||
644 | |||
645 | gui_syncsplash(HZ, true, (unsigned char *)"%s %s", str(LANG_SETTINGS_SAVED1), | ||
646 | str(LANG_SETTINGS_SAVED2)); | ||
647 | |||
648 | return true; | ||
649 | } | ||
650 | |||
651 | /* Allows browsing of preset files */ | ||
652 | bool eq_browse_presets(void) | ||
653 | { | ||
654 | return rockbox_browse(EQS_DIR, SHOW_CFG); | ||
655 | } | ||
656 | |||
657 | /* Full equalizer menu */ | ||
658 | bool eq_menu(void) | ||
659 | { | ||
660 | int m; | ||
661 | bool result; | ||
662 | static const struct menu_item items[] = { | ||
663 | { ID2P(LANG_EQUALIZER_ENABLED), eq_enabled }, | ||
664 | { ID2P(LANG_EQUALIZER_GRAPHICAL), eq_menu_graphical }, | ||
665 | { ID2P(LANG_EQUALIZER_GAIN), eq_gain_menu }, | ||
666 | { ID2P(LANG_EQUALIZER_ADVANCED), eq_advanced_menu }, | ||
667 | { ID2P(LANG_EQUALIZER_SAVE), eq_save_preset }, | ||
668 | { ID2P(LANG_EQUALIZER_BROWSE), eq_browse_presets }, | ||
669 | }; | ||
670 | |||
671 | m=menu_init( items, sizeof(items) / sizeof(*items), NULL, | ||
672 | NULL, NULL, NULL); | ||
673 | result = menu_run(m); | ||
674 | menu_exit(m); | ||
675 | |||
676 | return result; | ||
677 | } | ||
678 | |||
diff --git a/apps/eq_menu.h b/apps/eq_menu.h new file mode 100644 index 0000000000..a22c1e51b8 --- /dev/null +++ b/apps/eq_menu.h | |||
@@ -0,0 +1,28 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2006 Dan Everton | ||
11 | * | ||
12 | * All files in this archive are subject to the GNU General Public License. | ||
13 | * See the file COPYING in the source tree root for full license agreement. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | #ifndef _EQ_MENU_H | ||
20 | #define _EQ_MENU_H | ||
21 | |||
22 | #include "menu.h" | ||
23 | |||
24 | bool eq_browse_presets(void); | ||
25 | bool eq_menu_graphical(void); | ||
26 | bool eq_menu(void); | ||
27 | |||
28 | #endif | ||
diff --git a/apps/lang/english.lang b/apps/lang/english.lang index c3d458e84c..fa02e06016 100644 --- a/apps/lang/english.lang +++ b/apps/lang/english.lang | |||
@@ -3610,3 +3610,94 @@ desc: prompt shown when about to erase a modified dynamic playlist | |||
3610 | eng: "Erase dynamic playlist?" | 3610 | eng: "Erase dynamic playlist?" |
3611 | voice "" | 3611 | voice "" |
3612 | new: | 3612 | new: |
3613 | |||
3614 | id: LANG_EQUALIZER | ||
3615 | desc: in the sound settings menu | ||
3616 | eng: "Equalizer" | ||
3617 | voice: "Equalizer" | ||
3618 | new: | ||
3619 | |||
3620 | id: LANG_EQUALIZER_ENABLED | ||
3621 | desc: in the equalizer settings menu | ||
3622 | eng: "Enable EQ" | ||
3623 | voice: "Enable EQ" | ||
3624 | new: | ||
3625 | |||
3626 | id: LANG_EQUALIZER_GRAPHICAL | ||
3627 | desc: in the equalizer settings menu | ||
3628 | eng: "Graphical EQ" | ||
3629 | voice: "Graphical EQ" | ||
3630 | new: | ||
3631 | |||
3632 | id: LANG_EQUALIZER_GAIN | ||
3633 | desc: in the equalizer settings menu | ||
3634 | eng: "Simple EQ Settings" | ||
3635 | voice: "Simple EQ Settings" | ||
3636 | new: | ||
3637 | |||
3638 | id: LANG_EQUALIZER_ADVANCED | ||
3639 | desc: in the equalizer settings menu | ||
3640 | eng: "Advanced EQ Settings" | ||
3641 | voice: "Advanced EQ Settings" | ||
3642 | new: | ||
3643 | |||
3644 | id: LANG_EQUALIZER_SAVE | ||
3645 | desc: in the equalizer settings menu | ||
3646 | eng: "Save EQ Preset" | ||
3647 | voice: "Save EQ Preset" | ||
3648 | new: | ||
3649 | |||
3650 | id: LANG_EQUALIZER_BROWSE | ||
3651 | desc: in the equalizer settings menu | ||
3652 | eng: "Browse EQ Presets" | ||
3653 | voice: "Browse EQ Presets" | ||
3654 | new: | ||
3655 | |||
3656 | id: LANG_EQUALIZER_GAIN_ITEM | ||
3657 | desc: in the equalizer settings menu | ||
3658 | eng: "%d Hz Band Gain" | ||
3659 | voice: "" | ||
3660 | new: | ||
3661 | |||
3662 | id: LANG_EQUALIZER_BAND_CUTOFF | ||
3663 | desc: in the equalizer settings menu | ||
3664 | eng: "Cutoff" | ||
3665 | voice: "Cutoff" | ||
3666 | new: | ||
3667 | |||
3668 | id: LANG_EQUALIZER_BAND_Q | ||
3669 | desc: in the equalizer settings menu | ||
3670 | eng: "Q" | ||
3671 | voice: "Q" | ||
3672 | new: | ||
3673 | |||
3674 | id: LANG_EQUALIZER_BAND_GAIN | ||
3675 | desc: in the equalizer settings menu | ||
3676 | eng: "Gain" | ||
3677 | voice: "Gain" | ||
3678 | new: | ||
3679 | |||
3680 | id: LANG_EQUALIZER_EDIT_MODE | ||
3681 | desc: in the equalizer settings menu | ||
3682 | eng: "Edit mode: %s" | ||
3683 | voice: "" | ||
3684 | new: | ||
3685 | |||
3686 | id: LANG_EQUALIZER_BAND_LOW_SHELF | ||
3687 | desc: in the equalizer settings menu | ||
3688 | eng: "Low Shelf Filter" | ||
3689 | voice: "" | ||
3690 | new: | ||
3691 | |||
3692 | id: LANG_EQUALIZER_BAND_PEAK | ||
3693 | desc: in the equalizer settings menu | ||
3694 | eng: "Peak Filter %d" | ||
3695 | voice: "" | ||
3696 | new: | ||
3697 | |||
3698 | id: LANG_EQUALIZER_BAND_HIGH_SHELF | ||
3699 | desc: in the equalizer settings menu | ||
3700 | eng: "High Shelf Filter" | ||
3701 | voice: "" | ||
3702 | new: | ||
3703 | |||
diff --git a/apps/onplay.c b/apps/onplay.c index 17b4d1591b..9b94be0959 100644 --- a/apps/onplay.c +++ b/apps/onplay.c | |||
@@ -58,6 +58,9 @@ | |||
58 | #include "main_menu.h" | 58 | #include "main_menu.h" |
59 | #include "sound_menu.h" | 59 | #include "sound_menu.h" |
60 | #include "database.h" | 60 | #include "database.h" |
61 | #if CONFIG_CODEC == SWCODEC | ||
62 | #include "eq_menu.h" | ||
63 | #endif | ||
61 | 64 | ||
62 | static int context; | 65 | static int context; |
63 | static char* selected_file = NULL; | 66 | static char* selected_file = NULL; |
@@ -537,7 +540,11 @@ static int onplay_callback(int key, int menu) | |||
537 | 540 | ||
538 | int onplay(char* file, int attr, int from) | 541 | int onplay(char* file, int attr, int from) |
539 | { | 542 | { |
540 | struct menu_item items[8]; /* increase this if you add entries! */ | 543 | #if CONFIG_CODEC == SWCODEC |
544 | struct menu_item items[10]; /* increase this if you add entries! */ | ||
545 | #else | ||
546 | struct menu_item items[8]; | ||
547 | #endif | ||
541 | int m, i=0, result; | 548 | int m, i=0, result; |
542 | #ifdef HAVE_LCD_COLOR | 549 | #ifdef HAVE_LCD_COLOR |
543 | char *suffix; | 550 | char *suffix; |
@@ -641,6 +648,19 @@ int onplay(char* file, int attr, int from) | |||
641 | i++; | 648 | i++; |
642 | } | 649 | } |
643 | 650 | ||
651 | #if CONFIG_CODEC == SWCODEC | ||
652 | /* Equalizer menu items */ | ||
653 | if (context == CONTEXT_WPS) | ||
654 | { | ||
655 | items[i].desc = ID2P(LANG_EQUALIZER_GRAPHICAL); | ||
656 | items[i].function = eq_menu_graphical; | ||
657 | i++; | ||
658 | items[i].desc = ID2P(LANG_EQUALIZER_BROWSE); | ||
659 | items[i].function = eq_browse_presets; | ||
660 | i++; | ||
661 | } | ||
662 | #endif | ||
663 | |||
644 | /* DIY menu handling, since we want to exit after selection */ | 664 | /* DIY menu handling, since we want to exit after selection */ |
645 | if (i) | 665 | if (i) |
646 | { | 666 | { |
diff --git a/apps/settings.c b/apps/settings.c index d13f56891e..ea8c562a04 100644 --- a/apps/settings.c +++ b/apps/settings.c | |||
@@ -511,6 +511,28 @@ static const struct bit_entry hd_bits[] = | |||
511 | {1, S_O(warnon_erase_dynplaylist), false, | 511 | {1, S_O(warnon_erase_dynplaylist), false, |
512 | "warn when erasing dynamic playlist", off_on }, | 512 | "warn when erasing dynamic playlist", off_on }, |
513 | 513 | ||
514 | #if CONFIG_CODEC == SWCODEC | ||
515 | {1, S_O(eq_enabled), false, "eq enabled", off_on }, | ||
516 | /* 0..32768 Hz */ | ||
517 | {15, S_O(eq_band0_cutoff), 60, "eq band 0 cutoff", NULL }, | ||
518 | {15, S_O(eq_band1_cutoff), 200, "eq band 1 cutoff", NULL }, | ||
519 | {15, S_O(eq_band2_cutoff), 800, "eq band 2 cutoff", NULL }, | ||
520 | {15, S_O(eq_band3_cutoff), 4000, "eq band 3 cutoff", NULL }, | ||
521 | {15, S_O(eq_band4_cutoff), 12000, "eq band 4 cutoff", NULL }, | ||
522 | /* 0..64 (or 0.0 to 6.4) */ | ||
523 | {6, S_O(eq_band0_q), 7, "eq band 0 q", NULL }, | ||
524 | {6, S_O(eq_band1_q), 10, "eq band 1 q", NULL }, | ||
525 | {6, S_O(eq_band2_q), 10, "eq band 2 q", NULL }, | ||
526 | {6, S_O(eq_band3_q), 10, "eq band 3 q", NULL }, | ||
527 | {6, S_O(eq_band4_q), 7, "eq band 4 q", NULL }, | ||
528 | /* -240..240 (or -24db to +24db) */ | ||
529 | {9|SIGNED, S_O(eq_band0_gain), 0, "eq band 0 gain", NULL }, | ||
530 | {9|SIGNED, S_O(eq_band1_gain), 0, "eq band 1 gain", NULL }, | ||
531 | {9|SIGNED, S_O(eq_band2_gain), 0, "eq band 2 gain", NULL }, | ||
532 | {9|SIGNED, S_O(eq_band3_gain), 0, "eq band 3 gain", NULL }, | ||
533 | {9|SIGNED, S_O(eq_band4_gain), 0, "eq band 4 gain", NULL }, | ||
534 | #endif | ||
535 | |||
514 | /* If values are just added to the end, no need to bump the version. */ | 536 | /* If values are just added to the end, no need to bump the version. */ |
515 | /* new stuff to be added at the end */ | 537 | /* new stuff to be added at the end */ |
516 | 538 | ||
@@ -1023,6 +1045,7 @@ void settings_apply(void) | |||
1023 | audio_set_crossfade(global_settings.crossfade); | 1045 | audio_set_crossfade(global_settings.crossfade); |
1024 | dsp_set_replaygain(true); | 1046 | dsp_set_replaygain(true); |
1025 | dsp_set_crossfeed(global_settings.crossfeed); | 1047 | dsp_set_crossfeed(global_settings.crossfeed); |
1048 | dsp_eq_update_data(global_settings.eq_enabled); | ||
1026 | #endif | 1049 | #endif |
1027 | 1050 | ||
1028 | #ifdef HAVE_SPDIF_POWER | 1051 | #ifdef HAVE_SPDIF_POWER |
diff --git a/apps/settings.h b/apps/settings.h index 3255f61ff3..6efaacbaf3 100644 --- a/apps/settings.h +++ b/apps/settings.h | |||
@@ -39,6 +39,7 @@ | |||
39 | #define PLUGIN_DIR ROCKBOX_DIR"/rocks" | 39 | #define PLUGIN_DIR ROCKBOX_DIR"/rocks" |
40 | #define BACKDROP_DIR ROCKBOX_DIR"/backdrops" | 40 | #define BACKDROP_DIR ROCKBOX_DIR"/backdrops" |
41 | #define REC_BASE_DIR "/recordings" | 41 | #define REC_BASE_DIR "/recordings" |
42 | #define EQS_DIR ROCKBOX_DIR "/eqs" | ||
42 | 43 | ||
43 | #define MAX_FILENAME 20 | 44 | #define MAX_FILENAME 20 |
44 | 45 | ||
@@ -408,6 +409,39 @@ struct user_settings | |||
408 | int brightness; /* iriver h300: backlight PWM value: 2..15 | 409 | int brightness; /* iriver h300: backlight PWM value: 2..15 |
409 | (0 and 1 are black) */ | 410 | (0 and 1 are black) */ |
410 | #endif | 411 | #endif |
412 | |||
413 | #if CONFIG_CODEC == SWCODEC | ||
414 | bool eq_enabled; /* Enable equalizer */ | ||
415 | |||
416 | /* Order is important here, must be cutoff, q, then gain for each band. | ||
417 | See dsp_eq_update_data in dsp.c for why. */ | ||
418 | |||
419 | /* Band 0 settings */ | ||
420 | int eq_band0_cutoff; /* Hz */ | ||
421 | int eq_band0_q; | ||
422 | int eq_band0_gain; /* +/- dB */ | ||
423 | |||
424 | /* Band 1 settings */ | ||
425 | int eq_band1_cutoff; /* Hz */ | ||
426 | int eq_band1_q; | ||
427 | int eq_band1_gain; /* +/- dB */ | ||
428 | |||
429 | /* Band 2 settings */ | ||
430 | int eq_band2_cutoff; /* Hz */ | ||
431 | int eq_band2_q; | ||
432 | int eq_band2_gain; /* +/- dB */ | ||
433 | |||
434 | /* Band 3 settings */ | ||
435 | int eq_band3_cutoff; /* Hz */ | ||
436 | int eq_band3_q; | ||
437 | int eq_band3_gain; /* +/- dB */ | ||
438 | |||
439 | /* Band 4 settings */ | ||
440 | int eq_band4_cutoff; /* Hz */ | ||
441 | int eq_band4_q; | ||
442 | int eq_band4_gain; /* +/- dB */ | ||
443 | #endif | ||
444 | |||
411 | #ifdef HAVE_LCD_COLOR | 445 | #ifdef HAVE_LCD_COLOR |
412 | unsigned char backdrop_file[MAX_FILENAME+1]; /* backdrop bitmap file */ | 446 | unsigned char backdrop_file[MAX_FILENAME+1]; /* backdrop bitmap file */ |
413 | #endif | 447 | #endif |
diff --git a/apps/sound_menu.c b/apps/sound_menu.c index e44aa68231..2bd0ff6e59 100644 --- a/apps/sound_menu.c +++ b/apps/sound_menu.c | |||
@@ -45,6 +45,7 @@ | |||
45 | #include "splash.h" | 45 | #include "splash.h" |
46 | #if CONFIG_CODEC == SWCODEC | 46 | #if CONFIG_CODEC == SWCODEC |
47 | #include "dsp.h" | 47 | #include "dsp.h" |
48 | #include "eq_menu.h" | ||
48 | #endif | 49 | #endif |
49 | 50 | ||
50 | int selected_setting; /* Used by the callback */ | 51 | int selected_setting; /* Used by the callback */ |
@@ -379,6 +380,7 @@ bool sound_menu(void) | |||
379 | { ID2P(LANG_STEREO_WIDTH), stereo_width }, | 380 | { ID2P(LANG_STEREO_WIDTH), stereo_width }, |
380 | #if CONFIG_CODEC == SWCODEC | 381 | #if CONFIG_CODEC == SWCODEC |
381 | { ID2P(LANG_CROSSFEED), crossfeed }, | 382 | { ID2P(LANG_CROSSFEED), crossfeed }, |
383 | { ID2P(LANG_EQUALIZER), eq_menu }, | ||
382 | #endif | 384 | #endif |
383 | #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) | 385 | #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) |
384 | { ID2P(LANG_LOUDNESS), loudness }, | 386 | { ID2P(LANG_LOUDNESS), loudness }, |