Welcome to %s forums

BrainModular Users Forum

Login Register

Script midi out to another module input

I need help on a Patch
Post Reply
sm_jamieson
Member
Posts: 559
Contact:

Unread post by sm_jamieson » 01 Feb 2015, 03:13

Hi,
I have created a simple midi script which passes input to output. I have connected the script module's output to a midi filter module's input.
When I send midi to the script, the information panel shows midi messages on the script module input and output, so it is passing them through. But when I draw a "wire" between the script module's midi output and the midi filter module's input to pass midi from the script module to the midi filter, nothing is received on the midi filter's input. If the midi filter is selected so that its input is shown on the information panel, the input indicates "No Midi".
This does not make sense - how can the midi be present at one end of the "wire" and not present at the other end ?
Is this a bug in relation to passing midi from a script module to another type of module ?
This has stopped me in my tracks, since if this does not work my project is impossible !

My script is:

/////////////////////////
//
/////////////////////////
// parameters declaration
// midi script attempt

Var MidiIn : tParameter;
Var Midiout : tParameter;

// initialisation : create parameters
procedure init;
begin
MidiIn := CreateParam('Midi In', ptMidi);
SetIsOutput(MidiIn, false);
MidiOut := CreateParam('Midi Out', ptMidi);
SetIsInput(MidiOut, false);
end;

var i : integer;
var j : integer;
var nbOfMidi : integer;
var RcvdMidi : TMidi;

// Callback procedure
Procedure Callback(n:integer);
begin

end;

//////////////////////////////
// main proc
//////////////////////////////
Procedure Process;
begin
nbOfMidi := GetLength(MidiIn); // number of incoming messages

if nbOfMidi > 0 then begin
j := 0;
for i := 0 to nbOfMidi-1 do begin // loop for all input messages
GetMidiArrayValue(midiIn, i, RcvdMidi); // get this message
sTrace('recv msg ' + IntToStr(RcvdMidi.Msg));
SetMidiArrayValue(midiOut,j,RcvdMidi); // set output value
j = j + 1;
end;
SetLength(midiOut,j);
end
else SetLength(midiOut,0); // nothing received, set out length to 0
end;

Thanks,
Simon.

sephult
Member
Posts: 1144
Contact:

Unread post by sephult » 01 Feb 2015, 07:01

Hello sm_jamieson!


So it looks like you are doing the SetLength(midiOut,j) and it is being set at the wrong time...so what happens is within the if loop for sending the MIDI you are actually not specifying the size of the message until after you set the output. Probably why the reason you are seeing the actual notes, but not really getting the message out of the port. You need to specify the length of the message before you enter the loop. So you would do SetLength(midiOut,nbOfMidi) to make your output the size of the input;

BTW -The integer j and the increment shouldn't be needed since you specify the size by input (just left it in and noticed)
I modified your script for comparison, this should correct your problem:


/////////////////////////
//
/////////////////////////
// parameters declaration
// midi script attempt

Var MidiIn : tParameter;
Var Midiout : tParameter;

// initialisation : create parameters
procedure init;
begin
MidiIn := CreateParam('Midi In', ptMidi);
SetIsOutput(MidiIn, false);
MidiOut := CreateParam('Midi Out', ptMidi);
SetIsInput(MidiOut, false);
end;

var i : integer;
var j : integer;
var nbOfMidi : integer;
var RcvdMidi : TMidi;

// Callback procedure
Procedure Callback(n:integer);
begin

end;

//////////////////////////////
// main proc
//////////////////////////////
Procedure Process;
begin
nbOfMidi := GetLength(MidiIn); // number of incoming messages

if nbOfMidi > 0 then begin
j := 0;
SetLength(MidiOut,nbOfMidi);
for i := 0 to nbOfMidi-1 do begin // loop for all input messages
GetMidiArrayValue(midiIn, i, RcvdMidi); // get this message
sTrace('recv msg ' + IntToStr(RcvdMidi.Msg));
SetMidiArrayValue(midiOut,i,RcvdMidi); // set output value
j = j + 1;
end;

end
else SetLength(midiOut,0); // nothing received, set out length to 0
end;


-S
"Every act of creation is first an act of destruction." -Picasso

sephult
Member
Posts: 1144
Contact:

Unread post by sephult » 01 Feb 2015, 07:03

One of the biggest problems with MIDI inside a script was knowing where to set the length, and how and at what level of the loops is needed to set the length to cut it off. This took me awhile to get a handle on, however using the library script examples you can extract some comparative code to identify what is going on in comparison to your own scripting.

Hope this helps, let me know if you have any more questions or need help

-S
"Every act of creation is first an act of destruction." -Picasso

sephult
Member
Posts: 1144
Contact:

Unread post by sephult » 01 Feb 2015, 07:42

Here are some other scripts I made awhile back I use as well, hopefully you can find some use or comparison as well.
The first one is just a MIDI Thru that only processes MIDI ON/OFF messages.
The second one is an example of a router/switch/selector for determining paths based on an input. Be careful though as switching the output during a note will leave a hanging note if the note off message is not in the right path.

Hopefully here soon I will be adding a mass of add-ons and useful tools - I have been building :)

//////////////////////////
// MIDI Thru - Note On/Off Only
// By Sephult 11/26/14
/////////////////////////
/////////////////////////////////////////////////////////
//PARAMETERS DECLARATION
///////////////////////////////////////////////////////
var MidiIn : Tparameter;
var MidiOut : Tparameter;

/////////////////////////////////////////////////////////
//Initialization
///////////////////////////////////////////////////////
procedure init;
Begin
MidiIn := CreateParam('In',ptMidi);
SetIsOutput(MidiIn,false);
MidiOut := CreateParam('Out',ptMidi);
SetIsInput(MidiOut,false);

End;

/////////////////////////////////////////////////////////
//GLOBAL VARIABLES
///////////////////////////////////////////////////////
var i,cnt : integer;
var lngthMidi : integer;
var ReceivedMidi : TMidi;

/////////////////////////////////////////////////////////
//MAIN PROCEDURE
///////////////////////////////////////////////////////
procedure process;
Begin

lngthMidi := GetLength(MidiIn);
if lngthMidi > 0
then begin
cnt := 0;
for i := 0 to lngthMidi-1
do begin
GetMidiArrayValue(MidiIn,i,ReceivedMidi);
if ((ReceivedMidi.msg = 128) or (ReceivedMidi.msg = 144))
then begin
inc(cnt);
SetLength(MidiOut,cnt);
SetMidiArrayValue(MidiOut,cnt-1,ReceivedMidi);
end;
end;
end
else SetLength(MidiOut,0);

End;



--------------------------------------------------------------------------------------------------------

//////////////////////////
// MIDI Router - Note On/Off Only
// By Sephult 11/26/14
/////////////////////////
/////////////////////////////////////////////////////////
//PARAMETERS DECLARATION
///////////////////////////////////////////////////////
var MidiIn : Tparameter;
var MidiOut : Tparameter;
var MidiOut2 : Tparameter;
var Selector : Tparameter;

/////////////////////////////////////////////////////////
//Initialization
///////////////////////////////////////////////////////
procedure init;
Begin
MidiIn := CreateParam('In',ptMidi);
SetIsOutput(MidiIn,false);
MidiOut := CreateParam('Out 1',ptMidi);
SetIsInput(MidiOut,false);
MidiOut2:= CreateParam('Out 2',ptMidi);
SetIsInput(MidiOut2,false);
Selector:= CreateParam('Selector',ptSwitch);
SetIsOutput(Selector,false);
End;

/////////////////////////////////////////////////////////
//GLOBAL VARIABLES
///////////////////////////////////////////////////////
var i,cnt : integer;
var lngthMidi : integer;
var ReceivedMidi : TMidi;
var Choice : integer;

/////////////////////////////////////////////////////////
//MAIN PROCEDURE
///////////////////////////////////////////////////////
procedure process;
Begin
Choice := round(getValue(Selector));

lngthMidi := GetLength(MidiIn);
if lngthMidi > 0
then begin
cnt := 0;
for i := 0 to lngthMidi-1
do begin
GetMidiArrayValue(MidiIn,i,ReceivedMidi);
if ((ReceivedMidi.msg = 128) or (ReceivedMidi.msg = 144))
then begin
if Choice = 0 then begin
inc(cnt);
SetLength(MidiOut,cnt);
SetMidiArrayValue(MidiOut,cnt-1,ReceivedMidi);
end
else begin
inc(cnt);
SetLength(MidiOut2,cnt);
SetMidiArrayValue(MidiOut2,cnt-1,ReceivedMidi);
end;
end;
end;
end
else begin
SetLength(MidiOut,0);
SetLength(MidiOut2,0);
end;
End;
"Every act of creation is first an act of destruction." -Picasso

sm_jamieson
Member
Posts: 559
Contact:

Unread post by sm_jamieson » 01 Feb 2015, 15:47

Wow thanks for the quick response guys. That has done the trick. I might as well explain what I am doing. I am scripting a midi controller that takes a single midi channel as input and splits this over a number of keyboard zones on different midi channels. The features:
1. Zones or splits over the keyboard, assigned by playing notes
2. "Soft zones", i.e. the note velocities are faded out over an octave instead of a sudden cut - useful for blending in strings over part of the keyboard
3. Zone fade-in, switch the zone on or off and it fades in and out automatically over a few seconds - useful for smooth solo playing
4. Program selection and fader per zone
5. Program changes (for multitimbral instruments) allowing held notes to continue, using two midi channels to implement this
6. Anything else I wished I had in a keyboard controller and never did !
If such a thing has already been produced for Usine, please let me know.

One graphical component that seems to be missing: a piano keyboard widget that can be played, can indicate incoming midi by lighting up the notes, and that can also indicate keyboard zones by different coloured keys. If nothing like that is available I might have to tackle the Usine intermediate language, since I think doing that in a script might not be very efficient.

Thanks,
Simon.

sephult
Member
Posts: 1144
Contact:

Unread post by sephult » 01 Feb 2015, 16:44

Hello,

Very cool ideas, I had worked some MIDI tools as well. One that I have implemented is a small Octave selector that detects the incoming midi by octave and allows you to Filter by Octave and transpose by octave. This lets you remap them across the keyboard easily, essentially letting you play bass in X8 zone, while highs in X3 zone.

Right now I am working on a new Chord/Harmonizer which is pretty well implemented, however a friend of mine is working some details for progressions and we have a huge chord list trying to make efficient. Essentially like a Harmonizer version 3 module but much more detail, and custom chords. For specifying the chords by note, etc... I used different colored comboboxes vertical for the keyboard layout.


If you would like some help, I definitely would love too, whether it's scripting functionality, testing, or implementing the key gui.
Hopefully can help teach, and learn together....and build awesome tools!

-S
"Every act of creation is first an act of destruction." -Picasso

sm_jamieson
Member
Posts: 559
Contact:

Unread post by sm_jamieson » 01 Feb 2015, 17:55

sephult wrote:Hello,

Very cool ideas, I had worked some MIDI tools as well. One that I have implemented is a small Octave selector that detects the incoming midi by octave and allows you to Filter by Octave and transpose by octave. This lets you remap them across the keyboard easily, essentially letting you play bass in X8 zone, while highs in X3 zone.

Right now I am working on a new Chord/Harmonizer which is pretty well implemented, however a friend of mine is working some details for progressions and we have a huge chord list trying to make efficient. Essentially like a Harmonizer version 3 module but much more detail, and custom chords. For specifying the chords by note, etc... I used different colored comboboxes vertical for the keyboard layout.


If you would like some help, I definitely would love too, whether it's scripting functionality, testing, or implementing the key gui.
Hopefully can help teach, and learn together....and build awesome tools!

-S
Hi - its good to see an active community on here.
The thing that would be most useful is a keyboard widget, and I'm sure many people would use it. It would be fairly easy to create a row of boxes (I've seen the single octave keyboard in the dowloads section), but a proper layout with black keys would need proper graphics programming integrated with Usine. As far as I know, Usine is not open source, but there is the IML language. Perhaps an official feature request to Usine ?

The other thing I was surprised that was not built into Usine is a midi splitter (not confused with the midi message split function). There is midi mapper and filter modules, etc, but nothing to duplicate messages on one channel onto others. You could do it with a set of filters and mappers, but that would be rather clumsy.

Anyway, good luck with your stuff. I will post back my project when its working properly.

Simon.

sephult
Member
Posts: 1144
Contact:

Unread post by sephult » 02 Feb 2015, 09:07

So the Piano I just integrated with decent graphics. At the moment its just a single octave, but looks pretty good.
Has option for Dynamic or Fixed Length play (mouse down, until release for Note off, or set length single trigger).

Anything more specific for a keyboard widget you are looking for that I can add? You said possibly one that lit up in response as well, I will look into that.

MIDI splitter is actually quite easy to do, I believe I have one in a few patches.

Just take your script above and add the Tparameters for the additional output ports you want, and in the INIT section as well.

Just set their lengths for all before the loop, and add each one within the loop to set the output...... like
SetMidiArrayValue(midiOut,i,RcvdMidi), SetMidiArrayValue(midiOut2,i,RcvdMidi), etc...

Finally at the end of the loop make sure to set each length of the ports to zero to complete the message, and prepare for the next.

Then you should have an easy scripted splitter. However since HollyHock is a modular system you don't necessarily need a splitter as you can always wire to multiple nodes. If you want multiple channels, you could easily use a transform module within a subpatch and change the channel through that. That is probably the intention as to why there is no specific splitter module.

If you are saying you want to split to separate channels that is fairly easy to do as well within a script.
The channel message resides in the Tmidi like your var RcvdMidi : TMidi you declared.

You would just reference like RcvMidi.channel = 12 to set the channel to 12, and when you output it will set the channel byte to 12.


-S
"Every act of creation is first an act of destruction." -Picasso

sm_jamieson
Member
Posts: 559
Contact:

Unread post by sm_jamieson » 02 Feb 2015, 12:20

sephult wrote:So the Piano I just integrated with decent graphics. At the moment its just a single octave, but looks pretty good.
Has option for Dynamic or Fixed Length play (mouse down, until release for Note off, or set length single trigger).

Anything more specific for a keyboard widget you are looking for that I can add? You said possibly one that lit up in response as well, I will look into that.

MIDI splitter is actually quite easy to do, I believe I have one in a few patches.

Just take your script above and add the Tparameters for the additional output ports you want, and in the INIT section as well.

Just set their lengths for all before the loop, and add each one within the loop to set the output...... like
SetMidiArrayValue(midiOut,i,RcvdMidi), SetMidiArrayValue(midiOut2,i,RcvdMidi), etc...

Finally at the end of the loop make sure to set each length of the ports to zero to complete the message, and prepare for the next.

Then you should have an easy scripted splitter. However since HollyHock is a modular system you don't necessarily need a splitter as you can always wire to multiple nodes. If you want multiple channels, you could easily use a transform module within a subpatch and change the channel through that. That is probably the intention as to why there is no specific splitter module.

If you are saying you want to split to separate channels that is fairly easy to do as well within a script.
The channel message resides in the Tmidi like your var RcvdMidi : TMidi you declared.

You would just reference like RcvMidi.channel = 12 to set the channel to 12, and when you output it will set the channel byte to 12.


-S
Hi sephult.

I get the point about being able to wire up modules to achieve almost anything really. I think the manual says sometimes this can get inefficient, but we have scripting to fix that.

Where can I find your single octave keyboard module ?

My requirements for a perfect graphical keyboard module would include:

1. Have a midi input and be able to display the midi input key presses graphically (selectable colour for note down). Probably one selectable channel for input, but imagine being able to display different key channels in different colours !

2. Have a midi output with selectable midi channel, that can be played using mouse or touch screen (different selectable colour for note down)

3. Be able to indicate key presses and incoming midi at the same time, also a midi thru that can merge played notes into the midi stream.

3. Some way of indicating several possibly overlapping key zones, graphically overlayed on the keyboard, that accurately indicate the start and end keys, even if they are black notes. Key zones to be set from an incoming data bus (so you can have start of zone and end of zone faders), and set or modified by a mouse or touch screen by dragging the ends of the zones.

I can't think of anything else for now. I know its a lot of features !

Simon.

sm_jamieson
Member
Posts: 559
Contact:

Unread post by sm_jamieson » 03 Feb 2015, 00:15

sm_jamieson wrote:Hi sephult.

I get the point about being able to wire up modules to achieve almost anything really. I think the manual says sometimes this can get inefficient, but we have scripting to fix that.

Where can I find your single octave keyboard module ?

My requirements for a perfect graphical keyboard module would include:

1. Have a midi input and be able to display the midi input key presses graphically (selectable colour for note down). Probably one selectable channel for input, but imagine being able to display different key channels in different colours !

2. Have a midi output with selectable midi channel, that can be played using mouse or touch screen (different selectable colour for note down)

3. Be able to indicate key presses and incoming midi at the same time, also a midi thru that can merge played notes into the midi stream.

3. Some way of indicating several possibly overlapping key zones, graphically overlayed on the keyboard, that accurately indicate the start and end keys, even if they are black notes. Key zones to be set from an incoming data bus (so you can have start of zone and end of zone faders), and set or modified by a mouse or touch screen by dragging the ends of the zones.

I can't think of anything else for now. I know its a lot of features !

Simon.
OK, well I have just discovered range faders, which are more or less what is needed to indicate keyboard ranges. I don't know if they can be transparent and overlayed onto a keyboard widget, but that the type of thing I was thinking of anyway.

Simon.

sephult
Member
Posts: 1144
Contact:

Unread post by sephult » 03 Feb 2015, 02:26

Yep that was where I was going for the Zone control. I started an overlayed Piano Graphic on shapes for the colors.
I have ran into some issues regarding mouse-down messages and I have a report I am going to send in.

As far as triggering the colors yes the concept works and I am looking into ways to implement. Ill keep you updated.
Maybe can use as a tutorial to help you too

-S
"Every act of creation is first an act of destruction." -Picasso

sm_jamieson
Member
Posts: 559
Contact:

Unread post by sm_jamieson » 04 Feb 2015, 12:48

I looked at the range faders yesterday. They look good, but the display of captions and values is a bit strange. The caption is overlayed on the "range" section of the fader rather than the whole fader, so if the caption is longer than the range section, some of it is obscured.
Also, the start and end range values are only displayed when the fader is being moved. So you'd probably have to overlay the text and just use the faders as a graphic.
Simon.

Post Reply

Who is online

Users browsing this forum: No registered users and 26 guests