{ Part Maker 1.0
  By Nils Liberg
  
  You can use this script to transpose and pitch-bend back notes for secondary voices.
  This is useful for ensembles where you layer multiple instances of the same instrument,
  but want to avoid phasing problems.
  
  This script is inspired by J's Ensemble Maker script, but differs in a couple of ways.
  First of all the Ensemble Maker script makes one instrument into an ensemble while this
  script makes one instrument into one voice of the ensemble. In most cases Jay's script is 
  simpler to setup, but if you for some reason want to let separate instruments play the
  voices (eg. you want to use different MIDI channels for voices, place the voices in an
  instrument bank, or want more control) you can use this script. Another benefit is that 
  this script supports polyphonic playing for instruments with release triggers.
  On the negative side it lacks end-slop and has not been tested with VSL legato yet.   
  I see it more as a complement than a competitor to the Ensemble Maker script.

  In addition to the tranpose part there is also a simple humanizer part -
  tuning, velocity (optionally random) and start timing sloppiness (always random).  
  Important: if your instrument uses release triggers you must set the Release Group.
  
  Links:
    - The web page of this script:
      http://nilsliberg.se/ksp/scripts/scripts.html
      
    - Theo Krueger's Kontakt Script Collector page (including J's Ensemble Maker):
      http://www.theokrueger.com/kontakt2.htm
}
on init  
  declare ui_value_edit $transpose(-12,12,1)       { number of notes }
  declare ui_value_edit $tuning(-50000,50000,1000) { number of cents }  
  declare ui_value_edit $velocity(-127,127,1)      { velocity adjustment }
  declare ui_value_edit $slop(0,500,10)            { number of ms    }
  declare ui_button $random_tuning                 { whether detuning is random            }
  declare ui_button $random_velocity               { whether velocity adjustment is random }
  declare ui_menu $release_group                   { index of release group                }
  declare ui_label $label_slop(1,1)
  declare ui_label $label_release(1,1)    
  declare polyphonic $parent_id                    { a copy of the original $EVENT_ID     }  
  declare polyphonic $new_tuning                   { the tuning used in note callback     }
  declare polyphonic $new_velocity                 { the velocity used in note callback   }
  declare $id                                      { id of script generated note          }
  declare $group_index := -1                       { only used in "on init"               }
  declare $i                                       { only used in "on init"               }
  
  { init control values }
  $random_tuning := 1
  $random_velocity := 1
  
  { init release group menu }
  add_menu_item($release_group, "", -1)
  while ($group_index # 0)
    add_menu_item($release_group, group_name($i), $i)    
    inc($i)
    $group_index := find_group(group_name($i))
  end while
  
  { init controls }
  set_text($label_slop, "               (in ms)")    
  set_text($label_release, "Release group:")  
  move_control($random_tuning, 2, 2)
  move_control($random_velocity, 3, 2)
  move_control($label_slop, 4, 2)
  move_control($label_release, 5, 1)
  move_control($release_group, 5, 2)  
  
  { init persistence }
  make_persistent($transpose)
  make_persistent($tuning)
  make_persistent($slop)
  make_persistent($random_tuning)
  make_persistent($random_velocity)
  make_persistent($release_group)
  
  SET_CONDITION(NO_SYS_SCRIPT_RLS_TRIG)
  message("")
end on

on note
  ignore_event($EVENT_ID)  
  $parent_id := $EVENT_ID { save this so we can tell the two release callbacks apart
                            (one for the original note which have polyphonic variables
                            tied to it, and one for the generated note which don't have
                            polyphonic variables)
                          }
  
  { if release group set, turn it off }
  if ($release_group # -1)
    allow_group($ALL_GROUPS)
    disallow_group($release_group)
  end if
  
  { wait for a random slop time }
  if ($slop > 0)
    wait(random(0, $slop*1000))
  end if  
  
  { calculate tuning }
  if ($random_tuning = 1)
    $new_tuning := -100000*$transpose + random(-$tuning, $tuning)
  else
    $new_tuning := -100000*$transpose + $tuning
  end if
  
  { calculate velocity and make sure it's in the 0-127 range }
  if ($random_velocity = 1)
    $new_velocity := $EVENT_VELOCITY + random(-$velocity, $velocity)
  else
    $new_velocity := $EVENT_VELOCITY + $velocity
  end if  
  if ($new_velocity > 127)
    $new_velocity := 127
  end if
  if ($new_velocity < 0)
    $new_velocity := 0
  end if
  
  { play the transposed note and change its tuning }
  $id := play_note($EVENT_NOTE + $transpose, $new_velocity, 0, -1)
  change_tune($id, $new_tuning, 0)  
end on

on release
  { if release group set and this is the release of the note that triggered "on note" }
  if ($release_group # -1 and $EVENT_ID = $parent_id)
        
    { turn release group on and everything else off }    
    disallow_group($ALL_GROUPS)
    allow_group($release_group)
    
    { play the transposed release note and change its tuning }
    $id := play_note($EVENT_NOTE + $transpose, $new_velocity, 0, -1)
    change_tune($id, $new_tuning, 0)  
  end if
end on