Kontakt Scripting · KSP

Playing a Random Set of Samples in Kontakt

June 2014

For a project I am working on I am using Native Instruments Kontakt's scripting language (KSP) to trigger random samples from a range within the sampler.

This was all working well but when the sample size was getting too small the script was getting locked in a while loop trying to find notes that it had not used before — which was very inefficient and would eventually cause Kontakt to hang.

The Solution: Shuffle an Array

The solution I came up with was to use an array to store all the note indices, which gets shuffled randomly whenever the playhead reaches the end of the list. This way we cycle through every sample exactly once before repeating — no infinite loops, no repeated samples until the full set has played.

The Script

on init
  message("Loaded...")

  declare $temp := 0
  declare $random_temp := 0
  declare $counter := 0
  declare $lower_limit := 0
  declare $upper_limit := 10
  declare $play_head := 0

  declare %array_one[10]

  { Populate array with sequential indices }
  while($counter < num_elements(%array_one))
    %array_one[$counter] := $counter
    inc($counter)
  end while

  { Initial shuffle }
  $counter := 0
  while($counter < num_elements(%array_one))
    $random_temp := random(0, num_elements(%array_one) - 1)
    $temp := %array_one[$counter]
    %array_one[$counter] := %array_one[$random_temp]
    %array_one[$random_temp] := $temp
    inc($counter)
  end while

end on


function shuffleArray
  $counter := 0
  while($counter < num_elements(%array_one))
    $random_temp := random(0, num_elements(%array_one) - 1)
    $temp := %array_one[$counter]
    %array_one[$counter] := %array_one[$random_temp]
    %array_one[$random_temp] := $temp
    inc($counter)
  end while
end function


on note
  if ($play_head < 10)
    message("Playing....")
    play_note(%array_one[$play_head], 100, 0, -0)
    inc($play_head)
  else
    message("Shuffle....")
    call shuffleArray
    $play_head := 0
    play_note(%array_one[$play_head], 100, 0, -0)
    inc($play_head)
  end if
end on

How it Works

On initialisation, the array is filled with sequential indices (0 through 9) and then immediately shuffled using a Fisher-Yates style swap. On each note trigger, the script plays the sample at the current playhead position and advances. Once the playhead reaches the array limit, the array is reshuffled and the playhead resets — guaranteeing a new random order each cycle.

This approach is far more efficient than searching for an unused note. It also guarantees every sample is heard before any repeats, which gives a much more natural and musical result.