diff options
Diffstat (limited to 'engine.c')
-rw-r--r-- | engine.c | 172 |
1 files changed, 104 insertions, 68 deletions
@@ -2,6 +2,7 @@ | |||
2 | #include <stdlib.h> | 2 | #include <stdlib.h> |
3 | 3 | ||
4 | #include "config.h" | 4 | #include "config.h" |
5 | #include "geometry.h" | ||
5 | #include "engine.h" | 6 | #include "engine.h" |
6 | #include "main.h" | 7 | #include "main.h" |
7 | #include "midi.h" | 8 | #include "midi.h" |
@@ -13,91 +14,131 @@ static int g_selected_string = -1; | |||
13 | 14 | ||
14 | static LPoint g_render_points[1024]; | 15 | static LPoint g_render_points[1024]; |
15 | static int g_render_point_count; | 16 | static int g_render_point_count; |
16 | static const int g_harfe_width = 1024; | 17 | static ConfigSelect g_selected_config; |
17 | static const int g_harfe_height = 768; | 18 | static void highlight_line(int value, int y, int max_x, uint32_t color); |
18 | static int g_factor = 1<<16; | ||
19 | 19 | ||
20 | static inline int scale(int coord) { | 20 | #define scale(X) display_scale_harfe_to_screen(X) |
21 | return (int)(((((int64_t)coord) << 32) / g_factor ) >> 16); | ||
22 | } | ||
23 | 21 | ||
24 | void | 22 | void |
25 | engine_redraw() | 23 | engine_redraw() |
26 | { | 24 | { |
27 | int i; | 25 | char text[32]; |
26 | char *config_hints[] = { "No", "Harfe", "File", "Edit" }; | ||
27 | int i, MAX_X, MAX_Y, FONT_HEIGHT; | ||
28 | int height = g_max_y - g_min_y; | ||
28 | 29 | ||
29 | display_redraw(); | 30 | display_redraw(); |
30 | display_clear(); | 31 | display_clear(); |
31 | display_text(g_harfe_connected ? "online" : "offline", 4, 4, 0xffffffff); | 32 | display_getdimensions(&MAX_X, &MAX_Y, &FONT_HEIGHT); |
32 | 33 | ||
33 | for (i = 0; i < g_string_count; ++i) { | 34 | snprintf( text, sizeof(text), g_harfe_connected ? "online (%s)" : "offline (%s)", config_hints[(int)g_config_source]); |
34 | LLine *l = &g_string_conf[i].line; | 35 | display_text(text, 8, MAX_Y - 4, g_harfe_connected ? 0x00ff3fff : 0xff003fff ); |
35 | uint32_t color = i == g_selected_string ? 0xff00ffff : 0x00ffffffff; | ||
36 | 36 | ||
37 | display_line_color(scale(l->x0), scale(l->y0), scale(l->x1), scale(l->y1), color); | 37 | if (height) { |
38 | display_circle(scale(l->x0), scale(l->y0), 4); | 38 | int b = g_midi_three_octave_split_inverse; |
39 | display_circle(scale(l->x1), scale(l->y1), 4); | 39 | int tos1 = g_midi_three_octave_split_1, tos2 = g_midi_three_octave_split_2; |
40 | display_text( b ? "+1" : "-1", 4, scale(g_min_y + tos1 * height / 200) + FONT_HEIGHT / 2, 0x007f7f7fff); | ||
41 | display_text( " 0", 4, scale(g_min_y + (tos1 + tos2) * height / 200) + FONT_HEIGHT / 2, 0x007f7f7fff); | ||
42 | display_text( b ? "-1" : "+1", 4, scale(g_min_y + (tos2 / 2 + 50 ) * height / 100) + FONT_HEIGHT / 2, 0x007f7f7fff); | ||
40 | 43 | ||
41 | if (g_string_conf[i].playing) | 44 | display_line_color(0, scale(g_min_y), MAX_X, scale(g_min_y), 0xff00ffff); |
42 | display_text(config_midi_note_to_string(g_string_conf[i].note+12*g_string_conf[i].octave), scale(l->x1) - 20, g_height - 40, color ); | 45 | display_line_color(0, scale(g_max_y), MAX_X, scale(g_max_y), 0xff00ffff); |
43 | else | 46 | |
44 | display_text(config_midi_note_to_string(g_string_conf[i].note), scale(l->x1) - 20, g_height - 40, color ); | 47 | 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); |
48 | |||
49 | display_line_color(0, scale(g_min_y + tos1 * height / 100), MAX_X, scale(g_min_y + tos1 * height / 100), 0x00ff00ff); | ||
50 | display_line_color(0, scale(g_min_y + tos2 * height / 100), MAX_X, scale(g_min_y + tos2 * height / 100), 0x00ff00ff); | ||
51 | |||
52 | |||
53 | switch (g_selected_config) { | ||
54 | case sel_min_y: highlight_line(g_min_y, g_min_y, MAX_X, 0xff00ffff); break; | ||
55 | case sel_max_y: highlight_line(g_max_y, g_max_y, MAX_X, 0xff00ffff); break; | ||
56 | 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; | ||
57 | case sel_3_oct_top: highlight_line(tos2, g_min_y + tos2 * height / 100, MAX_X, 0x00ff00ff); break; | ||
58 | case sel_3_oct_bottom: highlight_line(tos1, g_min_y + tos1 * height / 100, MAX_X, 0x00ff00ff); break; | ||
59 | case sel_none: break; | ||
60 | } | ||
61 | |||
62 | for (i = 0; i < g_string_count; ++i) { | ||
63 | LLine *l = &g_string_conf[i].line; | ||
64 | uint32_t color = ( ( i == g_selected_string ) ? 0xff00ffff : 0x00ffffffff ); | ||
65 | uint32_t text_color = ( ( i == g_selected_string ) ? 0xff00ffff : 0x007f7f7fff ); | ||
66 | |||
67 | int center_y = g_min_y+height/2; | ||
68 | int x2 = l->p1.x; | ||
69 | |||
70 | if (l->p1.x!=l->p0.x) { | ||
71 | double m = (double)(l->p1.y-l->p0.y) / (double)(l->p1.x-l->p0.x); | ||
72 | double _x2 = ((double)center_y) - (double)l->p0.y + m * (double)l->p0.x; | ||
73 | x2 = (int)(_x2/m); | ||
74 | } | ||
75 | |||
76 | if (g_string_conf[i].playing) | ||
77 | 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 ); | ||
78 | else | ||
79 | display_text(config_midi_note_to_string(g_string_conf[i].note), scale(x2-20), scale(center_y) + FONT_HEIGHT, text_color ); | ||
80 | |||
81 | display_line_color(scale(l->p0.x), scale(l->p0.y), scale(l->p1.x), scale(l->p1.y), color); | ||
82 | display_circle(scale(l->p0.x), scale(l->p0.y), 4); | ||
83 | display_circle(scale(l->p1.x), scale(l->p1.y), 4); | ||
84 | |||
85 | } | ||
45 | } | 86 | } |
46 | g_selected_string = -1; | 87 | g_selected_string = -1; |
47 | 88 | ||
48 | for (i = 0; i < g_render_point_count; ++i) | 89 | for (i = 0; i < g_render_point_count; ++i) |
49 | display_circle_color(scale(g_render_points[i].x), scale(g_render_points[i].y), 4, 0xff0000ff); | 90 | display_circle_color(scale(g_render_points[i].x), scale(g_render_points[i].y), 4, 0xff0000ff); |
50 | g_render_point_count = 0; | 91 | g_render_point_count = 0; |
92 | } | ||
51 | 93 | ||
52 | display_line_color(0, scale(g_min_y), g_width, scale(g_min_y), 0xff00ffff); | 94 | static void |
53 | display_line_color(0, scale(g_max_y), g_width, scale(g_max_y), 0xff00ffff); | 95 | highlight_line(int value, int y, int max_x, uint32_t color) { |
54 | 96 | char text[32]; | |
55 | if (g_min_y != g_max_y) { | 97 | display_line_color(0, scale(y-10), 10, scale(y), color); |
56 | int height = scale(g_max_y - g_min_y); | 98 | display_line_color(0, scale(y+10), 10, scale(y), color); |
57 | 99 | display_line_color(max_x, scale(y-10), max_x-10, scale(y), color); | |
58 | display_line_color(0, scale(g_max_y) - g_midi_two_octave_split * height / 256, g_width, scale(g_max_y) - g_midi_two_octave_split * height / 256, 0xffff00ff); | 100 | display_line_color(max_x, scale(y+10), max_x-10, scale(y), color); |
59 | 101 | ||
60 | display_line_color(0, scale(g_max_y) - g_midi_three_octave_split_1 * height / 256, g_width, scale(g_max_y) - g_midi_three_octave_split_1 * height / 256, 0x00ff00ff); | 102 | display_rect_color(max_x/2-40, scale(y+20), 80, 40, 0xffffffff); |
61 | display_line_color(0, scale(g_max_y) - g_midi_three_octave_split_2 * height / 256, g_width, scale(g_max_y) - g_midi_three_octave_split_2 * height / 256, 0x00ff00ff); | 103 | display_text(text, max_x/2-20, scale(y+20), 0); |
62 | } | ||
63 | } | 104 | } |
64 | 105 | ||
65 | #endif | ||
66 | |||
67 | void | 106 | void |
68 | engine_init() { | 107 | engine_select_config(ConfigSelect sel) { |
69 | #ifndef NO_DISPLAY | 108 | g_selected_config = sel; |
70 | g_factor = (g_harfe_width << 16) / g_width; | ||
71 | if ((g_harfe_height << 16) / g_height < g_factor) | ||
72 | g_factor = (g_harfe_height << 16) / g_height; | ||
73 | #endif | ||
74 | } | 109 | } |
75 | 110 | ||
76 | static int | 111 | ConfigSelect |
77 | dist_pp(int x0, int y0, int x1, int y1) | 112 | engine_change_selected(int off) |
78 | { | 113 | { |
79 | return (y0 - y1) * (y0 - y1) + (x0 - x1) * (x0 - x1); | 114 | switch(g_selected_config) { |
115 | case sel_3_oct_top: | ||
116 | g_midi_three_octave_split_2 += off; | ||
117 | if (g_midi_three_octave_split_2<0) g_midi_three_octave_split_2 = 0; | ||
118 | if (g_midi_three_octave_split_2>100) g_midi_three_octave_split_2 = 100; | ||
119 | break; | ||
120 | case sel_3_oct_bottom: | ||
121 | g_midi_three_octave_split_1 += off; | ||
122 | if (g_midi_three_octave_split_1<0) g_midi_three_octave_split_1 = 0; | ||
123 | if (g_midi_three_octave_split_1>100) g_midi_three_octave_split_1 = 100; | ||
124 | break; | ||
125 | case sel_2_oct: | ||
126 | g_midi_two_octave_split += off; | ||
127 | if (g_midi_two_octave_split<0) g_midi_two_octave_split = 0; | ||
128 | if (g_midi_two_octave_split>100) g_midi_two_octave_split = 100; | ||
129 | break; | ||
130 | default: | ||
131 | break; | ||
132 | } | ||
133 | return g_selected_config; | ||
80 | } | 134 | } |
81 | 135 | ||
82 | // dist is a fixed point with precission of 8 bits | 136 | #endif |
83 | // offs is where on the line segment xy0-xy1 the point's normale hits, | ||
84 | // range 0..65536 (but can extend, if normale hits line outside line segment) | ||
85 | static int | ||
86 | dist_lp(int x0, int y0, int x1, int y1, int xp, int yp, int *offs) | ||
87 | { | ||
88 | int64_t r = (y1 - y0) * (y1 - y0) + (x1 - x0) * (x1 - x0); | ||
89 | int64_t q1 = (xp - x0) * (y1 - y0) - (yp - y0) * (x1 - x0); | ||
90 | int64_t q2 = (x1 - x0) * (xp - x0) + (y1 - y0) * (yp - y0); | ||
91 | 137 | ||
92 | *offs = (int)((q2 << 16) / r); | 138 | void |
93 | return (int)( q1 * q1 * ((y0 - y1) * (y0 - y1) + (x1 - x0) * (x1 - x0)) * 256 / (r * r)); | 139 | engine_init() { |
94 | } | 140 | } |
95 | 141 | ||
96 | static int | ||
97 | dist_pl(LPoint * p, LLine * l, int *offs) | ||
98 | { | ||
99 | return dist_lp(l->x0, l->y0, l->x1, l->y1, p->x, p->y, offs); | ||
100 | } | ||
101 | 142 | ||
102 | void | 143 | void |
103 | engine_handle_point(LPoint * p, uint32_t monotime) | 144 | engine_handle_point(LPoint * p, uint32_t monotime) |
@@ -108,9 +149,6 @@ engine_handle_point(LPoint * p, uint32_t monotime) | |||
108 | int y_viewfield, pitch_factor = 12; | 149 | int y_viewfield, pitch_factor = 12; |
109 | int dv, dt, speed, new_pitch; | 150 | int dv, dt, speed, new_pitch; |
110 | 151 | ||
111 | // XXX should not be inverted here | ||
112 | p->x = 1024 - p->x; | ||
113 | |||
114 | #ifndef NO_DISPLAY | 152 | #ifndef NO_DISPLAY |
115 | /* Pass to "render thread" */ | 153 | /* Pass to "render thread" */ |
116 | g_render_points[g_render_point_count] = *p; | 154 | g_render_points[g_render_point_count] = *p; |
@@ -120,27 +158,25 @@ engine_handle_point(LPoint * p, uint32_t monotime) | |||
120 | /* See which line is closest */ | 158 | /* See which line is closest */ |
121 | for (i = 0; i < g_string_count; ++i) { | 159 | for (i = 0; i < g_string_count; ++i) { |
122 | int dist = dist_pl(p, &g_string_conf[i].line, &offs); | 160 | int dist = dist_pl(p, &g_string_conf[i].line, &offs); |
123 | if ((dist < 256 * 10 * 10 ) && (dist < dist_max)) { | 161 | |
162 | /* Avoid miss-fires, check if offset is in range -5% - +105% */ | ||
163 | if ((dist < 512 * 10 * 10 ) && (dist < dist_max) && (offs<68812) && (offs>-3276)) { | ||
124 | dist_max = dist; | 164 | dist_max = dist; |
125 | saite = i; | 165 | saite = i; |
126 | } | 166 | } |
127 | } | 167 | } |
128 | 168 | ||
129 | /* Avoid miss-fires, check if offset is in range -5% - +105% */ | ||
130 | if (offs>68812 || offs<-3276) | ||
131 | return; | ||
132 | |||
133 | if (saite == -1) | 169 | if (saite == -1) |
134 | return; | 170 | return; |
135 | 171 | ||
136 | s = g_string_conf + saite; | 172 | s = g_string_conf + saite; |
137 | g_selected_string = saite; | 173 | g_selected_string = saite; |
138 | 174 | ||
139 | y_viewfield = 256 * (g_max_y - p->y) / (g_max_y - g_min_y); | 175 | y_viewfield = (100 * (p->y - g_min_y)) / (g_max_y - g_min_y); |
140 | if (y_viewfield < 0) | 176 | if (y_viewfield < 0) |
141 | y_viewfield = 0; | 177 | y_viewfield = 0; |
142 | if (y_viewfield >= 256) | 178 | if (y_viewfield >= 100) |
143 | y_viewfield = 255; | 179 | y_viewfield = 100; |
144 | 180 | ||
145 | // Determine octave, if configured | 181 | // Determine octave, if configured |
146 | switch (s->mode) { | 182 | switch (s->mode) { |
@@ -183,7 +219,7 @@ engine_handle_point(LPoint * p, uint32_t monotime) | |||
183 | dv = abs(s->start_off - offs); | 219 | dv = abs(s->start_off - offs); |
184 | dt = monotime - s->first_time_seen; | 220 | dt = monotime - s->first_time_seen; |
185 | if (!dt) ++dt; | 221 | if (!dt) ++dt; |
186 | speed = 1000 * dv / dt; // in offs_prec per second | 222 | speed = 1000 * dv / dt; // in offs_prec per second |
187 | } | 223 | } |
188 | s->last_off = offs; | 224 | s->last_off = offs; |
189 | break; | 225 | break; |
@@ -193,7 +229,7 @@ engine_handle_point(LPoint * p, uint32_t monotime) | |||
193 | if (s->modifier == pitch_bend_up) | 229 | if (s->modifier == pitch_bend_up) |
194 | new_pitch = (pitch_factor * (s->start_off - offs)) >> 16; | 230 | new_pitch = (pitch_factor * (s->start_off - offs)) >> 16; |
195 | else if (s->modifier == pitch_bend_down) | 231 | else if (s->modifier == pitch_bend_down) |
196 | new_pitch = (pitch_factor * (s->start_off - offs)) >> 16; | 232 | new_pitch = (pitch_factor * (offs - s->start_off)) >> 16; |
197 | else | 233 | else |
198 | break; | 234 | break; |
199 | // avoid reporting same pitch bend over and over | 235 | // avoid reporting same pitch bend over and over |