Other proposals we looked at, for retuning using undefined controllers, undefined RPNs, other methods with velocity keyswitches and using undefined Midi messages

These are alternatives to the High numbered keyswitches retuning unofficial midi spec. These all had various drawbacks, and so far the velocity retuning with notes 127 and 126 seems the clear winner at least for Kontakt.

However I include the other methods here for reference in case they are useful in other situations.

Sending the instructions using a single high numbered velocity keyswitch
Actually you could reduce it to velocity instructions on a single note number, midi note 127. But that would get more complex and need more data.

One way to do that would be to use the. highest 3 bits set the "status" and lower 4 bits set the "data". This time you need 4 messages to send 2 bytes.

I'm not sure it is worth the extra complexity and the increased number of bytes needed, especially now that we can switch off the high keyswitches retuning and so send a complete 128 note tuning table to the synth using the two notes method.

Velocity tuning keyswitches (original method with notes 122 to 127)
Here the note 127 is used for "extra instructions".

So for instance Now input note 60 will be retuned to midi note 62, with pitch bend, 64 + (32*128) = 4160

Zero values
All this works fine except for a minor 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 (extra 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, the output note gets set to the last used output note for that input note. This may be clearer with an example:

So for instance in

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.

The RPNs idea
This was our first idea. However it didn't work as a Kontakt script. It worked by using undefined RPNs.

With the coarse part of the RPN set to 100 and 101 and fine part of the RPN set to the note you want to retune, this is what you send:

There tuning happens during receipt of the pitch bend LSB. Only the input not and the pitch bend LSB are required, so a minimal message if you keep the current data values for all the undefined RPNs is:

where the - means that no data is sent.

However for this to work you need to be able to inspect the raw data stream. Is not enough to just be able to interrogate and find the current data value for any of the RPNs. If your script or code can only inspect the current data value of the RPNs, then it is necessary to send all the data.

In hex:

bug for RPNs idea
I got this working, 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.

Note also I don't know for sure if this happens in Kontakt or in my DAW (Cantabile).

But - the keyswitches idea solves this. Notes are high priority and don't seem to get lost in the same way.

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 (sent before the fine) - most programmers would not need this.

For choice of controllers I used the last six of the "undefined controllers" (UPDATE - now using 119 to set the tuning method - so will use 113 to 118 instead of 114 to 119, will update script soon).

Another approach, to use undefined system common messages
Midi has several undefined "system common" messages which are just like the Note on, aftertouch etc messages but are left undefined for future use. It seems unlikely that these will ever get defined.

These messages include: 0xF4, 0xF5, 0xF9, and 0xFD

If we could use two of the undefined system common messages, that would be ideal for data, as that would let us send two bytes of information with a single message and you could retune a single note with just two messages, six bytes

as before retunes m to n with c, f for the pitch bend

Unfortunately you can't access them in a Kontakt instrument script. I would imagine in many environments you can't access them.

It could be done in Windows, sending messages from one Windows program to another one coded at a low level with midiOutShortMsg