# Anyone try scripting using the new K5 ksp features?



## UCAudio (Oct 9, 2011)

I'm wondering what all is possible with the new K5 ksp stuff... particularly the new midi sequencing stuff. Anyone script anything using the new features yet? Is there any documentation on the new ksp features?


----------



## Big Bob (Oct 9, 2011)

I'm still waiting for NI to ship but, I have heard that persistent arrays and some form of text input has also been added. 

Rejoice,

Bob


----------



## Lindon (Oct 25, 2011)

Well seems no one has answered yet so...I've spent a little time with the K5 KSP Manual and noodled some simple(very) scripts:

Theres a new level meter to play with 
These some new callbacks triggerable on completion of an action (mainly for file loads)

Theres midi file load
There is *NO* mid file player

..but there are commands to read first, next, previous events from midi files and the ability to ascertain the number of clicks (96 ppqn I think) to the next event.
Theres a new wait command wait_clicks(nnn).


With the above its pretty clear that you can read in a midi file and use a loop to move thru it "playing" events as you go...

Theres corresponding commands to alter midi events in a file and to save the file...


There's more. But that about covers it for the MIDI stuff in a five sentence overview..


----------



## thumky (Nov 16, 2011)

The Midi Player sounds reeeeeally interesting to me. I'm considering upgrading but i'm frustrated i can't read the manual first. Would you be willing to send me the K5 scripting manual? 
thx,
md


----------



## Lindon (Nov 16, 2011)

hmm, didnt you read this?:

*There is *NO* midi file player *


...and please dont ask people to send the manual. Want the manual? Buy the product.


----------



## Reegs (Nov 16, 2011)

Lindon @ Tue Oct 25 said:


> Theres midi file load
> There is *NO* mid file player
> 
> ..but there are commands to read first, next, previous events from midi files and the ability to ascertain the number of clicks (96 ppqn I think) to the next event.
> ...



I don't have K5 yet, but do the new commands sort of kill my pet project? (KSP2MIDI), or is there a niche for it yet?
http://peteroregan.com/scripts.html

Peter


----------



## thumky (Nov 17, 2011)

Lindon @ Tue Oct 25 said:


> ..but there are commands to read first, next, previous events from midi files...
> With the above its pretty clear that you can read in a midi file and use a loop to move thru it "playing" events as you go...



Take it down a notch, Lindon. These are exactly the features i'm looking for.


----------



## Mike Greene (Nov 17, 2011)

Reegs @ Wed Nov 16 said:


> Lindon @ Tue Oct 25 said:
> 
> 
> > Theres midi file load
> ...


That's a very cool looking utility, Peter.

I haven't played with any of the K5 MIDI commands yet, but it seems to me that with K5, you still have to write some code to make the MIDI files play. (Play note, wait a few clicks, play next note, wait some more clicks . . . ) So yours is probably simpler and faster for some situations. Plus it's the only option for the person who can't write code (which is most people.)


----------



## sonaht (Nov 17, 2011)

Hello,

Here is a generic script and a test midi file showcasing the new MIDI features of K5.

Hope it helps.

Best.
Thanos


```
on init
	message("")
	make_perfview
	
	declare @filepath
	{MAC}
	@filepath := "/Users/<username>/Documents/Native Instruments/Kontakt 5/MIDI Files/test.mid"
	{PC:=  C:\Users\username\Desktop\Kontakt 5\MIDI\test files\test.mid"}
	
	declare $TRACK_IDX := -1
	declare const $LISTENER_RESOL := 16
	declare const $LISTENER_BEAT_LENGTH_TICKS := 960 / $LISTENER_RESOL
	
	{playback related variables}
	declare $mf_length := -1	{midi file length - in ticks}
	declare $cur_listener_id
	declare $prev_ext_song_pos	{keeping track of the incoming song position}
	declare $cur_song_pos
	declare $diff				{wait time between events - in ticks}
	declare $last_pos			{position of the previously triggered event}
	declare $end_of_beat		{end position for all events that need handled by the current "on listener" callback}
	declare %num_events_per_note[128]		{number of active events per note - to keep track of their IDs and match Note-On and Note-Off events}
	declare %event_ids_per_note[128 * 10]
	{/playback related variables}
	
	declare ui_button $get_first
	declare ui_button $get_next
	declare ui_button $get_next_at
	declare ui_button $get_last
	declare ui_button $get_prev
	declare ui_button $get_prev_at
	
	declare ui_button $scan
	declare ui_button $move
	declare ui_value_edit $pos (0, 5000, 1)
	
	declare ui_button $play_in_loop
	move_control($play_in_loop, 6, 6)
	
	declare $count
	
	declare ui_label $monitor (3, 6)
	
	set_listener($NI_SIGNAL_TIMER_BEAT, $LISTENER_RESOL)
end on

on ui_control ($scan)
	$scan := 0
	add_text_line($monitor, "scan")
	mf_get_first($TRACK_IDX)
	while (mf_get_command() # 0)
		add_text_line($monitor, mf_get_pos() & "    " & mf_get_command() & "    " & mf_get_byte_one() & "    " & mf_get_byte_two())
		mf_get_next($TRACK_IDX)
	end while
end on

on ui_control ($move)
	$move := 0
	add_text_line($monitor, "move")
	mf_set_pos($pos)
	add_text_line($monitor, mf_get_pos() & "    " & mf_get_command() & "    " & mf_get_byte_one() & "    " & mf_get_byte_two())
end on

on ui_control ($get_next)
	$get_next := 0
	add_text_line($monitor, "get_next")
	mf_get_next($TRACK_IDX)
	add_text_line($monitor, mf_get_pos() & "    " & mf_get_command() & "    " & mf_get_byte_one() & "    " & mf_get_byte_two())
end on

on ui_control ($get_next_at)
	$get_next_at := 0
	add_text_line($monitor, "get_next_at")
	mf_get_next_at($TRACK_IDX, $pos)
	add_text_line($monitor, mf_get_pos() & "    " & mf_get_command() & "    " & mf_get_byte_one() & "    " & mf_get_byte_two())
end on

on ui_control ($get_prev)
	$get_prev := 0
	add_text_line($monitor, "get_prev")
	mf_get_prev($TRACK_IDX)
	add_text_line($monitor, mf_get_pos() & "    " & mf_get_command() & "    " & mf_get_byte_one() & "    " & mf_get_byte_two())
end on

on ui_control ($get_first)
	$get_first := 0
	add_text_line($monitor, "get_first")
	mf_get_first($TRACK_IDX)
	add_text_line($monitor, mf_get_pos() & "    " & mf_get_command() & "    " & mf_get_byte_one() & "    " & mf_get_byte_two())
end on

on ui_control ($get_last)
	$get_last := 0
	add_text_line($monitor, "get_last")
	mf_get_last($TRACK_IDX)
	add_text_line($monitor, mf_get_pos() & "    " & mf_get_command() & "    " & mf_get_byte_one() & "    " & mf_get_byte_two())
end on

on ui_control ($get_prev_at)
	$get_prev_at := 0
	add_text_line($monitor, "get_prev_at")
	mf_get_next_at($TRACK_IDX, $pos)
	add_text_line($monitor, mf_get_pos() & "    " & mf_get_command() & "    " & mf_get_byte_one() & "    " & mf_get_byte_two())
end on

on ui_control ($play_in_loop)
	if ($play_in_loop = 1)
		add_text_line($monitor, "playback start")
	else
		add_text_line($monitor, "playback end")
	end if
end on

on listener
	$cur_listener_id := $NI_CALLBACK_ID

	if ($play_in_loop = 1)
		if ($mf_length = -1)
			mf_get_last($TRACK_IDX)
			$mf_length := mf_get_pos()
		end if
		
		{is the clock running or not? if not "emulate" it}
		if ($prev_ext_song_pos = $NI_SONG_POSITION)
			$cur_song_pos := $cur_song_pos + $LISTENER_BEAT_LENGTH_TICKS
		else
			$cur_song_pos := $NI_SONG_POSITION
		end if
		
		$prev_ext_song_pos := $NI_SONG_POSITION
		
		{definition of the time window this "on listener" callback is handling}
		mf_get_next_at($TRACK_IDX, $cur_song_pos mod $mf_length)
		$end_of_beat := $cur_song_pos mod $mf_length + $LISTENER_BEAT_LENGTH_TICKS
		$last_pos := $cur_song_pos mod $mf_length
		
		while (mf_get_pos() < $end_of_beat and $play_in_loop = 1 and $cur_listener_id = $NI_CALLBACK_ID)
			if (mf_get_command() = 0)
				$end_of_beat := $end_of_beat mod $mf_length
				mf_get_first($TRACK_IDX)
				$diff := $mf_length - $last_pos + mf_get_pos()
			else
				$diff := mf_get_pos() - $last_pos
			end if
			
			if (ticks_to_ms($diff) > 0)
				wait_ticks($diff)
			end if
			
			if ($play_in_loop = 1)
				if (mf_get_command() = $MIDI_COMMAND_NOTE_ON and mf_get_byte_two() # 0)
					%event_ids_per_note[mf_get_byte_one() * 10 + %num_events_per_note[mf_get_byte_one()]] := play_note(mf_get_byte_one(),mf_get_byte_two(),0,0)
					add_text_line($monitor, mf_get_pos() & "    " & mf_get_command() & "    " & mf_get_byte_one() & "    " & mf_get_byte_two())
					inc(%num_events_per_note[mf_get_byte_one()])
				else
					if (mf_get_command() = $MIDI_COMMAND_NOTE_OFF or (mf_get_command() = $MIDI_COMMAND_NOTE_ON and mf_get_byte_two() = 0))
						add_text_line($monitor, mf_get_pos() & "    " & mf_get_command() & "    " & mf_get_byte_one() & "    " & mf_get_byte_two())
						dec(%num_events_per_note[mf_get_byte_one()])
						note_off(%event_ids_per_note[mf_get_byte_one() * 10 + %num_events_per_note[mf_get_byte_one()]])
					end if
				end if
			end if
			$last_pos := mf_get_pos()
			mf_get_next($TRACK_IDX)
		end while
	end if	
end on
```


----------



## xoandxo (Nov 17, 2011)

i put test.mid in Public 
then change like this
------------------------
declare @file_path 

@file_path := "C:\Users\Public\test.mid" 
————————————————————————
still can not hear anything......


----------



## sonaht (Nov 18, 2011)

Hi xoandxo,

The script is not meant to make Kontakt into Quicktime midi player 
It is generic just to show the new midi commands in action.

For one a midi file has no sound, it's merely a series of note on and note off bytes.
You would need to route the data through the script to play already loaded zones in K5.

Hope this helps.

Best,
Thanos


----------



## dpiatek (Sep 17, 2015)

I'm curious how one would sync the internal Kontakt tempo to match the tempo embedded in the MIDI file. I've been going over the KSP manual and Googling and can't seem to figure out an answer.


----------



## EvilDragon (Sep 17, 2015)

Kontakt doesn't care about the tempo of the MIDI file - it disregards it. Kontakt's own tempo is used instead.


----------



## emin2277 (May 1, 2019)

This script is not working on my macbook. I think the file path is wrong. In my macbook documents, sync with icloud drive. 
users / <user> / iCloud Drive / Documents / ..... I am writing this but does not see the midi file. Can you help me?


----------



## Edward Stevan (Mar 8, 2022)

emin2277 said:


> This script is not working on my macbook. I think the file path is wrong. In my macbook documents, sync with icloud drive.
> users / <user> / iCloud Drive / Documents / ..... I am writing this but does not see the midi file. Can you help me?


i think it not working because it has no function to load the midi file
mf_insert_file(@filepath,0,0,0)


----------

