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 ); |