# Suggestions for CC usage in scripts



## Big Bob (Aug 31, 2007)

Hi Everyone,

More and more scripts are being written which provide optional MIDI control of knobs and edit boxes. In addition, MIDI CCs have been used in other inventive ways such as Interscript communication and, more recently, as 'proxies' for other kinds of MIDI events that the KSP doesn't make available to scripts (such as aftertouch).

As part of a major new upgrade to SIPS, I decided to spend some time thinking about the best ways to incorporate CCs into scripts and I thought I would share some of my thoughts with you in an effort to promote some future uniformity in how scripters (and script kiddies :wink: ) handle CCs.

The MIDI spec provides for a total of 128 CCs numbered from 0 to 127. Each such CC event contains a 7-bit data field and thus can carry a value in the range of 0 to 127 also. When the MIDI spec was originally setup, the CCs from 120 to 127 were set aside for a special purpose. These CCs are usually referred to as the 'Channel Mode Messages'. These messages are defined in the MIDI spec as:

120 All Sound Off
121 Reset All Controllers
122 Local Control On/Off
123 All Notes Off
124 Omni Mode Off
125 Omni Mode On
126 Poly Mode On/Off
127 Poly Mode Mono Off

I'll say more about these Channel Mode Messages later.

However, my first suggestion is that we write our scripts to allow only the CCs from 0 to 119 to be assigned for parameter control purposes. I have seen several scripts where any CC# from 0 to 127 is allowed but I would like to discourage you from allowing CCs above 119 to be assigned. And, even though K2 allows you to assign CCs from 0 to 127 to control various parameters in the synth engine, I would also like to discourage you from overtly using CCs above 119.

The exception to this in your scripts will be the Pitch Bender. As MIDI data, Pitch Bender messages are distinct from CC messages because the bender has its own MIDI op code and carries a 14-bit data field. But, for convenience, many keyboards and synthesizers use CC#s above 127 to represent special controllers. The KSP uses CC#128 for scripts to access Bender messages. So when you allow a script knob to be controlled via MIDI by assigning a CC, if you want to allow the bender to be assigned, you have to provide for the number 128 (internally at least) in addition to the CC# range from 0 to 119.

If you are using a simple value edit box for the user to select a CC number, this presents a small problem in that there is a discontinuity in the series. Various ways around this have been implemented such as using -1 to indicate the bender. This makes the edit-box range continuous from -1 to 119. More recently, several of us have started using drop-down menus for CC assignment. This is the most flexible because no special sequence of numbers is required and moreover, descriptive names can be used to indicate the more or less standard usage for each of the CCs. For example, Mod Wheel, Breath Control, Volume, and Expression are almost universally associated with CC1, CC2, CC7 and CC11 respectively.

Now, I'd like to discuss special usage of CCs and make a few more suggestions. Referring to the Channel-Mode messages (CC120 to CC127), many synthersizers (especially older ones) use all these messages for their intended purpose. However, as best as I can tell, K2 only recognizes CC120 and CC123 (however they can be defeated in Instrument Options). Whenever we utilize a CC for some special purpose (such as serving as a proxy for aftertouch), we then have a potential conflict with other uses of that CC. So for example, if we use CC100 as a proxy for aftertouch, then we need to avoid using CC100 elsewhere for other things that might conflict. It would be nice if we could implement a few commonly needed special functions with CCs without 'burning up' any of our general purpose CC pool (0 to 119).

Two special uses for CCs that have become of much interest recently are as 'proxies' for *Aftertouch* and *Program Change*. These are of much interest because the KSP does not directly allow scripts to respond to these MIDI events and recently several pre-processing schemes (which allow these MIDI events to be 'mapped' to CC messages) have become available. So before everyone starts using a different set of CCs for these proxies, I'd like to suggest that we use *CC124 for Aftertouch and CC125 for Program Change*. I have already adopted these proxies in the new version of SIPS.

There are several ways of doing the 'front-end' processing required to map AT and PC to CC124 and CC125 proxies including a special VST plugin that Marc Bangerter (*mbncp* on the forums) has developed. More recently, thanks to Nils' (aka Kotori) amazing detective work, we now have another way to do the pre-processing by writing a MultiScript. My suggestion is that we judiciously utilize the 6 Channel-Mode messages that K2 doesn't respond to for a number of these kinds of things.

When Marc wrote his plugin, he also included a timer function which is very useful in scripts. This KSP-Timer provides a steady stream of CC122 messages that you can use to accurately time various events without the need for messy polling loops. I have also written a slot-1 script which can supply this KSP-Timer function in the absence of the plugin so we intend that there will be a lot of flexibility here. But, I'd like to ask you to *reserve CC122 *for this timer 'interrupt' function.

Finally, due to Nils' brilliant discoveries with MultiScripts, there will no doubt be many pre-processing scripts written shortly. Part of the problem with this scheme however is that the MS control panel is not readily accessible (because of the need to do the registry bit). Since the MS panel cannot be switched in and out by your script and if you have a MS that you would like to provide several user-selectable options for, either the user has to keep swapping variations of the MS that you write or worse. However, there is a very nifty solution for this problem. We can write the MS in such a way that it can be custom-configured with any keyboard (via MIDI) and then resaved with the new options. All this can be done without having to launch K2 in the MS mode. 

Marc and I have been working together to develop a series of pre-processing modules that we call the* KSP Plus System*. This system is within a few days of completion and we will then make it available free to all scripters and script users. At that time, I will post a Programmable MS that you can use both for it's intended purpose and as a prototype for future programmable MultiScripts. However, I'm mentioning this prematurely because the MIDI programming strategy I'm using will also utilize another CC or two from the 'dwindling' list of channel-mode messages. These things will eventually become scarce as hen's teeth so let's try to not use them all up without careful planning.

My purpose in writing this is not to put anyone in a straight jacket but rather to give everyone the benefit of the effort I have already expended in this area and save some of you the trouble of re-inventing the CC Wheel :lol: .

God Bless,

Bob


----------



## mbncp (Aug 31, 2007)

Hi Bob, 

If I get you right, we have:

120 All Sound Off --> handled by K2
121 Reset All Controllers --> "unused"
122 Local Control On/Off --> Timer
123 All Notes Off --> handled by K2
124 Omni Mode Off --> Channel Aftertouch
125 Omni Mode On --> Patch Change
126 Poly Mode On/Off --> currently unused
127 Poly Mode Mono Off --> multi script programming mode

I think that 121 (Reset All Controllers) should be left unused as it can be used to reset some scripts or multiscripts in a certain state.

Btw, here's an article on Reset All CC by the MMA:
http://www.midi.org/about-midi/rp15.shtml


> Upon receipt of Reset All Controllers message (Controller #121) the following actions are taken for the specified MIDI channel:
> 
> Set Expression (#11) to 127
> Set Modulation (#1) to 0
> ...



But then, it's pretty up to us.

Marc


----------



## Big Bob (Aug 31, 2007)

Hi Marc,

Fancy meeting you here :lol: 



> I think that 121 (Reset All Controllers) should be left unused as it can be used to reset some scripts or multiscripts in a certain state.



You might have noticed that I 'skipped over' CC121 with just this sort of thing in mind. For now let's just say that CC121 should probably be the last one we assign for some other function :wink: .

God Bless,

Bob


----------



## Reegs (Aug 31, 2007)

Hi Bob,

As a newcomer into the scripting world, please let me say how grateful I am for all the pioneer work that you have done. It is really inspiring.

I am modifying my scripts to adjust to the new parameters.

Also, regarding the break in continuous controller values, perhaps an effective workaround would be to adjust the break via the ui_control statement, giving the user the appearance of the jump:


```
on init
declare ui_control $ValueEdit (0,128,1)
end on

on ui_control ($ValueEdit)

if $ValueEdit =120
  $ValueEdit = 128
end if
if $ValueEdit = 127
   $ValueEdit = 119
end if

end on
```


I use CC-adjustable bypass controls in many of my scripts to make it easy to enable/disable them on the fly. 
With the discoveries going on regarding multiscripts, do you think there is a command that will bypass a script (like bypass($ScriptSlot1))? There's a button for it, so my thought is that a function for it should exist, somewhere. If we find it, perhaps it would be a good idea to create a standardized set of bypass CC's, so that a user knows that if he loads a multi-control script, CC#114 will always disable a script in slot 1, and 115 will work for slot 2, etc.

Reegs


----------



## mbncp (Aug 31, 2007)

Big Bob @ Fri Aug 31 said:


> Fancy meeting you here :lol:


Well, lots of nêw cool stuff these days, so I better follow what's coming up 



> You might have noticed that I 'skipped over' CC121 with just this sort of thing in mind. For now let's just say that CC121 should probably be the last one we assign for some other function :wink: .


I never really though you'd miss that :lol: 

I think that a few sequencers are sending CC121 on stop, which can be interesting.

Cheers,
Marc


----------



## Big Bob (Aug 31, 2007)

> I think that a few sequencers are sending CC121 on stop, which can be interesting.



One thing I didn't mention is that when we use say CC124 as a proxy for Aftertouch,
the front-end processor (be it a plugin or a MultiScript) should discard 'real' CC124s in the input stream. That way when a normal script receives a CC124, it's always an Aftertouch proxy, not some unintened, 'Omni Mode Off' message.

and 

Hi Reegs,



> Also, regarding the break in continuous controller values, perhaps an effective workaround would be to adjust the break via the ui_control statement, giving the user the appearance of the jump:



That's another good way to skin the cat :lol: . I should mention though that sometimes the KSP is a little slow at updating ui controls and the user may be a little 'startled' by what he sees :o . Nevertheless, it does keep a user from entering a value in the 'illegal range'

As to the bypass button thingy, so far I don't think anyone has come up with the command, but, hang in there because this is a pretty prolific bunch 8) 

God Bless,

Bob


----------



## mbncp (Aug 31, 2007)

For bypass and other goodies *_set_engine_par_m* is probably the function we are looking for in multiscripts.

I didn't try it yet, but I believe it uses the same syntax as _set_engine_par with probably the channel number (0-63) as first parameter.

This will be a nice little boring job to figure out what is what ... :( 

Another option would be to hire a retired spy in Berlin 

Cheers,
Marc


----------



## kotori (Aug 31, 2007)

mbncp @ Fri Aug 31 said:


> _set_engine_par_m is probably the function we are looking for in multiscripts. I didn't try it yet, but I believe it uses the same syntax as _set_engine_par with probably the channel number (0-63) as first parameter.


I would rather guess that the first parameter still represents the parameter code. Maybe it's: _set_engine_par_m(parameter, value, channel_number, slot, generic)
where one or both of slot and generic have been removed.



> This will be a nice little boring job to figure out what is what ... :(
> 
> Another option would be to hire a retired spy in Berlin


 :lol:


----------



## mbncp (Aug 31, 2007)

kotori @ Fri Aug 31 said:


> I would rather guess that the first parameter still represents the parameter code. Maybe it's: _set_engine_par_m(parameter, value, channel_number, slot, generic)
> where one or both of slot and generic have been removed.



Yeap just notice that we don't have an extra parameter.
Also still only 512 elements per array (now that's cheap on a multi).

I guess the trick is to have a multiscript read "all" values into a few arrays, "wait" for the user to make a change, like moving an AUX slider, and scan again and see what has changed.

I still like the spy guy idea better :wink: 

Cheers,
Marc


----------



## Big Bob (Aug 31, 2007)

> I still like the spy guy idea better



I'll vote for that idea! What do industrial spys earn now days? Maybe a few of us could chip in together :lol: 

BTW Marc, your latest *KSP_Plus *plugin seems to work beautifully. The only reason I haven't emailed you yet is because I'm putting the finishing touches on the MultiScript so I can test all the combinations with and without the plugin. If that's OK, then I have to complete the Programmer Script but, I'm starting to get a little weary from lack of sleep I guess. So, I may not get this all finished until tomorrow. :roll:


ZZZZZZzzzzzzzzzzz..........


----------



## mbncp (Sep 1, 2007)

Big Bob @ Sat Sep 01 said:


> I'll vote for that idea! What do industrial spys earn now days?


In the VI business ? Not much :cry: 

Hi Bob,

I think it would be nice to have a sticky on CC usage. With some extra info about plugs using them by default.

I know I will use one to have access to the 64 channels in plug mode. Using 2 bits for the port and 5 for the "in-script channel". And now that I can dynamically load any patch, it will be a breeze to load 6 times an instrument for using the guitar, so I won't bother you anymore with a multi-channel SIPS :oops: 

I noticed that data2 in midi_in holds the note off velocity. So I will use another CC for that one, sending it just before the NoteOff message.

Sending a CC to K2 from outside or from an MS (MultiScript) takes about 3 times less processing than a NoteOn event, which means that it's still a lot of processing time, so this should be evaluated as well.
The good part, is that the 64 channel switching is made in the MS, so I'm not sending any extra info to K2, except for "in-script channel" info and noteoff velocity, but only when needed.

About _load_patch, the syntax should be "c:/my folder/my instrument.nki", it will show only the file title instead of the full path when using backslash.

Anyway, this stuff looks really nice, at least for me as my goal would be to control K2 using either my own interface or some scripting to load/unload instruments on the fly, adding removing fx. Instead of creating a bunch of similar instruments, loading always the same one and sending over some CC to configure it from the host.

Btw, to have my instruments load in less than 2 seconds, I made a little app that loads the beginning of each samples from the instruments I use the most (system cache). I do that when booting my machine (coffee and mails time).
But this is not possible with protected libs (monolith). Now with MS, it should be possible to create a little app that changes the DFD settings, loads K2, loading an instrument in 1 or 2 slots at a time, and when done, closing K2 and setting back dfd to normal. K2 can not make use of my 4 GB of RAM but the windows system cache does 

And in case the spy from NI is hanging around here, please give us or tell us a way to load a script into any slot using MultiScripts and a param for script bypass.
:wink: 

Cheers,
Marc


----------



## mbncp (Sep 2, 2007)

Hi Bob,

Indeed, I'm really happy with these new toys. I can now select any patch on my drives by sending a Bank+Patch change from the sequencer. Your script will be handy to deal with the controller assignement.

Too bad we can't send "K2 NRPNs" from a multiscript. What would be neat is that each script has it's own NRPN, instead of a fix or selectable CC.
Then I could assign one of my "live" controllers (mod wheel, breath controller, CC foot pedals, ...) to any script parameter from the sequencer or the keyboard, the multiscript dealing with the mapping.

It's funny, less I'm sleeping, more I'm dreaming :wink: 

Cheers,
Marc


----------

