High numbered keyswitches retuning

Sketch for Kontakt high numbered key switches retuning source code.

Do you just want to get the script and add it to your Kontakt instrument? If so, skip to.

Status
This now runs okay and permits high keyswitch retuning of Kontakt instruments.

For the draft of the RPN spec see Tuning RPNs (specification draft). I've modified it here, instead of using the data increment and decrement, I do it using keyswitches

The controllers idea
Our first idea was to use RPNs. See the Tuning RPNs (specification draft) for details. However I ran into issues implementing it as a Kontakt script. It only got about 12 of the RPN instructions out of a batch of 512.

Another idea was to use controllers like this:

The pitch bend fine is an "end of instruction" so no retuning is done until the pitch bend fine is reached. The extra fine pitch bend was an extra thing I added myself to get millicent precision in the display in Kontakt.

This idea seemed promising at first. But I ran into the same issue. If you send hundreds of controller messages, all for the same four controllers, in a short period of time, the script only gets notification of the last value of each of the controllers. That is understandable if you think of the controller messages as updating the value so the script only needs to know the latest value of the controller at any one time.

It was possible to get the controllers to work, but only if my program sent them at intervals of about 10 ms between each message, or about 40 ms between each occurrence of the same controller. Send them any more quickly than that and some got lost.

So, I was completely at a loss about how to proceed. This may just be a Kontakt issue, but it seems to me it might also be an issue with other synths as well. With controllers then generally your program wants to know the current value at any time and is less interested in the sequence of messages that lead to that value, so it is at least reasonable for a host or engine to discard controller messages if there is too much traffic.

The high numbered velocity keyswitches idea
This is the brilliant suggestion of Dr. Ozan Yarman of Başkent University. The topmost notes of the midi range are rarely used in instruments - are well beyond the top notes of a piano. Notes also are high priority so less likely to be dropped than controllers.

Keyswitches are often used to change playing styles of instruments, but typically they use notes below the natural range of the instrument to do this. The high notes are normally not used for anything.

So the idea is to send the information using the note on velocities of the note numbers 124 to 127.

In this script, as before, I also use note number 123 to send an extra ultra fine pitch resolution byte.

Instructions used in this script
Here the note 127 is used for "extra instructions".

I ran into a complication here that the note velocity has to be greater than zero, because a note on with velocity 0 is treated as a note off in Midi. This was solved by adding some more messages using the 127 (instructions) note.

Each instruction should be followed by a note release, which can be note on velocity 0. With running status this means it takes 8 bytes to retune a note.

Persistent output note
When you change the input note, then it sets to the last used output note for that input note.

So for instance in

126 60 - input note 125 62 - output note ... 126 61 - input note 125 65 - output note ... 126 60 - input note 125 62 - output note - is same as previous value this input note so can be ommitted.

This helps to reduce message traffic. For instance if you just want to slightly adjust the tuning of all the notes, e.g. several notes gliding simultaneously, then you only need to set the input note and the fine pitch bend of each note, most of the time.

Pitch bend format
The pitch bend follows the same format as a standard midi pitch bend, except that the pitch bend range (just for these messages) is hard coded to +- 50 cents. So there are 16384 steps for the range -50 to 50, giving a pitch bend resolution of 0.0061 cents.

That is good enough for even the most demanding of microtonalists in almost all situations (in theory, you could notice a difference in tuning of less than a hundredth of a cent on a super accurately pitched instrument if you had polyrhythmic beating partials beating at different rates from each other but this situation is likely to be exceedingly rare).

I've added the extra fine pitch bend here mainly so that the numbers can be displayed accurately in Kontakt, and because Kontakt works internally with millicents, or a thousandth of a cent. This divides each of the pitch steps into a further 128 finer steps giving a resolution less than 0.00005 cents.

Omni tuning mode and multi channel tuning mode
These are suggested instructions for our draft (totally unofficial) midi tuning spec

So - the idea is, multitimbral synths can be in mono tuning mode only, multi channel tuning mode only, or optionally both, and if both modes are supported, can, again optionally, respond to these instructions to change the tuning mode via midi.

For technical reasons, this script does not currently permit switching between mono and multi channel tuning mode via midi, and these instructions are ignored.

This Kontakt script acts on the instrument instance as a whole. So, it will be in multi channel tuning mode if you load a different copy of the instrument in each midi channel, and mono tuning mode if you load a single instance of the instrument set to receive midi notes on all channels.

(Q: Is there any way for a Kontakt script to check which midi channel the notes were received on? If so I could make it switchable between the two modes in case where user has it set to receive notes on all midi channels).

Sketch of how it works
First my script monitors the note on event. It records all the note on velocities for notes >= 123 and uses information encoded into the note on velocites of the notes to build a big tuning table in the internal memory of the instrument.

Then when you play ordinary notes it then looks up the note in that table to find out how to retune it. Then, depending on the pitch, it may choose a different sample from the one that would normally be played by that input note, and it then adjusts its tuning further by up to 50 cents up or down.

This script is for Kontakt only
This script relies on this unusual feature of Kontakt; you can modify the notes with a script AFTER the midi notes are received in the instrument. In this way, Kontakt lets you hack the inner workings of the instrument itself.

This script should work with almost all kontakt instruments. Will work also with other instruments e.g. .gig or .sf2 if they can be converted into Kontakt format. THIS SCRIPT HAS TO BE PLAYED IN KONTAKT PLAYER, AND WILL NOT WORK WITH ANY OTHER SAMPLE PLAYERS AFAIK.

It would I think be permissible for someone to write another sample player able to play Kontakt scripts using the published Kontakt script manuals as a basis, through the same laws of interoperability that permit Wine to emulate Windows. But would be a big task, many programmer years probably. Not heard of anyone who has done that.

You can't write a VST plug in to do any of this, because there is no midi message in the standard protocol to change the tuning of an individual note.

So, any VSTi would need to be reprogrammed individually to support this feature.

Similarly other sample players, software or hardware synths would need to have their code modified to use this feature.

They wouldn't need to use this script. The programmers would surely program their software directly to respond to thesse midi messages in the same way. It might be quite simple coding depending on the architecture, but because of the need to tune one note in the channel one way and another note another way, it is totally outside the scope of what can be achieved by a normal plug in.

How to use this
This script adds four knobs to the user interface for your instrument.

To retune any note on the keyboard to anywhere in the midi range, use the first knob to select the input note, second knob to select output note, third note to set pitch bend, and 4th knob to fine adjust the pitch bend in millicents

Later on I plan to release a version of Bounce Metronome able to send high numbered keyswitches to retune these instruments via midi, so e.g. you just need to select a SCALA scale from a drop list to retune all the notes to that scale.

Other programmers of retuning software will probably follow suit.

NOTE - BETA, WORK IN PROGRESS

How to add this script to a Kontakt instrument
Note, this is a BETA script - particularly since the spec itself is work in progress.

You need the full version of Kontakt to install this script. You can't use this with the free Kontakt Player as it doesn't have script editing capabilities (except briefly in demo mode).

Authors of instruments for Kontakt will also be able to add this script to their instruments. The license permits it to be used in this way, in any project, free or commercial.

You can get the script here: kontakt_high_keyswitches_tuning_no_release_retuning.txt

Here it is again, with syntax colouring for programmers: Kontakt retuning script

To add this script to a Kontakt instrument:


 * 1) click on the wrench icon
 * 2) then on Script Editor,
 * 3) then look for an empty slot labelled Click on tab to select it and
 * 4) then click Edit.
 * 5) Then copy and paste my script into the edit field.
 * 6) Then click Apply (button to far right)

The title of the script gets filled in automatically, the button and knobs will appear, and your instrument can now be micro-tuned in Kontakt.



You will be able to retune the input notes straight away using the knobs. The tuning is persistent, so you can edit the tuning by hand and save the tuning, and it will remain tuned like that next time you use the instrument.

Free script slot issues
Some instruments have no free slots for new scripts. Many of the Kontakt pianos are like this for instance. If so, AFAIK, the only way to use this script is to contact the original author of the instrument and see if they can modify it.

Assuming you do have free slots, it is probably best to install this into the first available script slot to prevent interference with other scripts. Unfortunately often the slots are locked or password protected.

As a result often you are forced to install this script after the other ones. You may find that it only works if you disable other scripts. Try disabling each in turn until you find out which one causes the problem. Then you might find you can copy / paste those problematical scripts into a later slot than the one used for this script.

If the script slots are not protected, or you are the original designer of the instrument, you might be able to merge my script with the script already there. This would need some knowledge of how the scripts work.

Out of tune release sample issue
Most instruments work just fine with the default script. However, you might find that the note changes pitch at the note off, when it triggers the "release sample". If that happens, try this script, which disables the old release sample, and triggers its own new release sample, tuned to match the output note + pitch bend:

kontakt_high_keyswitches_tuning_no_release_retuning.txt

It is a bit of a kludge because the only way you can retune these release samples in Kontakt is to DISABLE ALL AUTOMATIC RELEASE SAMPLES and retrigger a new release in the script when you get notification that the note needs to be released.

Luckily most instruments don't need this tweak. If you do need it, it might work fine, but is not guaranteed to work.

In some situations you get interference with the other scripts, such as an extra "double" note at the note release, which never switches off.

This method doesn't put any restrictions on the output frequencies of the instruments
Suppose that your midi instrument is able to play midi note 127, then you can set any note you like to play midi note 127, e.g. you could set note 60 to play 127. Usually note 127 is too high in pitch to be of any interest, but you also get other "unorthodox" ways of using the midi range such as repeats of the same instrument with different articulations etc. So note 127 might be needed, if so no problem.

Monster keyboard instruments with hundreds or thousands of keys, using this keyswitch method
Microtonalists often use keyboards with huge numbers of keys such as the Terpestra keyboard. So you might wonder if this keyswitch method would let you use large numbers of keys.

At first it might seem that such a keyboard would be limited to 123 keys per midi input channel. But actually you could design a keyboard with any number of keys, say 1000 keys, all playing distinct notes and all played on a single channel. The only restriction is that you can't play chords of more than 123 notes held down simultaneously in the same channel.

I thought it might help to explain how this is possible, by sketching a possible design for a monster keyboard like this. I am assuming that the keyboard has an embedded microchip which is used to translate the key presses into a stream of midi notes.

I have no idea how such chips are programmed, but the concept behind it is simple. The idea is to dynamically reassign the midi note numbers to keys. Only the keys that are actually held down at any time need to have a midi note number assigned to them.

1. Internally each key has its own id, not limited to the 0 to 128, as it is not using midi at this stage. Could be voltages or 16 bit numbers or whatever it is the key sends to identify itself. So for a 1000 key keyboard, then each key sends a different number from 0 to 1000 to the internal chip that converts the key presses into midi messages, this is the key's id.

2. the chip has an internal table of 1000 entries which keeps track of the midi note numbers assigned to these ids. It doesn't matter how this is done, but to take an example, to start with, it could be set to 0 to 122 for first 123 keys, and then remaining keys assigned number -1 meaning not in use.

3. The chip has another internal "lock" table of 1000 entries, initialised to 0. As soon as you play a note, that number is marked as locked - its entry in the table is set to 1. When a key is locked, its assigned midi note number can't be changed.

4. When you release the key it unlocks its number so it can be reassigned.

5. When you press a key that doesn't have a midi number assigned (current note number -1), then the program on the microchip will look through the table for a key that is not currently held down. It then will then swap with that key. It sets that old key's note number to -1 meaning not assigned any midi note number, and use its number as the midi note number for the new key.

6. Before it sends the new note number as a note on event, it sends the sequence of high keyswitches needed to retune that note to the correct output note on the destination synth.

6. At any time no more than 123 of the keys have midi note numbers assigned, and the remaining keys are assigned -1 = not assigned.

Then we can assign any pitch in the midi range to any of these 1000 keys. The only limitation on the keyboard is that you can't hold down more than 123 notes simultaneously.

There might be other ways to do it, but this method would work. The only question is how easy or hard this is to program. That takes us beyond my realm of expertise, would be easy in C code such as what I write, and surely is possible at least.

Useful links to download free Kontakt instruments
These instruments work with the full version of Kontakt. Most of them can be microtuned using this script with a simple copy / paste of the script into one of the free script slots in the instrument as in the screenshot above.

http://rekkerd.org/freebies-for-native-instruments-kontakt/

Also most of the Kontakt Factory preset instruments can be scripted in this way.

Instruments that need work or can't be scripted in this way
Some of the pianos have no free scripting slots. With all the scripting slots occupied and password protected, there is nothing you can do. But the editors of the instruments might be able to merge my script with theirs.

Some of the scripts interfere with this one. The bassoon for example in the factory presets collection did this. I think it probably generated extra notes during receipt of the high numbered keyswitches which interfered with their effect.

Anyway whatever the reason, it needed to have my script before the Instrument script. As none of the scripts could be edited, I bypassed both the existing scripts bypassed, put my script into the next free slot and then put copies of the existing scripts in the remaining slots.

So that is a possible solution if you have enough free slots.

Useful external links for the Kontakt Scripting Language
This is for developers who want to write their own Kontakt scripts, I used some of these links when writing this script

http://www.sandymilne.com/category/kontakt-scripting/

http://nilsliberg.se/ksp/

http://www.soniccouture.org/tutorial/scriptorium-manual.pdf

http://www.audiotek.cz/produktyATK/ni/kontakt3_p2.pdf

http://www.soundonsound.com/sos/jul10/articles/kontakt1.htm

bug details
I've actually got this working now, successfully retuned a Kontakt instrument to 120-et using RPN retuning sending the RPN messages from a debug build of Bounce Metronome.

But ran into a curious issue. I have to leave a pause of 40 ms between each change of rpn like this:

RPN coarse: 101 RPN fine: NoteToRetune Data entry coarse 0 Data entry fine: NoteToRetuneTo

Sleep(40)

RPN coarse: 100 RPN fine: NoteToRetune Data entry coarse : Pitch bend MSB Data entry fine: Pitch bend LSB

Sleep(40)

If I set it to less than that e.g. Sleep(10) then it gets mixed up.

It will use e.g. the Pitch bend LSB as the NoteToRetuneTo, as if it never got the intervening RPN coarse and RPN fine messages.

Anyone know why that is necessary and whether there is a work around?

Note - never found a solution to this. Same thing happened with the undefined controllers retuning. Needed to have a sleep of about 10 ms between each controller sent. If sent without sleeps, then I found that the script only received 12 controller messages out of a batch of 512 controllers sent to Kontakt, in a test run.

But - the keyswitches idea solves this. Notes are high priority.