Anyone try scripting using the new K5 ksp features?

UCAudio

Member
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

Senior Member
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

VST/AU Developer
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

New Member
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

VST/AU Developer
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

MIDI Mechanic
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..
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

New Member
..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

Senior Member
Moderator
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..
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
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

New Member
Hello,

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

Hope it helps.

Best.
Thanos

Code:
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
 

Attachments

xoandxo

New Member
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

New Member
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

New Member
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.
 

emin2277

New Member
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?