title: Trivial Keyboard Monitor tags: reaper jsfx midi This is about as simple as I can do for a midi keyboard monitor. It's fixed as an 88 key piano layout. The two variables `lo` and `hi` set the bounds of the keyboard display. Potentially these could be sliders. Moreover this listens to all channels so that e.g. a noteon on channel 1 at pitch p will be ended by a note of pitch p on channel 2. This could be fixed by having a larger array of note values: one per channel but that is overkill for what I need, which is simply a display of what key I'm pressing. ``` desc: jda midi monitor @init // note range lo = 21; hi = 21+87; // look up table for colour of note notes = 100; colours = 10; colours[0] = 0; colours[1] = 1; colours[2] = 0; colours[3] = 1; colours[4] = 0; colours[5] = 0; colours[6] = 1; colours[7] = 0; colours[8] = 1; colours[9] = 0; colours[10] = 1; colours[11] = 0; function handleNoteOff() ( notes[msg2] = 0; ); function handleNoteOn() ( ( msg3 == 0 ) ? ( handleNoteOff(); ) : ( notes[msg2] = 1; ); ); // expand range if high or low notes are black ( colors[lo%12] == 1 ) ? ( lo -= 1; ); ( colors[hi%12] == 1 ) ? ( hi += 1; ); nn = hi-lo+1; // number of notes nwn = 0; // number of white notes // count white notes (used to compute width of white note) i = lo; loop(nn, ( colours[i%12] == 0 ) ? ( nwn += 1; ); i += 1; ); @block while(midirecv(offset,msg1,msg2,msg3)) ( channel = msg1 & 0xF; status = msg1 >> 4; ( status == 0x09 ) ? ( handleNoteOn(); ) : ( status == 0x08 ) ? ( handleNoteOff(); ); midisend(offset,msg1,msg2,msg3); // pass all through ); @gfx 880 100 // white background gfx_set(255,255,255); gfx_rect(0,0,gfx_w,gfx_h); // compute sizes of notes note_w = gfx_w / nwn; note_bw = note_w/1.6; note_bw2 = note_bw/2; note_h = gfx_h; note_hb = note_h * 0.6; // first pass, draw the white notes i = 0; note_r = 0; loop(nn, j = i + lo; s = notes[j]; pc = j % 12; col = colours[pc]; pos = poses[pc]; // set colour ( s == 0 ) ? ( ( j == 60 ) ? ( // middle C light yellow gfx_set(1,1,0.4); ) : ( gfx_set(1,1,1); ); ) : ( ( j == 60 ) ? ( gfx_set(1,0.25,0); ) : ( gfx_set(1,0,0); ); ); ( col == 0 ) ? ( gfx_rect(note_r,0,note_w,note_h); note_r += note_w; ); i += 1; ); // middle pass // draw the separators between the white notes note_r = 0; i = 0; loop(nn, s = notes[i]; j = i + lo; pc = j % 12; col = colours[pc]; pos = poses[pc]; // draw line between white notes ( col == 0 ) ? ( gfx_set(0,0,0); gfx_line(note_r,0,note_r,note_h); ); ( col == 0 ) ? ( //gfx_rect(note_r,0,note_w,note_h); note_r += note_w; ); i += 1; ); // third pass, draw the black notes note_r = 0; i = 0; loop(nn, j = i + lo; s = notes[j]; pc = j % 12; col = colours[pc]; pos = poses[pc]; // set colour ( s == 0 ) ? ( gfx_set(0,0,0); ) : ( gfx_set(0,0.7,0); ); ( col == 1 ) ? ( gfx_rect(note_r-note_bw2,0,note_bw,note_hb); ) : ( //gfx_rect(note_r,0,note_w,note_h); note_r += note_w; ); i += 1; ); ``` # V2 This one allows you to click on notes to send MIDI. ``` desc: jda midi key monitor 2 // idea is to allow clicks to be notes @init // note range lo = 21; hi = 21+87; // look up table for colour of note notes = 100; colours = 10; colours[0] = 0; colours[1] = 1; colours[2] = 0; colours[3] = 1; colours[4] = 0; colours[5] = 0; colours[6] = 1; colours[7] = 0; colours[8] = 1; colours[9] = 0; colours[10] = 1; colours[11] = 0; playing = 300; function allPlayingOff() ( i = 0; while(i<128) ( midisend(0,0x80,i,0); // note off on release i += 1; ); ); function handleNoteOff() ( notes[msg2] = 0; ); function handleNoteOn() ( ( msg3 == 0 ) ? ( handleNoteOff(); ) : ( notes[msg2] = 1; ); ); // expand range if high or low notes are black ( colors[lo%12] == 1 ) ? ( lo -= 1; ); ( colors[hi%12] == 1 ) ? ( hi += 1; ); nn = hi-lo+1; // number of notes nwn = 0; // number of white notes // count white notes (used to compute width of white note) i = lo; loop(nn, ( colours[i%12] == 0 ) ? ( nwn += 1; ); i += 1; ); mouse_play = -1; mouse_over = -1; mouse_down = 0; @block while(midirecv(offset,msg1,msg2,msg3)) ( channel = msg1 & 0xF; status = msg1 >> 4; ( status == 0x09 ) ? ( handleNoteOn(); ) : ( status == 0x08 ) ? ( handleNoteOff(); ); midisend(offset,msg1,msg2,msg3); // pass all through ); ( mouse_cap == 0 ) ? ( ( mouse_play >= 0 ) ? ( midisend(0,0x80,mouse_play,0); // note off on release mouse_play = -1; ); mouse_down = 0; ); ( mouse_cap == 1 ) ? ( ( mouse_down == 0 ) ? ( mouse_down = 1; ( mouse_play >= 0 ) ? ( midisend(0,0x80,mouse_play,0); // note off on release ); ( mouse_over >= 0 ) ? ( mouse_play = mouse_over; midisend(0,0x90,mouse_over,80); // note off on release ); ); ); @gfx 880 100 // white background gfx_set(255,255,255); gfx_rect(0,0,gfx_w,gfx_h); // compute sizes of notes note_w = gfx_w / nwn; note_bw = note_w/1.6; note_bw2 = note_bw/2; note_h = gfx_h; note_hb = note_h * 0.6; // first pass, draw the white notes i = 0; note_r = 0; loop(nn, j = i + lo; s = notes[j]; pc = j % 12; col = colours[pc]; pos = poses[pc]; // set colour ( s == 0 ) ? ( ( j == 60 ) ? ( // middle C light yellow gfx_set(1,1,0.4); ) : ( gfx_set(1,1,1); ); ) : ( ( j == 60 ) ? ( gfx_set(1,0.25,0); ) : ( gfx_set(1,0,0); ); ); ( col == 0 ) ? ( gfx_rect(note_r,0,note_w,note_h); ( ( mouse_x >= note_r && mouse_x <= note_r + note_w) && ( mouse_y >= 0 && mouse_y <= note_h ) ) ? ( mouse_over = j; ); note_r += note_w; ); i += 1; ); // middle pass // draw the separators between the white notes note_r = 0; i = 0; loop(nn, s = notes[i]; j = i + lo; pc = j % 12; col = colours[pc]; pos = poses[pc]; // draw line between white notes ( col == 0 ) ? ( gfx_set(0,0,0); gfx_line(note_r,0,note_r,note_h); ); ( col == 0 ) ? ( //gfx_rect(note_r,0,note_w,note_h); note_r += note_w; ); i += 1; ); // third pass, draw the black notes note_r = 0; i = 0; loop(nn, j = i + lo; s = notes[j]; pc = j % 12; col = colours[pc]; pos = poses[pc]; // set colour ( s == 0 ) ? ( gfx_set(0,0,0); ) : ( gfx_set(0,0.7,0); ); ( col == 1 ) ? ( gfx_rect(note_r-note_bw2,0,note_bw,note_hb); ( ( mouse_x >= ( note_r - note_bw2 ) && mouse_x <= ( note_r + note_bw ) ) && ( mouse_y >= 0 && mouse_y <= note_hb ) ) ? ( mouse_over = j; ); ) : ( //gfx_rect(note_r,0,note_w,note_h); note_r += note_w; ); i += 1; ); ```