Skip to content

Instantly share code, notes, and snippets.

@aike
Last active August 3, 2021 14:09
Show Gist options
  • Save aike/26236e96523d99a11ba855969c37976e to your computer and use it in GitHub Desktop.
Save aike/26236e96523d99a11ba855969c37976e to your computer and use it in GitHub Desktop.
Mersenne Twister (MT19937) random number generation library in KONTAKT KSP
{==========================================
Mersenne Twister example
random sequencer multi script
==========================================}
on init
set_ui_height_px(200)
make_perfview
set_script_title("MT Sequencer")
declare const $wait := 150000
declare %scale[8] := (0, 2, 4, 5, 7, 9, 11, 12)
declare ui_table %notes[16](4,6,8)
set_control_par(get_ui_id(%notes), $CONTROL_PAR_WIDTH, 400)
set_control_par(get_ui_id(%notes), $CONTROL_PAR_HEIGHT, 150)
move_control_px(%notes, 180, 20)
declare ui_value_edit $Seed(0, 07fffffffh, 1)
$Seed := 0
set_control_par(get_ui_id($Seed), $CONTROL_PAR_WIDTH, 90)
move_control_px($Seed, 70, 20)
declare ui_switch $Play
set_control_par(get_ui_id($Play), $CONTROL_PAR_WIDTH, 90)
move_control_px($Play, 70, 60)
declare $n
declare $beat
declare $playing
{==========================================
Mersenne Twister (MT19937)
random number generation library in KSP
usage:
call mt_init
initialize with $mt_seed
call mt_genrand
get a random number into $mt_rand
the range is 31bit (0-07fffffffh)
license:
MIT License
original version in C
http://www.math.sci.hiroshima-u.ac.jp/m-mat/MT/MT2002/CODES/mt19937ar.c
==========================================}
{ MT access variables }
declare $mt_seed
$mt_seed := 0
declare $mt_rand
{ MT xor helper variables }
declare $mt_xor_arg1
declare $mt_xor_arg2
declare $mt_xor_tmp_or
declare $mt_xor_tmp_nand
declare $mt_xor_result
{ MT Period parameters }
declare const $mt_N := 624
declare const $mt_M := 397
declare const $mt_MATRIX_A := 09908b0dfh
declare const $mt_UPPER_MASK := 080000000h
declare const $mt_LOWER_MASK := 07fffffffh
declare %mt_x[$mt_N]
declare $mt_i
declare $mt_y
declare $mt_z
{ MT initialize array with $mt_seed }
%mt_x[0] := $mt_seed .and. 0ffffffffh
$mt_i := 1
while ($mt_i < $mt_N)
$mt_xor_arg1 := %mt_x[$mt_i - 1]
$mt_xor_arg2 := sh_right(%mt_x[$mt_i - 1] .and. $mt_LOWER_MASK, 30)
if (%mt_x[$mt_i - 1] < 0)
$mt_xor_arg2 := $mt_xor_arg2 .or. 2
end if
$mt_xor_tmp_or := $mt_xor_arg1 .or. $mt_xor_arg2
$mt_xor_tmp_nand := .not. ($mt_xor_arg1 .and. $mt_xor_arg2)
$mt_xor_result := $mt_xor_tmp_or .and. $mt_xor_tmp_nand
%mt_x[$mt_i] := (1812433253 * $mt_xor_result) + $mt_i
%mt_x[$mt_i] := %mt_x[$mt_i] .and. 0ffffffffh
inc($mt_i)
end while
$mt_i := 0
message("")
end on
{ MT helper function calculate $mt_xor_arg1 XOR $mt_xor_arg2 }
function mt_xor
$mt_xor_tmp_or := $mt_xor_arg1 .or. $mt_xor_arg2
$mt_xor_tmp_nand := .not. ($mt_xor_arg1 .and. $mt_xor_arg2)
$mt_xor_result := $mt_xor_tmp_or .and. $mt_xor_tmp_nand
end function
{ MT initialize array with $mt_seed }
function mt_init
%mt_x[0] := $mt_seed .and. 0ffffffffh
$mt_i := 1
while ($mt_i < $mt_N)
$mt_xor_arg1 := %mt_x[$mt_i - 1]
$mt_xor_arg2 := sh_right(%mt_x[$mt_i - 1] .and. $mt_LOWER_MASK, 30)
if (%mt_x[$mt_i - 1] < 0)
$mt_xor_arg2 := $mt_xor_arg2 .or. 2
end if
call mt_xor
%mt_x[$mt_i] := (1812433253 * $mt_xor_result) + $mt_i
%mt_x[$mt_i] := %mt_x[$mt_i] .and. 0ffffffffh
inc($mt_i)
end while
$mt_i := 0
end function
{ MT generates a random number }
function mt_genrand
$mt_z := %mt_x[$mt_i] .and. $mt_UPPER_MASK
$mt_z := $mt_z .or. (%mt_x[($mt_i + 1) mod $mt_N] .and. $mt_LOWER_MASK)
$mt_xor_arg1 := %mt_x[($mt_i + $mt_M) mod $mt_N]
$mt_xor_arg2 := sh_right($mt_z .and. $mt_LOWER_MASK, 1)
if ($mt_z < 0)
$mt_xor_arg2 := $mt_xor_arg2 .or. 040000000h
end if
call mt_xor
$mt_xor_arg1 := $mt_xor_result
if (($mt_z .and. 1) = 0)
$mt_xor_arg2 := 0
else
$mt_xor_arg2 := $mt_MATRIX_A
end if
call mt_xor
%mt_x[$mt_i] := $mt_xor_result
$mt_y := %mt_x[$mt_i]
{ Tempering }
$mt_xor_arg1 := $mt_y
$mt_xor_arg2 := sh_right($mt_y .and. $mt_LOWER_MASK, 11)
if ($mt_y < 0)
$mt_xor_arg2 := $mt_xor_arg2 .or. 100000h
end if
call mt_xor
$mt_y := $mt_xor_result
$mt_xor_arg1 := $mt_y
$mt_xor_arg2 := sh_left($mt_y, 7) .and. 09d2c5680h
call mt_xor
$mt_y := $mt_xor_result
$mt_xor_arg1 := $mt_y
$mt_xor_arg2 := sh_left($mt_y, 15) .and. 0efc60000h
call mt_xor
$mt_y := $mt_xor_result
$mt_xor_arg1 := $mt_y
$mt_xor_arg2 := sh_right($mt_y .and. $mt_LOWER_MASK, 18)
if ($mt_y < 0)
$mt_xor_arg2 := $mt_xor_arg2 .or. 2000h
end if
call mt_xor
$mt_y := $mt_xor_result
{ get 31bit unsigned int }
$mt_rand := sh_right($mt_y .and. $mt_LOWER_MASK, 1)
if ($mt_y < 0)
$mt_rand := $mt_rand .or. 040000000h
end if
$mt_i := ($mt_i + 1) mod $mt_n
end function
{==========================================
Mersenne Twister End
==========================================}
on ui_control($Seed)
{ initialize MT with $mt_seed }
$mt_seed := $Seed
call mt_init
set_midi(0,$MIDI_COMMAND_NOTE_ON, $n, 0) { note off }
$n := 0
while ($n < 16)
{ get a MT random number into $mt_rand }
call mt_genrand
%notes[$n] := $mt_rand mod 8
inc($n)
end while
end on
on ui_control($Play)
if ($Play = 1)
$playing := 1
$beat := 0
while ($playing = 1)
$n := 60 + %scale[%notes[$beat]]
set_midi(0,$MIDI_COMMAND_NOTE_ON,$n,100) { note on }
wait($wait)
set_midi(0,$MIDI_COMMAND_NOTE_ON,$n, 0) { note off }
wait(100)
$beat := ($beat + 1) mod 16
end while
else
$playing := 0
end if
end on
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment