home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World 2008 February
/
PCWorld_2008-02_cd.bin
/
audio-video
/
reaper
/
reaper2028-install.exe
/
Effects
/
schwa
/
midi_humanizer
< prev
next >
Wrap
Text File
|
2007-12-03
|
4KB
|
128 lines
desc:midi velocity and timing humanizer
slider1:0<0,127,1>baseline velocity (0: use original) (automate!)
slider2:0<0,1,1{no (subtle timing humanization/bias only),yes (you must shift original midi 1 beat early)}>add 1 beat delay
slider3:0<-10,10>bias timing humanization early or late, msec
slider4:0<0,10>timing humanization level
slider5:0<0,10>velocity humanization level
slider6:0<-30,30>output timing humanization, msec (read-only)
slider7:0<-64,64,1>output velocity humanization (read-only)
@init
// We are "humanizing" not "crapifying."
MAX_VEL_SHIFT = 0.25; // Fraction of baseline velocity.
MAX_MSEC_SHIFT = 15; // Only applies if orig is shifted.
MAX_IS_X_STDEV = 1.5; // Max shift represents this many std dev.
DEV_N = 12;
buffer = 0;
MSG_BUF = 128; // msg buffer start location.
memset(0, 0, MSG_BUF);
n_buf = 0;
NOTE_ON = 9;
NOTE_OFF = 8;
AFTERTCH = 10;
@block
while (
midirecv(mpos, msg1, msg23) ? (
bias_samples = srate * slider3 / 1000;
(slider2 == 0) ? (
baseline_pos_shift = 0;
min_pos = 0;
max_pos = samplesblock - 1;
) : (
samples_per_beat = srate * 60 / tempo;
baseline_pos_shift = samples_per_beat;
min_pos = baseline_pos_shift - MAX_MSEC_SHIFT / 1000 * srate;
max_pos = baseline_pos_shift + MAX_MSEC_SHIFT / 1000 * srate;
);
msg = (msg1 & 240 ) / 16;
note_num = msg23 & 127;
msgvel = (msg23 / 256) | 0;
(msg == NOTE_ON && msgvel > 0) ? (
// Generate two quick & dirty normal deviates.
z1 = 0;
z2 = 0;
loop (DEV_N,
z1 += rand(100) / 100;
z2 += rand(100) / 100;
);
z1 -= DEV_N / 2;
z2 -= DEV_N / 2;
pos_shift = z1 * slider4 / 10;
pos_shift *= (max_pos - min_pos) / MAX_IS_X_STDEV;
new_pos = mpos + bias_samples + baseline_pos_shift + pos_shift;
new_pos = max(min_pos, new_pos);
new_pos = min(new_pos, max_pos);
pos_shift = new_pos - mpos;
buffer[note_num] = pos_shift;
mpos = new_pos;
(slider1 == 0) ? (
velocity = msgvel;
) : (
velocity = slider1;
);
min_vel = (1 - MAX_VEL_SHIFT) * velocity;
max_vel = (1 + MAX_VEL_SHIFT) * velocity;
vel_shift = z2 * slider5 / 10;
vel_shift *= (max_vel - min_vel) / MAX_IS_X_STDEV;
vel_shift = floor(vel_shift + 0.5);
velocity += vel_shift;
velocity = max(0, velocity);
velocity = min(velocity, 127);
velocity |= 0;
msg23 = note_num + velocity * 256;
msec_shift = (pos_shift - baseline_pos_shift) * 1000 / srate;
slider6 = floor(msec_shift * 10) / 10;
slider7 = vel_shift;
sliderchange(2^6 + 2^7);
);
(msg == AFTERTCH) ? (
mpos += buffer[note_num];
);
(msg == NOTE_OFF || (msg==NOTE_ON && msgvel<1)) ? (
mpos += buffer[note_num];
buffer[note_num] = 0;
);
buffer[MSG_BUF+n_buf] = mpos;
buffer[MSG_BUF+n_buf+1] = msg1;
buffer[MSG_BUF+n_buf+2] = msg23;
n_buf += 3;
);
);
// Find everything in the buffer that is due
// to be played back in this block.
i = 0;
while (
(i < n_buf) ? (
mpos = buffer[MSG_BUF + i];
(mpos < samplesblock) ? (
midisend(mpos, buffer[MSG_BUF+i+1], buffer[MSG_BUF+i+2]);
memcpy(MSG_BUF+i, MSG_BUF+i+3, n_buf-i);
n_buf -= 3;
) : (
buffer[MSG_BUF+i] -= samplesblock;
i += 3;
);
);
);