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 | } |
