Here you are:
Code:
desc:MIDI Octave
//tags: MIDI processing
slider1:0<-11,11,1>Transpose Semitones
slider2:-5<-11,11,1>Previous Transpose
slider3:21<0,127,1>Lowest Key (MIDI Note #)
slider4:65<0,127,1>Midi CC Transpose
slider5:66<0,127,1>Midi CC Octave
// 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
global_info = 0;
notebuf = 0; // 4 entries per open note: orignote, channel, vel, transnote
buflen = 0;
last_transpose = 0;
gmem[global_info] = last_transpose;
last_samplepos = 0;
last_oct=0;
oo=0;
att=0;
oct1=slider3;
lowc=(((oct1+13) / 12) | 0) * 12; // if lowest key is a C -> one octave up
@slider
att=0;
oct1=slider3;
lowc=(((oct1+13) / 12) | 0) * 12; // if lowest key is a C -> one octave up
@block
samplepos = play_position*srate;
samplechg = samplepos-last_samplepos;
samplechg < -samplesblock/2.0 || samplechg > samplesblock*3.0/2.0 ? (
buflen = 0; // clear state on seek
);
last_samplepos = samplepos;
slider1|0 != last_transpose || oct != last_oct ? (
last_transpose = slider1|0;
gmem[global_info] = last_transpose;
last_oct = oct;
i = 0;
loop (
buflen,
n = notebuf[4*i]|0; // original note
c = notebuf[4*i+1]|0; // channel
v = notebuf[4*i+2]|0; // velocity
t = notebuf[4*i+3]|0; // transposed note
midisend(0, $x80|c, t&0x7F); // clear the sustaining transposed note
t & 0x80 ? ( // octave had been sent
midisend(0, $x80|c, (t&0x7F)-12); // clear the sustaining octave note
);
t = (n+last_transpose)|0; // new transposed note
t < 0 ? t = 0 : t > 127 ? t = 127;
// midisend(0, $x90|c, (v*256)|t); // send the new transposed note
notebuf[4*i+3] = t; // update the buffer
oct ? (
t-=12;
// midisend(0, 0x90|c, (v*256)|t); // send the new octave note
notebuf[4*i+3] = t|0x80; // update the buffer
);
i = i+1;
);
);
while (midirecv(offs, m1, m2) ) ( // m2 contains both note and velocity
s = m1&$xF0; // Status
s != 0xF0 ? (
s == 0x90 || s == $x80 ? ( // note-on or note-off
n = m2&0xFF; // original note
v = (m2&$xFF00)/256; // velocity
no = s==0x90 && v != 0;
att && no ? ( // we are special
att = 0; // next key is normal
(n >= lowc) && (n < lowc+24) ? ( // transpose request
n -= lowc+12; // +0 ... +11
slider1 = n;
m1 = 0; // no output
);
);
m1 ? (
n >= 0 ? (
c = m1&0xF; // channel
t = (n+last_transpose)|0; // transposed note
t < 0 ? t = 0 : t > 127 ? t = 127;
m2 = m2+t-n; // apply transposition
oo && (t>12) ? (
mo = m2-12; //Sub - Octave
) : (
mo = 0;
);
i = -1;
while ( // look for this note|channel already in the buffer
i = i+1;
i < buflen && (notebuf[4*i]|0 != n || notebuf[4*i+1]|0 != c);
);
no ? (// note-on, add to buffer
notebuf[4*i] = n;
notebuf[4*i+1] = c;
notebuf[4*i+2] = v;
notebuf[4*i+3] = t | oo;
i == buflen ? buflen = buflen+1;
) : (// note-off, remove from buffer
i < buflen ? (
memcpy(notebuf+4*i, notebuf+4*(i+1), 4*(buflen-i-1)); // delete the entry
buflen = buflen-1;
);
);
);
);
):(
s == 0xB0 ? (
m2 == 0x017E ? (
oct =1;
oo = 0x80;
m1 = 0;
):(
m2 == 0x007F ? (
oct = 0;
oo = 0;
m1 = 0;
):(
(m2 & 0x7F) == slider4 ? (
(m2 >> 8 ) < 64 ? (
slider2 = last_transpose;
att = 0;
slider1 = 0;
m1 = 0;
) : (
slider1 = slider2;
last_transpose = 0;
gmem[global_info] = last_transpose;
att = 1;
m1 = 0;
);
);
);
);
);
);
m1 ? (
midisend(offs, m1, m2);
no ? (
att = 0; // next key is handled normally
);
mo && (s == 0x90 || s == $x80) ? ( // Sub-Octave
midisend(offs, m1, mo);
);
);
nb0 = notebuf[4*0]; // why does this kill the error ?!?!?!?!?
nb1 = notebuf[4*1];
);
);