home *** CD-ROM | disk | FTP | other *** search
/ PC World 2007 July & August / PCWorld_2007-07-08_cd.bin / audio-video / reaper / reaper1861-install.exe / Effects / schwa / midi_humanizer
Text File  |  2007-03-22  |  4KB  |  127 lines

  1. desc:midi velocity and timing humanizer
  2.  
  3. slider1:0<0,127,1>baseline velocity (0: use original) (automate!)
  4. slider2:0<0,1,1{no (subtle timing humanization/bias only),yes (you must shift original midi 1 beat early)}>add 1 beat delay
  5. slider3:0<-10,10>bias timing humanization early or late, msec
  6. slider4:0<0,10>timing humanization level
  7. slider5:0<0,10>velocity humanization level
  8. slider6:0<-30,30>output timing humanization, msec (read-only)
  9. slider7:0<-64,64,1>output velocity humanization (read-only)
  10.  
  11. @init
  12.  
  13.   // We are "humanizing" not "crapifying."
  14.   MAX_VEL_SHIFT = 0.25;  // Fraction of baseline velocity.
  15.   MAX_MSEC_SHIFT = 15; // Only applies if orig is shifted.
  16.   MAX_IS_X_STDEV = 1.5;  // Max shift represents this many std dev.
  17.   
  18.   DEV_N = 12;
  19.   buffer = 0;
  20.   MSG_BUF = 128;  // msg buffer start location.
  21.   memset(0, 0, MSG_BUF);
  22.   n_buf = 0;
  23.  
  24.   NOTE_ON = 9;
  25.   NOTE_OFF = 8;
  26.   AFTERTCH = 10;
  27.  
  28. @block
  29.  
  30.   while (
  31.     midirecv(mpos, msg1, msg23) ? (
  32.  
  33.       bias_samples = srate * slider3 / 1000;
  34.  
  35.       (slider2 == 0) ? (
  36.         baseline_pos_shift = 0;
  37.         min_pos = 0;
  38.     max_pos = samplesblock - 1;
  39.       ) : (
  40.         samples_per_beat = srate * 60 / tempo;
  41.         baseline_pos_shift = samples_per_beat;
  42.     min_pos = baseline_pos_shift - MAX_MSEC_SHIFT / 1000 * srate;
  43.      max_pos = baseline_pos_shift + MAX_MSEC_SHIFT / 1000 * srate;
  44.       );     
  45.  
  46.       msg = (msg1 & 240 ) / 16;
  47.       note_num = msg23 & 127;
  48.  
  49.       (msg == NOTE_ON) ? (
  50.  
  51.         // Generate two quick & dirty normal deviates.
  52.         z1 = 0;
  53.         z2 = 0;
  54.         loop (DEV_N, 
  55.           z1 += rand(100) / 100;
  56.           z2 += rand(100) / 100;
  57.         );
  58.         z1 -= DEV_N / 2;
  59.         z2 -= DEV_N / 2;
  60.  
  61.     pos_shift = z1 * slider4 / 10;
  62.     pos_shift *= (max_pos - min_pos) / MAX_IS_X_STDEV;
  63.     
  64.     new_pos = mpos + bias_samples + baseline_pos_shift + pos_shift;
  65.     new_pos = max(min_pos, new_pos);
  66.     new_pos = min(new_pos, max_pos);
  67.  
  68.     pos_shift = new_pos - mpos;
  69.     buffer[note_num] = pos_shift;
  70.     mpos = new_pos;
  71.  
  72.         (slider1 == 0) ? (
  73.           velocity = (msg23 / 256) | 0;
  74.         ) : (
  75.           velocity = slider1;
  76.         );
  77.         min_vel = (1 - MAX_VEL_SHIFT) * velocity;
  78.         max_vel = (1 + MAX_VEL_SHIFT) * velocity;
  79.  
  80.         vel_shift = z2 * slider5 / 10;
  81.     vel_shift *= (max_vel - min_vel) / MAX_IS_X_STDEV;
  82.     vel_shift = floor(vel_shift + 0.5);
  83.         velocity += vel_shift;
  84.         velocity = max(1, velocity);
  85.         velocity = min(velocity, 127);
  86.         velocity |= 0;
  87.         msg23 = note_num + velocity * 256;
  88.  
  89.     msec_shift = (pos_shift - baseline_pos_shift) * 1000 / srate;
  90.     slider6 = floor(msec_shift * 10) / 10;
  91.     slider7 = vel_shift;
  92.     sliderchange(2^6 + 2^7);
  93.       );
  94.  
  95.       (msg == AFTERTCH) ? (
  96.         mpos += buffer[note_num];
  97.       );
  98.  
  99.       (msg == NOTE_OFF) ? (
  100.         mpos += buffer[note_num];
  101.         buffer[note_num] = 0;
  102.       ); 
  103.  
  104.       buffer[MSG_BUF+n_buf] = mpos;
  105.       buffer[MSG_BUF+n_buf+1] = msg1;
  106.       buffer[MSG_BUF+n_buf+2] = msg23;
  107.       n_buf += 3;
  108.     );
  109.   );
  110.  
  111.   // Find everything in the buffer that is due
  112.   // to be played back in this block.
  113.   i = 0;
  114.   while (
  115.     (i < n_buf) ? (
  116.       mpos = buffer[MSG_BUF + i];
  117.  
  118.       (mpos < samplesblock) ? (
  119.         midisend(mpos, buffer[MSG_BUF+i+1], buffer[MSG_BUF+i+2]);
  120.         memcpy(MSG_BUF+i, MSG_BUF+i+3, n_buf-i);
  121.         n_buf -= 3;
  122.       ) : (
  123.         buffer[MSG_BUF+i] -= samplesblock;
  124.         i += 3;
  125.       );
  126.     );
  127.   );