desc:Extended midi note filter.

slider1:0<0,127,1{0: C0,1: C#0,2: D0,3: D#0,4: E0,5: F0,6: F#0,7: G0,8: G#0,9: A0,10: A#0,11: B0,12: C1,13: C#1,14: D1,15: D#1,16: E1,17: F1,18: F#1,19: G1,20: G#1,21: A1,22: A#1,23: B1,24: C2,25: C#2,26: D2,27: D#2,28: E2,29: F2,30: F#2,31: G2,32: G#2,33: A2,34: A#2,35: B2,36: C3,37: C#3,38: D3,39: D#3,40: E3,41: F3,42: F#3,43: G3,44: G#3,45: A3,46: A#3,47: B3,48: C4,49: C#4,50: D4,51: D#4,52: E4,53: F4,54: F#4,55: G4,56: G#4,57: A4,58: A#4,59: B4,60: C5,61: C#5,62: D5,63: D#5,64: E5,65: F5,66: F#5,67: G5,68: G#5,69: A5,70: A#5,71: B5,72: C6,73: C#6,74: D6,75: D#6,76: E6,77: F6,78: F#6,79: G6,80: G#6,81: A6,82: A#6,83: B6,84: C7,85: C#7,86: D7,87: D#7,88: E7,89: F7,90: F#7,91: G7,92: G#7,93: A7,94: A#7,95: B7,96: C8,97: C#8,98: D8,99: D#8,100: E8,101: F8,102: F#8,103: G8,104: G#8,105: A8,106: A#8,107: B8,108: C9,109: C#9,110: D9,111: D#9,112: E9,113: F9,114: F#9,115: G9,116: G#9,117: A9,118: A#9,119: B9,120: C10,121: C#10,122: D10,123: D#10,124: E10,125: F10,126: F#10,127: G10}>Key range low

slider2:127<0,127,1{0: C0,1: C#0,2: D0,3: D#0,4: E0,5: F0,6: F#0,7: G0,8: G#0,9: A0,10: A#0,11: B0,12: C1,13: C#1,14: D1,15: D#1,16: E1,17: F1,18: F#1,19: G1,20: G#1,21: A1,22: A#1,23: B1,24: C2,25: C#2,26: D2,27: D#2,28: E2,29: F2,30: F#2,31: G2,32: G#2,33: A2,34: A#2,35: B2,36: C3,37: C#3,38: D3,39: D#3,40: E3,41: F3,42: F#3,43: G3,44: G#3,45: A3,46: A#3,47: B3,48: C4,49: C#4,50: D4,51: D#4,52: E4,53: F4,54: F#4,55: G4,56: G#4,57: A4,58: A#4,59: B4,60: C5,61: C#5,62: D5,63: D#5,64: E5,65: F5,66: F#5,67: G5,68: G#5,69: A5,70: A#5,71: B5,72: C6,73: C#6,74: D6,75: D#6,76: E6,77: F6,78: F#6,79: G6,80: G#6,81: A6,82: A#6,83: B6,84: C7,85: C#7,86: D7,87: D#7,88: E7,89: F7,90: F#7,91: G7,92: G#7,93: A7,94: A#7,95: B7,96: C8,97: C#8,98: D8,99: D#8,100: E8,101: F8,102: F#8,103: G8,104: G#8,105: A8,106: A#8,107: B8,108: C9,109: C#9,110: D9,111: D#9,112: E9,113: F9,114: F#9,115: G9,116: G#9,117: A9,118: A#9,119: B9,120: C10,121: C#10,122: D10,123: D#10,124: E10,125: F10,126: F#10,127: G10}>Key range high
 
slider3:0<0,2,1{0: Play,1: Press low key...,2: Press high key...}>Mode

slider4:0<-3,3,1>Octave shift

slider5:0<-12,12,1>Semitone shift

slider6:0<0,127,1>Min velocity

slider7:127<0,127,1>Max velocity

slider8:0<0,1,1{0: Enable, 1: Disable}>Sustain pedal

// these lines tell Reaper the effect has no audio input/output,
// which enables processing optimizations.
// MIDI-only FX should always have these lines.
in_pin:none
out_pin:none


@init

ext_noinit = 1;

NOTE_OFF = 8 * 16;
NOTE_ON = 9 * 16;
CC = 11 * 16;
CC_PEDAL = 64;

MODE_PLAY = 0;
MODE_SET_LOW_KEY = 1;
MODE_SET_HIGH_KEY = 2;

SHARP = $'#' * 256;
NOTE_NAMES = 0;
NOTE_NAMES[0] = $'C';
NOTE_NAMES[1] = $'C' + SHARP;
NOTE_NAMES[2] = $'D';
NOTE_NAMES[3] = $'D' + SHARP;
NOTE_NAMES[4] = $'E';
NOTE_NAMES[5] = $'F';
NOTE_NAMES[6] = $'F' + SHARP;
NOTE_NAMES[7] = $'G';
NOTE_NAMES[8] = $'G' + SHARP;
NOTE_NAMES[9] = $'A';
NOTE_NAMES[10] = $'A' + SHARP;
NOTE_NAMES[11] = $'B';

blinkrate = 10;

@slider

keyLow = slider1;
keyHigh = slider2;
mode = slider3;
transpose = slider4 * 12 + slider5;
velLow = slider6;
velHigh = slider7;

@block

while (
  midirecv(offset, msg1, msg23) ?
  (
	doSend = 1;
    m = msg1 & 240;
    m == CC && (msg23 & 255 == CC_PEDAL) && (slider8 == 1) ?
      doSend = 0;

    m == NOTE_ON || m == NOTE_OFF ?
    (
      vel = (msg23 / 256) | 0;
      note = msg23 & 127;
      noteOut = note + transpose;
      noteOut < 0 || noteOut > 127 || (mode == MODE_PLAY && (note < keyLow || note > keyHigh)) || (m == NOTE_ON && (vel < velLow || vel > velHigh)) ?
        doSend = 0 : msg23 = vel * 256 | noteOut;

      mode == MODE_SET_HIGH_KEY && m == NOTE_ON ? (
        slider2 = keyHigh = note;
        slider3 = mode = MODE_PLAY;
        sliderchange(b110);
      );

      mode == MODE_SET_LOW_KEY && m == NOTE_ON ? (
        slider1 = keyLow = note;
        slider3 = mode = MODE_SET_HIGH_KEY;
        sliderchange(b101);
      );
    );
    doSend ? midisend(offset, msg1, msg23) : 1;
  );
);

@gfx

// Measure character width
gfx_x = 0;
gfx_y = 0;
gfx_r = gfx_g = gfx_b = 0;
gfx_drawchar($'C');
textw = gfx_x;

btnPadding = 2;
btn1Left = gfx_w - 170;
btn2Left = btn1Left + 120;
btnTop = 10;
btnWidth = 4*textw + 2*btnPadding;
btnHeight = gfx_texth + 2*btnPadding;
btnBottom = btnTop + btnHeight;
btn1Right = btn1Left + btnWidth;
btn2Right = btn2Left + btnWidth;

gfx_a = 1;
gfx_clear = 0;//$xA0A0A0;
gfx_r = 0; gfx_g = 1; gfx_b = 0;
gfx_x = btn1Left - 4*textw;
gfx_y = btnTop + btnPadding;
gfx_drawchar($'L');
gfx_drawchar($'O');
gfx_drawchar($'W');
gfx_drawchar($':');
gfx_x = btn2Left - 5*textw;
gfx_drawchar($'H');
gfx_drawchar($'I');
gfx_drawchar($'G');
gfx_drawchar($'H');
gfx_drawchar($':');

// Draw button 1
gfx_x = btn1Left;
gfx_y = btnTop;
mode == MODE_SET_LOW_KEY && blinkphase < blinkrate ?
	(gfx_r = 1; gfx_g = 0; gfx_b = 0) :
	(gfx_r = 1; gfx_g = 1; gfx_b = 1);
gfx_rectto(btn1Right, btnBottom);
mode == MODE_SET_LOW_KEY && blinkphase < blinkrate ?
	(gfx_r = 1; gfx_g = 1; gfx_b = 1) :
	(gfx_r = 0; gfx_g = 0; gfx_b = 0);
gfx_x = btn1Left + btnPadding;
gfx_y = btnTop + btnPadding;
n = NOTE_NAMES[keyLow % 12];
gfx_drawchar(n & $xFF);
n > 256 ? gfx_drawchar(n / 256);
gfx_drawnumber((keyLow / 12) | 0, 0);
mode == MODE_SET_LOW_KEY ? (
	(blinkphase += 1) >= blinkrate * 2 ? blinkphase = 0;
);

// Draw button 2
mode == MODE_SET_HIGH_KEY && blinkphase < blinkrate ?
	(gfx_r = 1; gfx_g = 0; gfx_b = 0) :
	(gfx_r = 1; gfx_g = 1; gfx_b = 1);
gfx_x = btn2Left;
gfx_y = btnTop;
gfx_rectto(btn2Right, btnBottom);
mode == MODE_SET_HIGH_KEY && blinkphase < blinkrate ?
	(gfx_r = 1; gfx_g = 1; gfx_b = 1) :
	(gfx_r = 0; gfx_g = 0; gfx_b = 0);
gfx_x = btn2Left + btnPadding;
gfx_y = btnTop + btnPadding;
n = NOTE_NAMES[keyHigh % 12];
gfx_drawchar(n & $xFF);
n > 256 ? gfx_drawchar(n / 256);
gfx_drawnumber((keyHigh / 12) | 0, 0);
mode == MODE_SET_HIGH_KEY ? (
	(blinkphase += 1) >= blinkrate * 2 ? blinkphase = 0;
);
	
// Handle mouse
(mouse_cap & 1) && !mouseClick ? (
	newMode = MODE_PLAY;
	mouse_x >= btn1Left && mouse_x <= btn1Right &&
	mouse_y >= btnTop && mouse_y <= btnBottom ? (
		newMode = MODE_SET_LOW_KEY;
	) :
	mouse_x >= btn2Left && mouse_x <= btn2Right &&
	mouse_y >= btnTop && mouse_y <= btnBottom ? (
		newMode = MODE_SET_HIGH_KEY;
	);
	newMode == mode ? newMode = MODE_PLAY;
	newMode != mode ? (
		blinkphase = 0;
		slider3 = mode = newMode;
		sliderchange(slider3);
	);
);
mouseClick = mouse_cap & 1;

