diff options
| -rw-r--r-- | arduino/Laserharfe/Laserharfe.ino | 4 | ||||
| -rw-r--r-- | engine.c | 57 | ||||
| -rw-r--r-- | midi-sdl.c | 4 | ||||
| -rw-r--r-- | midi.h | 2 |
4 files changed, 50 insertions, 17 deletions
diff --git a/arduino/Laserharfe/Laserharfe.ino b/arduino/Laserharfe/Laserharfe.ino index 1d7adeb..b219951 100644 --- a/arduino/Laserharfe/Laserharfe.ino +++ b/arduino/Laserharfe/Laserharfe.ino | |||
| @@ -262,9 +262,9 @@ void handle_midi(char *command) { | |||
| 262 | Serial.println("- MIDI SENT"); | 262 | Serial.println("- MIDI SENT"); |
| 263 | } | 263 | } |
| 264 | 264 | ||
| 265 | void midi_playnote(int channel, int note, int octave_offset ) { | 265 | void midi_playnote(int channel, int note, int octave_offset, int velocity ) { |
| 266 | midi_pitchbend(channel, 0); | 266 | midi_pitchbend(channel, 0); |
| 267 | midiEventPacket_t p = { 0x9, 0x90 | channel, note + 12 * octave_offset, 0x7f }; | 267 | midiEventPacket_t p = { 0x9, 0x90 | channel, note + 12 * octave_offset, velocity }; |
| 268 | MidiUSB.sendMIDI(p); | 268 | MidiUSB.sendMIDI(p); |
| 269 | } | 269 | } |
| 270 | 270 | ||
| @@ -195,7 +195,7 @@ engine_handle_point(LPoint * p, uint32_t monotime) | |||
| 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 = 256*128; |
| 199 | int dv, dt, speed, new_pitch; | 199 | int dv, dt, speed, new_pitch; |
| 200 | 200 | ||
| 201 | #ifndef NO_DISPLAY | 201 | #ifndef NO_DISPLAY |
| @@ -250,29 +250,42 @@ engine_handle_point(LPoint * p, uint32_t monotime) | |||
| 250 | oct = -oct; | 250 | oct = -oct; |
| 251 | 251 | ||
| 252 | switch (s->playing) { | 252 | switch (s->playing) { |
| 253 | case silent: | 253 | case string_is_silent: |
| 254 | midi_playnote(s->channel, s->note, oct); | 254 | s->playing = string_is_in_attack; |
| 255 | s->playing = in_attack; | ||
| 256 | s->octave = oct; | 255 | s->octave = oct; |
| 257 | s->start_off = s->last_off = offs; | 256 | s->start_off = s->last_off = offs; |
| 258 | s->first_time_seen = monotime; | 257 | s->first_time_seen = monotime; |
| 259 | break; | 258 | break; |
| 260 | case in_attack: | 259 | case string_is_in_attack: |
| 261 | // test if difference is less than g_settled_dist percent of | 260 | // test if difference is less than g_settled_dist percent of |
| 262 | // line segment length | 261 | // line segment length |
| 263 | if (100 * abs(s->last_off - offs) < g_settled_dist << 16) { | 262 | dt = monotime - s->first_time_seen; |
| 264 | s->playing = playing; | 263 | if (dt > 10 && abs(s->last_off - offs) < g_settled_dist) { |
| 265 | s->current_pitch = 0; | 264 | s->playing = string_is_playing; |
| 266 | 265 | ||
| 267 | // estimated energy of hand is dv/dt from first seen to settled | 266 | // estimated energy of hand is dv/dt from first seen to settled |
| 268 | dv = abs(s->start_off - offs); | 267 | dv = abs(s->start_off - offs); |
| 269 | dt = monotime - s->first_time_seen; | ||
| 270 | if (!dt) ++dt; | 268 | if (!dt) ++dt; |
| 271 | speed = 1000 * dv / dt; // in offs_prec per second | 269 | speed = 1000 * dv / dt; // in offs_prec per second |
| 270 | // printf("SPEED: %d (%d) for dt %d\n", speed, 64 + speed / 4000, dt); | ||
| 271 | speed = 64 + speed / 4000; | ||
| 272 | if (speed > 127) speed = 127; | ||
| 273 | midi_playnote(s->channel, s->note, s->octave, speed); | ||
| 274 | |||
| 275 | /* XXX TODO report speed as midi command */ | ||
| 276 | s->start_off = offs; | ||
| 272 | } | 277 | } |
| 278 | s->octave = oct; | ||
| 273 | s->last_off = offs; | 279 | s->last_off = offs; |
| 274 | break; | 280 | break; |
| 275 | case playing: | 281 | case string_is_playing: |
| 282 | if (monotime - s->first_time_seen < g_pitchbend_delay) | ||
| 283 | break; | ||
| 284 | s->start_off = offs; | ||
| 285 | s->current_pitch = 0; | ||
| 286 | s->playing = string_is_bending; | ||
| 287 | break; | ||
| 288 | case string_is_bending: | ||
| 276 | if (s->pitch_factor) | 289 | if (s->pitch_factor) |
| 277 | pitch_factor = s->pitch_factor; | 290 | pitch_factor = s->pitch_factor; |
| 278 | if (s->modifier == pitch_bend_up) | 291 | if (s->modifier == pitch_bend_up) |
| @@ -302,9 +315,29 @@ engine_checksilence(uint32_t monotime) | |||
| 302 | 315 | ||
| 303 | if (s->mode == midi_controller) | 316 | if (s->mode == midi_controller) |
| 304 | continue; | 317 | continue; |
| 318 | |||
| 319 | // Play notes in attack that are not visible anymore | ||
| 320 | if (s->playing == string_is_in_attack && (monotime - s->last_time_seen) > 5) { | ||
| 321 | int speed, dv, dt = monotime - s->first_time_seen; | ||
| 322 | if (!dt) ++dt; | ||
| 323 | s->playing = string_is_playing; | ||
| 324 | s->current_pitch = 0; | ||
| 325 | |||
| 326 | // estimated energy of hand is dv/dt from first seen to settled | ||
| 327 | dv = abs(s->start_off - s->last_off); | ||
| 328 | speed = 1000 * dv / dt; // in offs_prec per second | ||
| 329 | // printf("SPEED: %d (%d) for dt %d\n", speed, 64 + speed / 4000, dt); | ||
| 330 | speed = 64 + speed / 4000; | ||
| 331 | if (speed > 127) speed = 127; | ||
| 332 | midi_playnote(s->channel, s->note, s->octave, speed); | ||
| 333 | |||
| 334 | s->start_off = s->last_off; | ||
| 335 | } | ||
| 336 | |||
| 305 | if (s->playing && (monotime - s->last_time_seen > tts)) { | 337 | if (s->playing && (monotime - s->last_time_seen > tts)) { |
| 306 | midi_silencenote(s->channel, s->note, s->octave); | 338 | if (s->playing >= string_is_playing) |
| 307 | s->playing = silent; | 339 | midi_silencenote(s->channel, s->note, s->octave); |
| 340 | s->playing = string_is_silent; | ||
| 308 | } | 341 | } |
| 309 | } | 342 | } |
| 310 | } | 343 | } |
| @@ -9,9 +9,9 @@ int midi_init() { | |||
| 9 | return 0; | 9 | return 0; |
| 10 | } | 10 | } |
| 11 | 11 | ||
| 12 | void midi_playnote( int channel, int note, int octave_offset ) { | 12 | void midi_playnote( int channel, int note, int octave_offset, int velocity ) { |
| 13 | char out[32]; | 13 | char out[32]; |
| 14 | int b = sprintf(out,"M%02X0020\nM%02X%02X%02X\n", 0xe0 | channel, 0x90 | channel, note + 12 * octave_offset, 0x7f); | 14 | int b = sprintf(out,"M%02X0020\nM%02X%02X%02X\n", 0xe0 | channel, 0x90 | channel, note + 12 * octave_offset, velocity&127); |
| 15 | if (g_harfe_connected && (g_harfe_fd != -1)) | 15 | if (g_harfe_connected && (g_harfe_fd != -1)) |
| 16 | write(g_harfe_fd, out, b); | 16 | write(g_harfe_fd, out, b); |
| 17 | } | 17 | } |
| @@ -2,7 +2,7 @@ | |||
| 2 | 2 | ||
| 3 | int midi_init(); | 3 | int midi_init(); |
| 4 | 4 | ||
| 5 | void midi_playnote( int channel, int note, int octave_offset ); | 5 | void midi_playnote( int channel, int note, int octave_offset, int velocity ); |
| 6 | void midi_silencenote( int channel, int note, int octave_offset ); | 6 | void midi_silencenote( int channel, int note, int octave_offset ); |
| 7 | void midi_pitchbend( int channel, int pitch ); | 7 | void midi_pitchbend( int channel, int pitch ); |
| 8 | //void midi_controller_event( int saite, int value ); | 8 | //void midi_controller_event( int saite, int value ); |
