summaryrefslogtreecommitdiff
path: root/apps/gui/pitchscreen.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/gui/pitchscreen.c')
-rw-r--r--apps/gui/pitchscreen.c284
1 files changed, 284 insertions, 0 deletions
diff --git a/apps/gui/pitchscreen.c b/apps/gui/pitchscreen.c
new file mode 100644
index 0000000000..b790835fcb
--- /dev/null
+++ b/apps/gui/pitchscreen.c
@@ -0,0 +1,284 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 Björn Stenberg
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 <stdbool.h>
21#include <string.h>
22#include <stdio.h>
23#include "config.h"
24#include "sprintf.h"
25#include "settings.h"
26#include "action.h"
27#include "system.h"
28#include "font.h"
29#include "misc.h"
30#include "dsp.h"
31#include "sound.h"
32#include "pcmbuf.h"
33#include "lang.h"
34#include "icons.h"
35#include "screen_access.h"
36
37#define PITCH_MAX 2000
38#define PITCH_MIN 500
39#define PITCH_SMALL_DELTA 1
40#define PITCH_BIG_DELTA 10
41#define PITCH_NUDGE_DELTA 20
42
43#define PITCH_MODE_ABSOLUTE 1
44#define PITCH_MODE_SEMITONE -PITCH_MODE_ABSOLUTE
45
46static int pitch_mode = PITCH_MODE_ABSOLUTE; /* 1 - absolute, -1 - semitone */
47
48/* returns:
49 0 if no key was pressed
50 1 if USB was connected */
51
52static void pitch_screen_draw(struct screen *display, int pitch, int pitch_mode)
53{
54 unsigned char* ptr;
55 unsigned char buf[32];
56 int w, h;
57
58 display->clear_display();
59
60 if (display->nb_lines < 4) /* very small screen, just show the pitch value */
61 {
62 w = snprintf((char *)buf, sizeof(buf), "%s: %d.%d%%",str(LANG_PITCH),
63 pitch / 10, pitch % 10 );
64 display->putsxy((display->width-(w*display->char_width))/2,
65 display->nb_lines/2,buf);
66 }
67 else /* bigger screen, show everything... */
68 {
69
70 /* UP: Pitch Up */
71 if (pitch_mode == PITCH_MODE_ABSOLUTE) {
72 ptr = str(LANG_PITCH_UP);
73 } else {
74 ptr = str(LANG_PITCH_UP_SEMITONE);
75 }
76 display->getstringsize(ptr,&w,&h);
77 display->putsxy((display->width-w)/2, 0, ptr);
78 display->mono_bitmap(bitmap_icons_7x8[Icon_UpArrow],
79 display->width/2 - 3, h, 7, 8);
80
81 /* DOWN: Pitch Down */
82 if (pitch_mode == PITCH_MODE_ABSOLUTE) {
83 ptr = str(LANG_PITCH_DOWN);
84 } else {
85 ptr = str(LANG_PITCH_DOWN_SEMITONE);
86 }
87 display->getstringsize(ptr,&w,&h);
88 display->putsxy((display->width-w)/2, display->height - h, ptr);
89 display->mono_bitmap(bitmap_icons_7x8[Icon_DownArrow],
90 display->width/2 - 3, display->height - h*2, 7, 8);
91
92 /* RIGHT: +2% */
93 ptr = "+2%";
94 display->getstringsize(ptr,&w,&h);
95 display->putsxy(display->width-w, (display->height-h)/2, ptr);
96 display->mono_bitmap(bitmap_icons_7x8[Icon_FastForward],
97 display->width-w-8, (display->height-h)/2, 7, 8);
98
99 /* LEFT: -2% */
100 ptr = "-2%";
101 display->getstringsize(ptr,&w,&h);
102 display->putsxy(0, (display->height-h)/2, ptr);
103 display->mono_bitmap(bitmap_icons_7x8[Icon_FastBackward],
104 w+1, (display->height-h)/2, 7, 8);
105
106 /* "Pitch" */
107 snprintf((char *)buf, sizeof(buf), str(LANG_PITCH));
108 display->getstringsize(buf,&w,&h);
109 display->putsxy((display->width-w)/2, (display->height/2)-h, buf);
110 /* "XX.X%" */
111 snprintf((char *)buf, sizeof(buf), "%d.%d%%",
112 pitch / 10, pitch % 10 );
113 display->getstringsize(buf,&w,&h);
114 display->putsxy((display->width-w)/2, display->height/2, buf);
115 }
116
117 display->update();
118}
119
120static int pitch_increase(int pitch, int delta, bool allow_cutoff)
121{
122 int new_pitch;
123
124 if (delta < 0) {
125 if (pitch + delta >= PITCH_MIN) {
126 new_pitch = pitch + delta;
127 } else {
128 if (!allow_cutoff) {
129 return pitch;
130 }
131 new_pitch = PITCH_MIN;
132 }
133 } else if (delta > 0) {
134 if (pitch + delta <= PITCH_MAX) {
135 new_pitch = pitch + delta;
136 } else {
137 if (!allow_cutoff) {
138 return pitch;
139 }
140 new_pitch = PITCH_MAX;
141 }
142 } else {
143 /* delta == 0 -> no real change */
144 return pitch;
145 }
146 sound_set_pitch(new_pitch);
147
148 return new_pitch;
149}
150
151/* Factor for changing the pitch one half tone up.
152 The exact value is 2^(1/12) = 1.05946309436
153 But we use only integer arithmetics, so take
154 rounded factor multiplied by 10^5=100,000. This is
155 enough to get the same promille values as if we
156 had used floating point (checked with a spread
157 sheet).
158 */
159#define PITCH_SEMITONE_FACTOR 105946L
160
161/* Some helpful constants. K is the scaling factor for SEMITONE.
162 N is for more accurate rounding
163 KN is K * N
164 */
165#define PITCH_K_FCT 100000UL
166#define PITCH_N_FCT 10
167#define PITCH_KN_FCT 1000000UL
168
169static int pitch_increase_semitone(int pitch, bool up)
170{
171 uint32_t tmp;
172 uint32_t round_fct; /* How much to scale down at the end */
173 tmp = pitch;
174 if (up) {
175 tmp = tmp * PITCH_SEMITONE_FACTOR;
176 round_fct = PITCH_K_FCT;
177 } else {
178 tmp = (tmp * PITCH_KN_FCT) / PITCH_SEMITONE_FACTOR;
179 round_fct = PITCH_N_FCT;
180 }
181 /* Scaling down with rounding */
182 tmp = (tmp + round_fct / 2) / round_fct;
183 return pitch_increase(pitch, tmp - pitch, false);
184}
185
186bool pitch_screen(void)
187{
188 int button;
189 int pitch = sound_get_pitch();
190 int new_pitch, delta = 0;
191 bool nudged = false;
192 bool exit = false;
193 int i;
194
195#if CONFIG_CODEC == SWCODEC
196 pcmbuf_set_low_latency(true);
197#endif
198
199 while (!exit)
200 {
201 FOR_NB_SCREENS(i)
202 pitch_screen_draw(&screens[i], pitch, pitch_mode);
203
204 button = get_action(CONTEXT_PITCHSCREEN,TIMEOUT_BLOCK);
205 switch (button) {
206 case ACTION_PS_INC_SMALL:
207 delta = PITCH_SMALL_DELTA;
208 break;
209
210 case ACTION_PS_INC_BIG:
211 delta = PITCH_BIG_DELTA;
212 break;
213
214 case ACTION_PS_DEC_SMALL:
215 delta = -PITCH_SMALL_DELTA;
216 break;
217
218 case ACTION_PS_DEC_BIG:
219 delta = -PITCH_BIG_DELTA;
220 break;
221
222 case ACTION_PS_NUDGE_RIGHT:
223 new_pitch = pitch_increase(pitch, PITCH_NUDGE_DELTA, false);
224 nudged = (new_pitch != pitch);
225 pitch = new_pitch;
226 break;
227
228 case ACTION_PS_NUDGE_RIGHTOFF:
229 if (nudged) {
230 pitch = pitch_increase(pitch, -PITCH_NUDGE_DELTA, false);
231 }
232 nudged = false;
233 break;
234
235 case ACTION_PS_NUDGE_LEFT:
236 new_pitch = pitch_increase(pitch, -PITCH_NUDGE_DELTA, false);
237 nudged = (new_pitch != pitch);
238 pitch = new_pitch;
239 break;
240
241 case ACTION_PS_NUDGE_LEFTOFF:
242 if (nudged) {
243 pitch = pitch_increase(pitch, PITCH_NUDGE_DELTA, false);
244 }
245 nudged = false;
246 break;
247
248 case ACTION_PS_RESET:
249 pitch = 1000;
250 sound_set_pitch( pitch );
251 break;
252
253 case ACTION_PS_TOGGLE_MODE:
254 pitch_mode = -pitch_mode;
255 break;
256
257 case ACTION_PS_EXIT:
258 exit = true;
259 break;
260
261 default:
262 if(default_event_handler(button) == SYS_USB_CONNECTED)
263 return 1;
264 break;
265 }
266
267 if(delta)
268 {
269 if (pitch_mode == PITCH_MODE_ABSOLUTE) {
270 pitch = pitch_increase(pitch, delta, true);
271 } else {
272 pitch = pitch_increase_semitone(pitch, delta > 0 ? true:false);
273 }
274
275 delta = 0;
276 }
277
278 }
279#if CONFIG_CODEC == SWCODEC
280 pcmbuf_set_low_latency(false);
281#endif
282 lcd_setfont(FONT_UI);
283 return 0;
284}