Help for Tune Smithy Koch snowflake icon.gif

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

From Tune Smithy

Revision as of 18:52, 15 December 2013 by WikiSysop (Talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

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.

Contents

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".

Note on velocity tuning instructions
127 1 reset tuning to 12-et for entire channel
126 v input note
125 v assign output note
124 v pitch bend (coarse)
123 v pitch bend (fine) - and update tuning
122 v pitch bend (extra fine) - optional, send before 123

So for instance

127 1 - 'reset to 12-et
126 60 -' set input note
125 62 -' assign output note 62 to the current input note (60)
124 32 -' assign 127 to the coarse pitch bend.
123 64  -' assign 32 to the fine pitch bend

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.

To send zero values
127 6 input note 0
127 5 assign output note 0
127 4 pitch bend (coarse) 0
127 3 pitch bend (fine) 0
127 2 pitch bend (ultra fine) 0

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.

Alternative method for zero values

(new idea, December 15th 2013)

To send zero values
127 126 input note 0
127 125 assign output note 0
127 124 pitch bend (coarse) 0
127 123 pitch bend (fine) 0
127 122 pitch bend (ultra fine) 0

The idea here is, instruction, followed by velocity n, gives zero value for n, so long as n is larger than (say) 122.

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

126 60 '- input note
125 62 '- assign this output note to the current input note
'- assigns 60 -> 62
...
126 61 '- input note
125 65 '- assign output note
'- assigns 61 -> 65
...
126 60 '- input note - at this point we already have 60 -> 62 as the assignment was done before
(125 62 '- assign output note - we have already done this, so don't heed to do it again.)

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.


mono tuning mode and multi channel tuning mode

127 6 Set synth to mono tuning mode - retune instructions on any channel apply to all the channels
127 7 Set synth to multi channel tuning mode - this should be the default if possible

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:

(RPN coarse, fine, data coarse, fine)
 
100, InputNote, 0, OutputNote
101, InputNote, Pitch bend MSB, Pitch bend LSB

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:

(RPN coarse, fine, data coarse, fine)
101, InputNote, - , Pitch bend LSB

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:

RPN MSB: Bc 65 64 (transpose, B means CC message, 65 means set RPN parameter MSB)
RPN LSB: Bc 64 nn (input note, 64 means set RPN parameter LSB)
data MSB: Bc 06 mm (output note, optional)
RPN MSB: Bc 65 65 (set the bend)
data MSB: Bc 06 yy (coarse tune, optional)
data LSB: Bc 26 zz (fine tune, required)

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:

Controller tuning instructions
113 0 reset tuning to 12-et for entire channel
114 n input note
115 n output note
116 n pitch bend (coarse)
117 n pitch bend (fine) - and update tuning
118 n pitch bend (extra fine) - optional, send before 117

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

0xF4, m, n = input note, output note
0xF5, c, f = coarse pitch bend, fine pitch bend

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

Why the 126 and 127 velocity tuning method seems a clear winner so far

The main advantages of the 126 and 127 method over the original method with notes 122 to 127 are:

  1. Notes 126 and 127 are high enough so in most applications they are not used at all, so you can leave the tuning method switched on all the time if you want. Note 123 is still very high, more than an octave above the highest note on a piano, but perhaps it might be used sometimes.
  2. Compared with the controllers and RPN method, it is more flexible. For instance it is easy to add a new instruction to vary the volume of the notes individually as well - for volume variation of a held note.

The version using noes 123 to 127 certainly is possible and has advantages. It also could be extended by adding new instructions as the 127 is hardly used at all in that system, you could add 127, 2 to change the volume of the note and use 126 and 125 for data. But it still has the complexities of the need to treat zero values separately from the other values.

In the absence of any clear strong advantage of the 123 to 127 note method, the one that uses fewest notes for the keyswitches seems best. It would be possible to use just a single note for the keyswitches, but only with an increase in complexity and large increase in the number of keyswitches that need to be sent. So, the two note numbers method seems best so far.

This is open for discussion and clearly any method one chooses has a certain level of arbitrariness e.g. the choice of 127, 4 as the "retuning instruction", where you have to make some choice or other and then stick with it as your standard.

Advantages of high numbered keyswitch retuning over the other methods include:

  1. The other methods involving controllers and RPNs simply don't work with Kontakt at present because of the way it treats intermediate values in a continuously changing controller as unimportant data which can be dropped if many values are received in a short space of time.
  2. Note ons are sure to be high priority in any midi environment, messages that must not be lost. So issues of dropped data seem unlikely to affect a note keyswitches retuning method.
  3. Keyswitches are an established method of changing instrument style, so many synths will already have code to handle note keyswitches already, as something other than normal midi notes.
  4. All synths are already equipped to receive note ons. They might not be set up to receive RPNs or undefined system common messages - for instance in Kontakt, again, then a different mechanism is set up for the RPNs and there is no way to receive undefined system common messages. This last point is less of an issue for controllers as most synths are likely to be able to receive controllers - but again, response to controlers is something not required in the midi standard, and e.g. undefined controllers could be stripped from the midi stream, while a synth absolutely has to be able to receive and play note ons or it wouldn't be a synth.
Personal tools
Namespaces
Variants
Actions
Navigation
How to use the wiki
More
Toolbox