# Multi script and Instrument Midi Channels?



## Tod (Mar 17, 2017)

I'm just wondering if and instrument's midi channel can be set with a multi script?

If so, please point me in the right dierction.


----------



## EvilDragon (Mar 17, 2017)

Nope, but MIDI data can be rerouted.


----------



## Tod (Mar 17, 2017)

Okay, thanks Mario, I was afraid of that.

So is it possible then to route the midi data to more than one midi channel at the same time?


----------



## Levitanus (Mar 17, 2017)

Tod said:


> So is it possible then to route the midi data to more than one midi channel at the same time?


yep. And you can use $MIDI_CHANNEL inside of instrment script as well as in the multi


----------



## Tod (Mar 17, 2017)

Thanks Levitanus, good suggestion, I never thought about that, I'll have to check that out.


----------



## Levitanus (Mar 17, 2017)

Don't forget to switch instrument chanel to omni


----------



## Tod (Mar 18, 2017)

Okay, I'm having a hard time getting this. What are the commands to send data coming in on one channel so that the data will also go out to other channels?

For example, using "on midi_in", how do I send the incoming midi events to channel 1, 2, and 3?


----------



## EvilDragon (Mar 18, 2017)

Use the set_midi() command, KSP reference explains it pretty simply.


----------



## Tod (Mar 18, 2017)

Thanks Mario, I figured that and tried it, but I'm not sure of the correct parameters to use. of course I want to send all event, but what do I use for "command" and the two byts?

set_midi(MIDI_CHANNEL+1,<command>,byt1,byt2)


----------



## neblix (Mar 18, 2017)

You can just pass the same command, and the same two bytes, as the midi event that triggered the callback.

These are directly accessible as variables similar to EVENT_NOTE and EVENT_VELOCITY. They are:

MIDI_COMMAND
MIDI_BYTE_1
MIDI_BYTE_2

So think of
set_midi(MIDI_CHANNEL+1, MIDI_COMMAND, MIDI_BYTE_1, MIDI_BYTE_2)

as similar to
play_note(EVENT_NOTE, EVENT_VELOCITY, 0, -1)

You're just using the information about the event which is already available and passing it right through.

The manual does explain and list out, however, how to put in your own data for these things, instead of simply passing them along, so I encourage you to read up to learn what more things you can do.


----------



## Tod (Mar 18, 2017)

Thanks Nabeel, but that's exactly what I've tried, and for some reason it's not working.

set_midi(MIDI_CHANNEL+1,MIDI_COMMAND,MIDI_BYTE_1,MIDI_BYTE_2)

I'm sending on midi channel 1 and I'm using an " if ($MIDI_CHANNEL = 1)".

```
if ($MIDI_CHANNEL = 1)
    set_midi(MIDI_CHANNEL+1,MIDI_COMMAND,MIDI_BYTE_1,MIDI_BYTE_2)
    message ("MidiCh+1 = " & MIDI_CHANNEL+1 & "   $MIDI_COMMAND = " & $MIDI_COMMAND & "  Byt1:" & MIDI_BYTE_1 &  "  Byt2:" & MIDI_BYTE_2)
end if
```

According to the message it definitely going through the "if".

Also I'm a little confused about the midi channels, are they not zero based? I'm sending Kontakt channel 1 from Reaper and the script is responding to it as channel "1" not "0".


----------



## EvilDragon (Mar 18, 2017)

MIDI channels _are _zero based.

Your instrument needs to be set to "omni" to recognize other channels coming, naturally (as was mentioned above).


----------



## Tod (Mar 18, 2017)

Humm, how is that going to work Mario, if I set all the instruments to "omni" they'll all play all the time, wont they?

Regarding the midi channel, I'm sending channel 1 from Reaper, but using "message ("Chan = " & $MIDI_CHANNEL)", and it's showing "Chan = 1", shouldn't it be "Chan = 0"?

Sorry Mario, I don't mean to bug yah, but this is getting more confusing as I go.


----------



## EvilDragon (Mar 18, 2017)

You're printing out $MIDI_CHANNEL+1, not $MIDI_CHANNEL.


----------



## Tod (Mar 18, 2017)

Oh no, when I use $MIDI_CHANNEL+1 I get "2'.

What about the omni thingy Mario, maybe what I want to do can't be done?


----------



## EvilDragon (Mar 18, 2017)

If you're using Kontakt's MIDI monitor scripts, they automatically change the 0-based MIDI channel they receive into human-readable 1-based form.


I guess if you just want to send the MIDI input to a multitude of instruments, they don't have to be set to omni.


----------



## Tod (Mar 18, 2017)

Thanks again Mario, I'm just using a little multi script I started for testing things out. It's the "on midi_in" where I'm querying the midi channel, so that should be "zero" based then, right?

What I'm trying to do is put together a multi script for someone on the Reaper form. What they want to do is be able to have all they're articulations setup in an instance of K5 with different midi channels, but then they would like to be able to select 2 or 3 articulations to play together at the same time, using keyswitchs. They want to be able to do this in real time, with any combination.

What I've been doing is making simple little tests to see if this is doable, and since I haven't worked with these midi commands before, I'm finding it quite a task.


----------



## EvilDragon (Mar 19, 2017)

Your problem is then, if you want the script to respond to MIDI channel 1, then you have to query "if ($MIDI_CHANNEL = 0)", not 1.


----------



## Tod (Mar 19, 2017)

Okay, I'll give that a shot, and just thinking about I'm sure it will work.

What totally confused me is that when I queried the channel, it gave me channel "1". Oh well. 

Thanks again Mario, and everyone else who responded.


----------



## neblix (Mar 19, 2017)

i wrote the Jazz Horns Smart Voicing system which is a multi script that distributes generated harmony voices to loaded nki's on different MIDI channels.

So if what you're doing is anything like that or not nearly as ambitious, it can most certainly be done. I can give you detailed help in a sec.

EDIT:

Okay, so if you load 16 nki's, MIDI channel 1 through 16, those are your 16 articulations.

Once you load a multi script into Kontakt, Kontakt is now intercepting MIDI data through the multi script before it goes to the nki's. The caveat here is, you need to write "ignore_midi" in your on midi in callback, otherwise you'll be sending out your generated data, and also still passing in the MIDI data from the DAW.

It just gets messy, you want to block the nki's from being passed midi commands automatically and just generate them all yourself using a script.

Now I don't know how you're doing your keyswitches here, but what you'll want to do is, based on your keyswitch states, fill an "active" array, size 16. All 0's, and when MIDI channels are "turned on" using the keyswitch, set it to 1.

So my array would look like this in the beginning:
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]

Then I hit a couple keyswitches, maybe it looks like this:
[1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0]

If you're stuck on how to do this, you need to check if the note is in the keyswitch range, which you do something like in_range(MIDI_BYTE_1, 36, 48) or something (that example gives you an if condition for being between C1 and C2).

Now, when the midi command is a midi note and its not in the keyswitch range, but in the melody range, you simply loop through that active array, like;



```
for m := 0 to 15
    if %channels_active[m] = 1
        set_midi(m, MIDI_COMMAND_NOTE_ON, MIDI_BYTE_1, MIDI_BYTE_2)
    end if
end for
```

This is just a short example. You'll want to do a similar loop for the note off's as well.


----------



## Tod (Mar 19, 2017)

Thanks Nabeel, and yeah, I've got it pretty well figured out.

I decided to use a CC controller instead of keyswitchs, and I've got it to where I can turn all the channels on and off. Keyswitchs are difficult if you have to place them way at the bottom or top and I think the CC controller is less messy. 
Also my code for querying is just like what you show above.

I think I'm going to be fine, this is my first experience with this midi code, but now I have a better idea how to correlate what's in the manual and put it into practice.

Thanks again everyone.


----------



## Tod (Mar 20, 2017)

Hey my friends, I've come along nicely, but I've run into a little snag.

I want to turn all notes off on a certain channel but I haven't figured it out yet. I've tried:

set_midi(mx,$MIDI_COMMAND_NOTE_OFF,$ALL_EVENTS,$ALL_EVENTS)

but it doesn't work. "mx" is the channel number. Any ideas?

Heh heh, I've really learned a lot with this project and managed a lot of little bugs, but this one alludes me.


----------



## EvilDragon (Mar 20, 2017)

Multiscripts don't work with events, they work with MIDI messages. So forget about $ALL_EVENTS.

You need to loop through all 128 keys and send a note off like that. Or send CC123, which is all-notes-off (but the instruments need to support receiving this message, this is set in Instrument Options->Controllers).


----------



## Tod (Mar 20, 2017)

Wow, I thought of that and was trying to avoid it. Okay I'll check out the CC123 thingy, but since this is not for me, I may have to go with the loop.

Thanks Mario, I've said it before and I'll say it again I love yah.


----------



## EvilDragon (Mar 20, 2017)

How is it "not for you"? Instead of sending 128*number of channels MIDI events, you would set 16*one MIDI CC event. Much simpler.


----------



## Tod (Mar 20, 2017)

Sorry Mario, you misunderstood me, I meant the script is not for my own personal use. I suppose I could stipulate that to the user, that they should uncheck the "Controllers/Accept all notes off" in the Instrument Options.

I did put the loop together and it works fine, very fast, but you're right using one CC123 would be much better, so I'll do that.

Thanks again.


----------



## Tod (Mar 21, 2017)

Okay, it looks like Reaper doesn't have a CC123. Or am I missing something.


----------



## EvilDragon (Mar 21, 2017)

You cannot send it from piano roll, but it gets sent when you press stop in transport (provided that option is enabled in Preferences), or run action "Send all-notes-off to all MIDI outputs/plugins".

CCS 120-127 are special in MIDI specification, and they are not really something you're supposed to enter via piano roll (ReaControlMIDI offers it, though).


----------



## Tod (Mar 21, 2017)

Aah, okay, that makes sense and I think I actually new that. 

That puts me back to the loop, I need to turn off notes that overhang my CC switch that turns off the channels.

Thanks Mario.


----------



## ScoringFilm (Mar 22, 2017)

Don't forget that you need to add 'ignore_midi' if you don't want the midi data to pass through to the original channel.


----------



## Tod (Mar 22, 2017)

Thanks SF, and yes, I'm using that in a couple of places.


----------



## Tod (Mar 23, 2017)

A couple of more questons.

1. Is it possible to use custom graphics with multi scripts?

2. Is there any way to color switches and labels without custom graphics?


----------



## EvilDragon (Mar 23, 2017)

1. Yes. Although it is extremely hacky because resource containers aren't supported.

2. No.


----------



## Tod (Mar 23, 2017)

Okay thanks again Mario. As I think back I remember Bob telling me he preferred not to use custom graphics in the MS gui because it was a pain.


----------



## neblix (Mar 23, 2017)

NI doesn't support library-folder loading of graphics for multi scripts. They have to be in the My Documents folder, no exceptions.

When we released SA Jazz Horns we had to include "installation instructions" for copying the folder full of UI graphics to said folder. It looked really bad, but we did what we had to; that multi script was an important part of the package.


----------



## Tod (Mar 24, 2017)

Thanks Nabeel, I was wondering how it could be done. However, I'm not going to worry abut it, my script will survive fine without it.

I just wished there was a way to color the controls and labels, the two shades of grey are not very conducive for the available fonts.


----------

