diff options
-rw-r--r-- | engine.c | 348 |
1 files changed, 174 insertions, 174 deletions
@@ -23,88 +23,88 @@ static void highlight_line(int value, int y, int max_x, uint32_t color); | |||
23 | void | 23 | void |
24 | engine_redraw() | 24 | engine_redraw() |
25 | { | 25 | { |
26 | const char *config_hints[] = { "No", "Harfe", "File", "Edit" }; | 26 | const char *config_hints[] = { "No", "Harfe", "File", "Edit" }; |
27 | char text[32]; | 27 | char text[32]; |
28 | const int tos1 = g_midi_three_octave_split_1, tos2 = g_midi_three_octave_split_2; | 28 | const int tos1 = g_midi_three_octave_split_1, tos2 = g_midi_three_octave_split_2; |
29 | const int height = g_max_y - g_min_y; | 29 | const int height = g_max_y - g_min_y; |
30 | int i, x2, MAX_X, MAX_Y, FONT_HEIGHT; | 30 | int i, x2, MAX_X, MAX_Y, FONT_HEIGHT; |
31 | 31 | ||
32 | display_redraw(); | 32 | display_redraw(); |
33 | display_clear(); | 33 | display_clear(); |
34 | display_getdimensions(&MAX_X, &MAX_Y, &FONT_HEIGHT); | 34 | display_getdimensions(&MAX_X, &MAX_Y, &FONT_HEIGHT); |
35 | 35 | ||
36 | if (!g_importing_config) | 36 | if (!g_importing_config) |
37 | snprintf( text, sizeof(text), g_harfe_connected ? "online (%s)" : "offline (%s)", config_hints[(int)g_config_source]); | 37 | snprintf( text, sizeof(text), g_harfe_connected ? "online (%s)" : "offline (%s)", config_hints[(int)g_config_source]); |
38 | else | 38 | else |
39 | snprintf( text, sizeof(text), "importing config (%s)", config_hints[(int)g_config_source]); | 39 | snprintf( text, sizeof(text), "importing config (%s)", config_hints[(int)g_config_source]); |
40 | display_text(text, 8, MAX_Y - 4, g_harfe_connected ? 0x00ff3fff : 0xff003fff ); | 40 | display_text(text, 8, MAX_Y - 4, g_harfe_connected ? 0x00ff3fff : 0xff003fff ); |
41 | 41 | ||
42 | menu_redraw(); | 42 | menu_redraw(); |
43 | 43 | ||
44 | if (height) { | 44 | if (height) { |
45 | int b = g_midi_three_octave_split_inverse; | 45 | int b = g_midi_three_octave_split_inverse; |
46 | display_text( b ? "+1" : "-1", 4, scale(g_min_y + tos1 * height / 200) + FONT_HEIGHT / 2, 0x007f7f7fff); | 46 | display_text( b ? "+1" : "-1", 4, scale(g_min_y + tos1 * height / 200) + FONT_HEIGHT / 2, 0x007f7f7fff); |
47 | display_text( " 0", 4, scale(g_min_y + (tos1 + tos2) * height / 200) + FONT_HEIGHT / 2, 0x007f7f7fff); | 47 | display_text( " 0", 4, scale(g_min_y + (tos1 + tos2) * height / 200) + FONT_HEIGHT / 2, 0x007f7f7fff); |
48 | display_text( b ? "-1" : "+1", 4, scale(g_min_y + (tos2 / 2 + 50 ) * height / 100) + FONT_HEIGHT / 2, 0x007f7f7fff); | 48 | display_text( b ? "-1" : "+1", 4, scale(g_min_y + (tos2 / 2 + 50 ) * height / 100) + FONT_HEIGHT / 2, 0x007f7f7fff); |
49 | 49 | ||
50 | display_line_color(0, scale(g_min_y), MAX_X, scale(g_min_y), 0xff00ffff); | 50 | display_line_color(0, scale(g_min_y), MAX_X, scale(g_min_y), 0xff00ffff); |
51 | display_line_color(0, scale(g_max_y), MAX_X, scale(g_max_y), 0xff00ffff); | 51 | display_line_color(0, scale(g_max_y), MAX_X, scale(g_max_y), 0xff00ffff); |
52 | #ifdef HAVE_TWO_OCTAVE_MODE | 52 | #ifdef HAVE_TWO_OCTAVE_MODE |
53 | display_line_color(0, scale(g_min_y + g_midi_two_octave_split * height / 100), MAX_X, scale(g_min_y + g_midi_two_octave_split * height / 100), 0xffff00ff); | 53 | display_line_color(0, scale(g_min_y + g_midi_two_octave_split * height / 100), MAX_X, scale(g_min_y + g_midi_two_octave_split * height / 100), 0xffff00ff); |
54 | #endif | 54 | #endif |
55 | display_line_color(0, scale(g_min_y + tos1 * height / 100), MAX_X, scale(g_min_y + tos1 * height / 100), 0x00ff00ff); | 55 | display_line_color(0, scale(g_min_y + tos1 * height / 100), MAX_X, scale(g_min_y + tos1 * height / 100), 0x00ff00ff); |
56 | display_line_color(0, scale(g_min_y + tos2 * height / 100), MAX_X, scale(g_min_y + tos2 * height / 100), 0x00ff00ff); | 56 | display_line_color(0, scale(g_min_y + tos2 * height / 100), MAX_X, scale(g_min_y + tos2 * height / 100), 0x00ff00ff); |
57 | 57 | ||
58 | switch (g_selected_config) { | 58 | switch (g_selected_config) { |
59 | case sel_min_y: highlight_line(g_min_y, g_min_y, MAX_X, 0xff00ffff); break; | 59 | case sel_min_y: highlight_line(g_min_y, g_min_y, MAX_X, 0xff00ffff); break; |
60 | case sel_max_y: highlight_line(g_max_y, g_max_y, MAX_X, 0xff00ffff); break; | 60 | case sel_max_y: highlight_line(g_max_y, g_max_y, MAX_X, 0xff00ffff); break; |
61 | case sel_2_oct: highlight_line(g_midi_two_octave_split, g_min_y + g_midi_two_octave_split * height / 100, MAX_X, 0xffff00ff); break; | 61 | case sel_2_oct: highlight_line(g_midi_two_octave_split, g_min_y + g_midi_two_octave_split * height / 100, MAX_X, 0xffff00ff); break; |
62 | case sel_3_oct_top: highlight_line(tos2, g_min_y + tos2 * height / 100, MAX_X, 0x00ff00ff); break; | 62 | case sel_3_oct_top: highlight_line(tos2, g_min_y + tos2 * height / 100, MAX_X, 0x00ff00ff); break; |
63 | case sel_3_oct_bottom: highlight_line(tos1, g_min_y + tos1 * height / 100, MAX_X, 0x00ff00ff); break; | 63 | case sel_3_oct_bottom: highlight_line(tos1, g_min_y + tos1 * height / 100, MAX_X, 0x00ff00ff); break; |
64 | case sel_none: break; | 64 | case sel_none: break; |
65 | } | 65 | } |
66 | 66 | ||
67 | for (i = 0; i < g_string_count; ++i) { | 67 | for (i = 0; i < g_string_count; ++i) { |
68 | LLine *l = &g_string_conf[i].line; | 68 | LLine *l = &g_string_conf[i].line; |
69 | LLine _l = g_string_conf[i].line; // Copy for extension | 69 | LLine _l = g_string_conf[i].line; // Copy for extension |
70 | uint32_t color = ( ( i == g_selected_string ) ? 0xff00ffff : 0x00ffffffff ); | 70 | uint32_t color = ( ( i == g_selected_string ) ? 0xff00ffff : 0x00ffffffff ); |
71 | uint32_t text_color = ( ( i == g_selected_string ) ? 0xff00ffff : 0x007f7f7fff ); | 71 | uint32_t text_color = ( ( i == g_selected_string ) ? 0xff00ffff : 0x007f7f7fff ); |
72 | int extended = 0, center_y = g_min_y+height/2; | 72 | int extended = 0, center_y = g_min_y+height/2; |
73 | 73 | ||
74 | if (_l.p0.y > g_min_y) { | 74 | if (_l.p0.y > g_min_y) { |
75 | _l.p0.x = get_x_for_y(&_l.p0, &_l.p1, g_min_y); | 75 | _l.p0.x = get_x_for_y(&_l.p0, &_l.p1, g_min_y); |
76 | _l.p0.y = g_min_y; | 76 | _l.p0.y = g_min_y; |
77 | extended = 1; | 77 | extended = 1; |
78 | } | 78 | } |
79 | if (_l.p1.y < g_max_y) { | 79 | if (_l.p1.y < g_max_y) { |
80 | _l.p1.x = get_x_for_y(&l->p0 /* Using unmodified original! */, &_l.p1, g_max_y); | 80 | _l.p1.x = get_x_for_y(&l->p0 /* Using unmodified original! */, &_l.p1, g_max_y); |
81 | _l.p1.y = g_max_y; | 81 | _l.p1.y = g_max_y; |
82 | extended = 1; | 82 | extended = 1; |
83 | } | 83 | } |
84 | if (extended) { | 84 | if (extended) { |
85 | display_line_color(scale(_l.p0.x), scale(_l.p0.y), scale(_l.p1.x), scale(_l.p1.y), 0x007f3f00); | 85 | display_line_color(scale(_l.p0.x), scale(_l.p0.y), scale(_l.p1.x), scale(_l.p1.y), 0x007f3f00); |
86 | display_circle_color(scale(_l.p0.x), scale(_l.p0.y), 4, 0x007f3f00); | 86 | display_circle_color(scale(_l.p0.x), scale(_l.p0.y), 4, 0x007f3f00); |
87 | display_circle_color(scale(_l.p1.x), scale(_l.p1.y), 4, 0x007f3f00); | 87 | display_circle_color(scale(_l.p1.x), scale(_l.p1.y), 4, 0x007f3f00); |
88 | } | 88 | } |
89 | 89 | ||
90 | x2 = get_x_for_y(&l->p0,&l->p1,center_y); | 90 | x2 = get_x_for_y(&l->p0,&l->p1,center_y); |
91 | 91 | ||
92 | if (g_string_conf[i].playing) | 92 | if (g_string_conf[i].playing) |
93 | display_text(config_midi_note_to_string(g_string_conf[i].note+12*g_string_conf[i].octave), scale(x2-20), scale(center_y) + FONT_HEIGHT, text_color ); | 93 | display_text(config_midi_note_to_string(g_string_conf[i].note+12*g_string_conf[i].octave), scale(x2-20), scale(center_y) + FONT_HEIGHT, text_color ); |
94 | else | 94 | else |
95 | display_text(config_midi_note_to_string(g_string_conf[i].note), scale(x2-20), scale(center_y) + FONT_HEIGHT, text_color ); | 95 | display_text(config_midi_note_to_string(g_string_conf[i].note), scale(x2-20), scale(center_y) + FONT_HEIGHT, text_color ); |
96 | 96 | ||
97 | display_line_color(scale(l->p0.x), scale(l->p0.y), scale(l->p1.x), scale(l->p1.y), color); | 97 | display_line_color(scale(l->p0.x), scale(l->p0.y), scale(l->p1.x), scale(l->p1.y), color); |
98 | display_circle(scale(l->p0.x), scale(l->p0.y), 4); | 98 | display_circle(scale(l->p0.x), scale(l->p0.y), 4); |
99 | display_circle(scale(l->p1.x), scale(l->p1.y), 4); | 99 | display_circle(scale(l->p1.x), scale(l->p1.y), 4); |
100 | 100 | ||
101 | } | ||
102 | } | 101 | } |
103 | g_selected_string = -1; | 102 | } |
103 | g_selected_string = -1; | ||
104 | 104 | ||
105 | for (i = 0; i < g_render_point_count; ++i) | 105 | for (i = 0; i < g_render_point_count; ++i) |
106 | display_circle_color(scale(g_render_points[i].x), scale(g_render_points[i].y), 4, 0xff0000ff); | 106 | display_circle_color(scale(g_render_points[i].x), scale(g_render_points[i].y), 4, 0xff0000ff); |
107 | g_render_point_count = 0; | 107 | g_render_point_count = 0; |
108 | } | 108 | } |
109 | 109 | ||
110 | static void | 110 | static void |
@@ -192,119 +192,119 @@ engine_init() { | |||
192 | void | 192 | void |
193 | engine_handle_point(LPoint * p, uint32_t monotime) | 193 | engine_handle_point(LPoint * p, uint32_t monotime) |
194 | { | 194 | { |
195 | StringConfig *s;; | 195 | StringConfig *s;; |
196 | int dist_max = 1024 * 1024 * 8; | 196 | int dist_max = 1024 * 1024 * 8; |
197 | int offs, saite = -1, i, oct = 0; | 197 | int offs, saite = -1, i, oct = 0; |
198 | int y_viewfield, pitch_factor = 12; | 198 | int y_viewfield, pitch_factor = 12; |
199 | int dv, dt, speed, new_pitch; | 199 | int dv, dt, speed, new_pitch; |
200 | 200 | ||
201 | #ifndef NO_DISPLAY | 201 | #ifndef NO_DISPLAY |
202 | /* Pass to "render thread" */ | 202 | /* Pass to "render thread" */ |
203 | g_render_points[g_render_point_count] = *p; | 203 | g_render_points[g_render_point_count] = *p; |
204 | ++g_render_point_count; | 204 | ++g_render_point_count; |
205 | #endif | 205 | #endif |
206 | 206 | ||
207 | /* See which line is closest */ | 207 | /* See which line is closest */ |
208 | for (i = 0; i < g_string_count; ++i) { | 208 | for (i = 0; i < g_string_count; ++i) { |
209 | int dist = dist_pl(p, &g_string_conf[i].line, &offs); | 209 | int dist = dist_pl(p, &g_string_conf[i].line, &offs); |
210 | 210 | ||
211 | /* Avoid miss-fires, check if offset is in range -5% - +105% */ | 211 | /* Avoid miss-fires, check if offset is in range -5% - +105% */ |
212 | if ((dist < 512 * 10 * 10 ) && (dist < dist_max) && (offs<68812) && (offs>-3276)) { | 212 | if ((dist < 512 * 10 * 10 ) && (dist < dist_max) && (offs<68812) && (offs>-3276)) { |
213 | dist_max = dist; | 213 | dist_max = dist; |
214 | saite = i; | 214 | saite = i; |
215 | } | ||
216 | } | 215 | } |
216 | } | ||
217 | 217 | ||
218 | if (saite == -1) | 218 | if (saite == -1) |
219 | return; | 219 | return; |
220 | 220 | ||
221 | s = g_string_conf + saite; | 221 | s = g_string_conf + saite; |
222 | g_selected_string = saite; | 222 | g_selected_string = saite; |
223 | 223 | ||
224 | y_viewfield = (100 * (p->y - g_min_y)) / (g_max_y - g_min_y); | 224 | y_viewfield = (100 * (p->y - g_min_y)) / (g_max_y - g_min_y); |
225 | if (y_viewfield < 0) | 225 | if (y_viewfield < 0) |
226 | y_viewfield = 0; | 226 | y_viewfield = 0; |
227 | if (y_viewfield >= 100) | 227 | if (y_viewfield >= 100) |
228 | y_viewfield = 100; | 228 | y_viewfield = 100; |
229 | 229 | ||
230 | // Determine octave, if configured | 230 | // Determine octave, if configured |
231 | switch (s->mode) { | 231 | switch (s->mode) { |
232 | case midi_controller: | 232 | case midi_controller: |
233 | case midi_controller_inv: | 233 | case midi_controller_inv: |
234 | return; // not implemented | 234 | return; // not implemented |
235 | case midi_one_octave: | 235 | case midi_one_octave: |
236 | break; | 236 | break; |
237 | case midi_two_octaves: | 237 | case midi_two_octaves: |
238 | if (y_viewfield < g_midi_two_octave_split) | 238 | if (y_viewfield < g_midi_two_octave_split) |
239 | oct = -1; | 239 | oct = -1; |
240 | break; | 240 | break; |
241 | case midi_three_octaves: | 241 | case midi_three_octaves: |
242 | if (y_viewfield < g_midi_three_octave_split_1) | 242 | if (y_viewfield < g_midi_three_octave_split_1) |
243 | oct = -1; | 243 | oct = -1; |
244 | if (y_viewfield > g_midi_three_octave_split_2) | 244 | if (y_viewfield > g_midi_three_octave_split_2) |
245 | oct = 1; | 245 | oct = 1; |
246 | break; | 246 | break; |
247 | } | 247 | } |
248 | // handle inverted octave configuration | 248 | // handle inverted octave configuration |
249 | if (g_midi_three_octave_split_inverse) | 249 | if (g_midi_three_octave_split_inverse) |
250 | oct = -oct; | 250 | oct = -oct; |
251 | 251 | ||
252 | switch (s->playing) { | 252 | switch (s->playing) { |
253 | case silent: | 253 | case silent: |
254 | midi_playnote(s->channel, s->note, oct); | 254 | midi_playnote(s->channel, s->note, oct); |
255 | s->playing = in_attack; | 255 | s->playing = in_attack; |
256 | s->octave = oct; | 256 | s->octave = oct; |
257 | s->start_off = s->last_off = offs; | 257 | s->start_off = s->last_off = offs; |
258 | s->first_time_seen = monotime; | 258 | s->first_time_seen = monotime; |
259 | break; | 259 | break; |
260 | case in_attack: | 260 | case in_attack: |
261 | // test if difference is less than g_settled_dist percent of | 261 | // test if difference is less than g_settled_dist percent of |
262 | // line segment length | 262 | // line segment length |
263 | if (100 * abs(s->last_off - offs) < g_settled_dist << 16) { | 263 | if (100 * abs(s->last_off - offs) < g_settled_dist << 16) { |
264 | s->playing = playing; | 264 | s->playing = playing; |
265 | s->current_pitch = 0; | 265 | s->current_pitch = 0; |
266 | 266 | ||
267 | // estimated energy of hand is dv/dt from first seen to settled | 267 | // estimated energy of hand is dv/dt from first seen to settled |
268 | dv = abs(s->start_off - offs); | 268 | dv = abs(s->start_off - offs); |
269 | dt = monotime - s->first_time_seen; | 269 | dt = monotime - s->first_time_seen; |
270 | if (!dt) ++dt; | 270 | if (!dt) ++dt; |
271 | speed = 1000 * dv / dt; // in offs_prec per second | 271 | speed = 1000 * dv / dt; // in offs_prec per second |
272 | } | 272 | } |
273 | s->last_off = offs; | 273 | s->last_off = offs; |
274 | break; | ||
275 | case playing: | ||
276 | if (s->pitch_factor) | ||
277 | pitch_factor = s->pitch_factor; | ||
278 | if (s->modifier == pitch_bend_up) | ||
279 | new_pitch = (pitch_factor * (s->start_off - offs)) >> 16; | ||
280 | else if (s->modifier == pitch_bend_down) | ||
281 | new_pitch = (pitch_factor * (offs - s->start_off)) >> 16; | ||
282 | else | ||
274 | break; | 283 | break; |
275 | case playing: | 284 | // avoid reporting same pitch bend over and over |
276 | if (s->pitch_factor) | 285 | if (s->current_pitch == new_pitch) |
277 | pitch_factor = s->pitch_factor; | ||
278 | if (s->modifier == pitch_bend_up) | ||
279 | new_pitch = (pitch_factor * (s->start_off - offs)) >> 16; | ||
280 | else if (s->modifier == pitch_bend_down) | ||
281 | new_pitch = (pitch_factor * (offs - s->start_off)) >> 16; | ||
282 | else | ||
283 | break; | ||
284 | // avoid reporting same pitch bend over and over | ||
285 | if (s->current_pitch == new_pitch) | ||
286 | break; | ||
287 | midi_pitchbend(s->channel, new_pitch); | ||
288 | s->current_pitch = new_pitch; | ||
289 | break; | 286 | break; |
290 | } | 287 | midi_pitchbend(s->channel, new_pitch); |
291 | s->last_time_seen = monotime; | 288 | s->current_pitch = new_pitch; |
289 | break; | ||
290 | } | ||
291 | s->last_time_seen = monotime; | ||
292 | } | 292 | } |
293 | 293 | ||
294 | void | 294 | void |
295 | engine_checksilence(uint32_t monotime) | 295 | engine_checksilence(uint32_t monotime) |
296 | { | 296 | { |
297 | int i; | 297 | int i; |
298 | 298 | ||
299 | for (i = 0; i < g_string_count; ++i) { | 299 | for (i = 0; i < g_string_count; ++i) { |
300 | StringConfig *s = g_string_conf + i; | 300 | StringConfig *s = g_string_conf + i; |
301 | int tts = s->timetosilence ? s->timetosilence : g_timetosilence; | 301 | int tts = s->timetosilence ? s->timetosilence : g_timetosilence; |
302 | 302 | ||
303 | if (s->mode == midi_controller) | 303 | if (s->mode == midi_controller) |
304 | continue; | 304 | continue; |
305 | if (s->playing && (monotime - s->last_time_seen > tts)) { | 305 | if (s->playing && (monotime - s->last_time_seen > tts)) { |
306 | midi_silencenote(s->channel, s->note, s->octave); | 306 | midi_silencenote(s->channel, s->note, s->octave); |
307 | s->playing = silent; | 307 | s->playing = silent; |
308 | } | ||
309 | } | 308 | } |
309 | } | ||
310 | } | 310 | } |