Welcome to %s forums

BrainModular Users Forum

Login Register

Help and improvment of the "array to midi" script

I need help on a Patch
Post Reply
ethnix73
Member
Posts: 604
Location: France, Caen
Contact:

Unread post by ethnix73 » 20 Nov 2010, 18:41

I'm always a noob script but i would like to use this script found in the matrix pack.

I want to use it with my launchpad patch, but i'm really enable to modify it...

Is there any script guru who could help me to add velocity and note lenght to this script?

Code: Select all

//////////////////////////
// 
/////////////////////////
// parameters declaration
var RowIn        : Tparameter;
var OnModeIn     : Tparameter;
var OffModeIn    : Tparameter;
var BaseOctaveIn : Tparameter;
var TickIn       : Tparameter;
var MidiOut      : Tparameter;

var BaseOctave      : integer;
var NbOfMidiNotes   : integer;
var OnMode          : integer;
var OffMode         : integer;
var PlayNotes       : boolean;
var CurrentNotes    : array of single;
var CurrentNotesLen : integer;
var LastNotes       : array of single;

CONST MID_NOTE_ON   = 144;
CONST MID_VOL_RANGE = 127;

CONST OCTAVE_RANGE  = 12;
CONST ON_MODE       = '"each","group"';
CONST OFF_MODE      = '"hold","cut"';
 
// initialisation : create parameters
procedure init;
begin  
 
 RowIn := CreateParam('row in',ptArray);
 SetIsOutput(RowIn,false);
 
 OnModeIn := CreateParam('on mode',ptListBox);
 SetIsOutput(OnModeIn,false);
 SetListBoxString(OnModeIn,ON_MODE);
 
 OffModeIn := CreateParam('off mode',ptListBox);
 SetIsOutput(OffModeIn,false);
 SetListBoxString(OffModeIn,OFF_MODE);
 
 BaseOctaveIn := CreateParam('octave',ptDataFader);
 SetIsOutput    (BaseOctaveIn,false);
 SetMin	        (BaseOctaveIn , 1);  
 SetMax	        (BaseOctaveIn , 10); 
 SetDefaultValue(BaseOctaveIn , 5); 
 SetFormat      (BaseOctaveIn , '%.0f'); 
 
 TickIn := CreateParam('tick',ptButton);
 SetIsOutput(RowIn,false);
 
 MidiOut := CreateParam('midi out',ptMidi);
 SetIsInput(MidiOut,false);

 BaseOctave := 5;
 NbOfMidiNotes := 0;
 OnMode := 0;
 OffMode := 0;
 PlayNotes := FALSE;
 SetArrayLength(CurrentNotes , 0);
 CurrentNotesLen := 0;
end;

// Global variables
var Miditmp      : TMidi;

//////////////////////////////
// callback proc
//////////////////////////////
procedure Callback(n:integer);
var i : integer;
var vol : single;
begin
    if (n = RowIn) then begin
        CurrentNotesLen := GetLength(RowIn);

        SetArrayLength(CurrentNotes , CurrentNotesLen);
        SetArrayLength(LastNotes , CurrentNotesLen);
        i := 0;
        while i < CurrentNotesLen  do begin
            
            vol &#58;= GetDataArrayValue&#40;RowIn, i&#41;;
            CurrentNotes&#91;i&#93; &#58;= vol;     
            i &#58;= i+1;
        end;
    end
    else if &#40;n = OnModeIn&#41; then begin
        OnMode &#58;= round&#40; GetValue&#40;OnModeIn&#41; &#41;;
    end
    else if &#40;n = OffModeIn&#41; then begin
        OffMode &#58;= round&#40; GetValue&#40;OffModeIn&#41; &#41;;
    end
    else if &#40;n = BaseOctaveIn&#41; then begin
        BaseOctave &#58;= round&#40; GetValue&#40;BaseOctaveIn&#41; &#41;;
    end
    else if &#40;n = TickIn&#41; then begin
        
        NbOfMidiNotes &#58;= 0; 
        
        i &#58;= 0;
        while i < CurrentNotesLen  do begin

            if &#40;&#40;OnMode = 1&#41; and  &#40;CurrentNotes&#91;i&#93; <> LastNotes&#91;i&#93;&#41; and  &#40;CurrentNotes&#91;i&#93; > 0&#41;&#41;
            or &#40;&#40;OnMode = 0&#41; and  &#40;CurrentNotes&#91;i&#93; > 0&#41;&#41;
            or &#40;&#40;OffMode = 1&#41; and  &#40;CurrentNotes&#91;i&#93; = 0&#41;&#41;
            then begin
                Miditmp.Channel &#58;= byte&#40;1&#41;;
                Miditmp.Msg &#58;= MID_NOTE_ON;
                Miditmp.Data1 &#58;= byte&#40; &#40;BaseOctave * OCTAVE_RANGE&#41; + i&#41;;
                Miditmp.Data2 &#58;= round&#40;MID_VOL_RANGE * CurrentNotes&#91;i&#93;&#41;;

                SetMidiArrayValue&#40;MidiOut, NbOfMidiNotes ,Miditmp&#41;;  // set output value
                NbOfMidiNotes &#58;= NbOfMidiNotes + 1;
            end; 
            LastNotes&#91;i&#93; &#58;= CurrentNotes&#91;i&#93;;    
            i &#58;= i+1;
        end;
        SetLength&#40;MidiOut,NbOfMidiNotes&#41;; 
        PlayNotes &#58;= TRUE;
    end;
end;


//////////////////////////////
// main proc
//////////////////////////////
Procedure Process;
var i &#58; integer;
var len &#58; integer;
var vol &#58; single;
begin
    if PlayNotes then  begin
        PlayNotes &#58;= FALSE;
    end
    else begin
        SetLength&#40;MidiOut,0&#41;;
    end;
end;
Seb.Dub

23fx23
Member
Posts: 2545
Contact:

Unread post by 23fx23 » 21 Nov 2010, 15:43

mm it 's strange caus it seems it was coded in,

i still fight a bit with midi and script, but ill try to have a look tonight.

but if martin watch i thinks this one is from him.

martignasse
Site Admin
Posts: 611
Location: Lyon, FRANCE
Contact:

Unread post by martignasse » 24 Nov 2010, 00:15

hi ethnix73,

arf, it's a pretty tricky script you try to custom here :rolleyes: (the hard way to learn script...23fx23 is kind of unique about learning curve;) )

anyway, if i remember correctly, we speak about the 'arr to midi' script of the 'matrix_fall_seq_example'

the note length is just a matter of note on and note off time laps.
in this script, 'on mode' and 'off mode' trigger when we should fire a note on and a note off, finally, it's processed in the 'else if (n = TickIn) then begin' section.

velocity, isn't triggered in this script, but i believe it's just a matter of multiplying the volume by the velocity (i'm not a midi master...)

hope it help
Martin FLEURENT - Usine Developer - SDK maintainer

23fx23
Member
Posts: 2545
Contact:

Unread post by 23fx23 » 24 Nov 2010, 00:47

mmm now i think i remember im pretty sure i already moded it to add velocity in my MX_zoom_sequencer patch, gonna check it now

edit: mmm yes it seems, maybe try this one:

Code: Select all

//////////////////////////
// 
/////////////////////////
// parameters declaration
var RowIn        &#58; Tparameter;
var OnModeIn     &#58; Tparameter;
var OffModeIn    &#58; Tparameter;
var BaseOctaveIn &#58; Tparameter;
var TickIn       &#58; Tparameter;
var MidiOut      &#58; Tparameter;

var BaseOctave      &#58; integer;
var NbOfMidiNotes   &#58; integer;
var OnMode          &#58; integer;
var OffMode         &#58; integer;
var PlayNotes       &#58; boolean;
var CurrentNotes    &#58; array of single;
var CurrentNotesLen &#58; integer;
var LastNotes       &#58; array of single;

CONST MID_NOTE_ON   = 144;
CONST MID_NOTE_OFF  = 128;
CONST MID_VOL_RANGE = 127;

CONST OCTAVE_RANGE  = 12;
CONST ON_MODE       = '"each","group"';
CONST OFF_MODE      = '"hold","cut"';
 
// initialisation &#58; create parameters
procedure init;
begin  
 
 RowIn &#58;= CreateParam&#40;'row in',ptArray&#41;;
 SetIsOutput&#40;RowIn,false&#41;;
 
 OnModeIn &#58;= CreateParam&#40;'on mode',ptListBox&#41;;
 SetIsOutput&#40;OnModeIn,false&#41;;
 SetListBoxString&#40;OnModeIn,ON_MODE&#41;;
 
 OffModeIn &#58;= CreateParam&#40;'off mode',ptListBox&#41;;
 SetIsOutput&#40;OffModeIn,false&#41;;
 SetListBoxString&#40;OffModeIn,OFF_MODE&#41;;
 
 BaseOctaveIn &#58;= CreateParam&#40;'octave',ptDataFader&#41;;
 SetIsOutput    &#40;BaseOctaveIn,false&#41;;
 SetMin	        &#40;BaseOctaveIn , 1&#41;;  
 SetMax	        &#40;BaseOctaveIn , 10&#41;; 
 SetDefaultValue&#40;BaseOctaveIn , 5&#41;; 
 SetFormat      &#40;BaseOctaveIn , '%.0f'&#41;; 
 
 TickIn &#58;= CreateParam&#40;'tick',ptButton&#41;;
 SetIsOutput&#40;RowIn,false&#41;;
 
 MidiOut &#58;= CreateParam&#40;'midi out',ptMidi&#41;;
 SetIsInput&#40;MidiOut,false&#41;;

 BaseOctave &#58;= 5;
 NbOfMidiNotes &#58;= 0;
 OnMode &#58;= 0;
 OffMode &#58;= 0;
 PlayNotes &#58;= FALSE;
 SetArrayLength&#40;CurrentNotes , 0&#41;;
 CurrentNotesLen &#58;= 0;
end;

// Global variables
var Miditmp      &#58; TMidi;

//////////////////////////////
// callback proc
//////////////////////////////
procedure Callback&#40;n&#58;integer&#41;;
var i &#58; integer;
var vol &#58; single;
begin
    if &#40;n = RowIn&#41; then begin
        CurrentNotesLen &#58;= GetLength&#40;RowIn&#41;;

        SetArrayLength&#40;CurrentNotes , CurrentNotesLen&#41;;
        SetArrayLength&#40;LastNotes , CurrentNotesLen&#41;;
        i &#58;= 0;
        while i < CurrentNotesLen  do begin
            
            vol &#58;= GetDataArrayValue&#40;RowIn, i&#41;;
            CurrentNotes&#91;i&#93; &#58;= vol;     
            i &#58;= i+1;
        end;
    end
    else if &#40;n = OnModeIn&#41; then begin
        OnMode &#58;= round&#40; GetValue&#40;OnModeIn&#41; &#41;;
    end
    else if &#40;n = OffModeIn&#41; then begin
        OffMode &#58;= round&#40; GetValue&#40;OffModeIn&#41; &#41;;
    end
    else if &#40;n = BaseOctaveIn&#41; then begin
        BaseOctave &#58;= round&#40; GetValue&#40;BaseOctaveIn&#41; &#41;;
    end
    else if &#40;n = TickIn&#41; then begin
        
        NbOfMidiNotes &#58;= 0; 
        
        i &#58;= 0;
        while i < CurrentNotesLen  do begin

            if &#40;&#40;OnMode = 1&#41; and  &#40;CurrentNotes&#91;i&#93; <> LastNotes&#91;i&#93;&#41; and  &#40;CurrentNotes&#91;i&#93; > 0&#41;&#41;
            or &#40;&#40;OnMode = 0&#41; and  &#40;CurrentNotes&#91;i&#93; > 0&#41;&#41;
            or &#40;&#40;OffMode = 1&#41; and  &#40;CurrentNotes&#91;i&#93; = 0&#41;&#41;
            then begin
                Miditmp.Channel &#58;= byte&#40;1&#41;;
                 if currentNotes&#91;i&#93;>0 then begin
                    Miditmp.Msg &#58;= MID_NOTE_ON;
                    end
                    else begin
                    Miditmp.Msg &#58;= MID_NOTE_OFF;
                    end;
                Miditmp.Data1 &#58;= byte&#40; &#40;BaseOctave * OCTAVE_RANGE&#41; + i&#41;;
                Miditmp.Data2 &#58;= round&#40;MID_VOL_RANGE * CurrentNotes&#91;i&#93;&#41;;

                SetMidiArrayValue&#40;MidiOut, NbOfMidiNotes ,Miditmp&#41;;  // set output value
                NbOfMidiNotes &#58;= NbOfMidiNotes + 1;
            end; 
            LastNotes&#91;i&#93; &#58;= CurrentNotes&#91;i&#93;;    
            i &#58;= i+1;
        end;
        SetLength&#40;MidiOut,NbOfMidiNotes&#41;; 
        PlayNotes &#58;= TRUE;
    end;
end;


//////////////////////////////
// main proc
//////////////////////////////
Procedure Process;
var i &#58; integer;
var len &#58; integer;
var vol &#58; single;
begin
    if PlayNotes then  begin
        PlayNotes &#58;= FALSE;
    end
    else begin
        SetLength&#40;MidiOut,0&#41;;
    end;
end;

ethnix73
Member
Posts: 604
Location: France, Caen
Contact:

Unread post by ethnix73 » 24 Nov 2010, 00:49

Thanks for your answer martignasse,

I will have a look, and make some try even if it's a hard way...
Anyway, learning script becomes more and more essential, so i will start with this one because i need it :)
Seb.Dub

ethnix73
Member
Posts: 604
Location: France, Caen
Contact:

Unread post by ethnix73 » 24 Nov 2010, 00:53

yeah!

Thanks marvellous 23fx23!

I will try it on tomorrow morning...
Seb.Dub

23fx23
Member
Posts: 2545
Contact:

Unread post by 23fx23 » 24 Nov 2010, 01:23

@martin thx for wise wordz, but i started on much simpler thingz :)

@ethnix: note there is no lenght setting here but velocity should be ok as i can see it clicking on wire,

Also, it would need to be optimized by checking only the needed midi events and set the midiarray out of that size. actually, it is constantly of the row size, wich is probably ok for a 8x matrix, (i tested on a 32xok) but could be problematic with bigger matrixes
and could be a tiny lower cpu with optimized code.

Note lengh is another much harder challenge at it implies dealing with time variable internally, and ideally in a polyphonic way,
mean keep a track of wich notes were on, trig time counters for each ect. but i would also love to make a mx sequencer with two XY variables, one for velocity and one for lengh. think that's a pretty much harder scripting challenge, still possible.

I was thinking from a while of a different should be easier technique, instead of dealing midi inside the scripts, matrix would
remote the pianoroll, entering notes, length and velocity and so pianoroll would handle the midi playing , being able to save
or recall sequences, finer later editing ect without bothering complex scripting.
It should be pretty doable if olivier manage to make the events array in possible to receive infos ans spread the notes.

ethnix73
Member
Posts: 604
Location: France, Caen
Contact:

Unread post by ethnix73 » 24 Nov 2010, 10:18

Thanks 23fx23,

First step with velocity (MidVolRange) inlet is done...

:)

Code: Select all

//////////////////////////
// 
/////////////////////////
// parameters declaration
var RowIn         &#58; Tparameter;
var OnModeIn      &#58; Tparameter;
var OffModeIn     &#58; Tparameter;
var MidVolRangeIn &#58; Tparameter;
var BaseOctaveIn  &#58; Tparameter;
var TickIn        &#58; Tparameter;
var MidiOut       &#58; Tparameter;

var BaseOctave      &#58; integer;
var NbOfMidiNotes   &#58; integer;
var OnMode          &#58; integer;
var OffMode         &#58; integer;
var PlayNotes       &#58; boolean;
var CurrentNotes    &#58; array of single;
var CurrentNotesLen &#58; integer;
var LastNotes       &#58; array of single;
var MidVolRange     &#58; integer;

CONST MID_NOTE_ON   = 144;
CONST MID_NOTE_OFF  = 128;

CONST OCTAVE_RANGE  = 12;
CONST ON_MODE       = '"each","group"';
CONST OFF_MODE      = '"hold","cut"';
 
// initialisation &#58; create parameters
procedure init;
begin  
 
 RowIn &#58;= CreateParam&#40;'row in',ptArray&#41;;
 SetIsOutput&#40;RowIn,false&#41;;
 
 MidVolRangeIn &#58;= CreateParam&#40;'MidVolRange',ptDataFader&#41;;
 SetIsOutput &#40;MidVolRangeIn,false&#41;;
 SetMin           &#40;MidVolRangeIn , 0&#41;;
 SetMax           &#40;MidVolRangeIn , 127&#41;;
 SetDefaultValue   &#40;MidVolRangeIn , 64&#41;;

 OnModeIn &#58;= CreateParam&#40;'on mode',ptListBox&#41;;
 SetIsOutput&#40;OnModeIn,false&#41;;
 SetListBoxString&#40;OnModeIn,ON_MODE&#41;;
 
 OffModeIn &#58;= CreateParam&#40;'off mode',ptListBox&#41;;
 SetIsOutput&#40;OffModeIn,false&#41;;
 SetListBoxString&#40;OffModeIn,OFF_MODE&#41;;
 
 BaseOctaveIn &#58;= CreateParam&#40;'octave',ptDataFader&#41;;
 SetIsOutput    &#40;BaseOctaveIn,false&#41;;
 SetMin            &#40;BaseOctaveIn , 1&#41;;  
 SetMax            &#40;BaseOctaveIn , 10&#41;; 
 SetDefaultValue&#40;BaseOctaveIn , 5&#41;; 
 SetFormat      &#40;BaseOctaveIn , '%.0f'&#41;; 
 
 TickIn &#58;= CreateParam&#40;'tick',ptButton&#41;;
 SetIsOutput&#40;RowIn,false&#41;;
 
 MidiOut &#58;= CreateParam&#40;'midi out',ptMidi&#41;;
 SetIsInput&#40;MidiOut,false&#41;;

 BaseOctave &#58;= 5;
 MidVolRange &#58;=64;
 NbOfMidiNotes &#58;= 0;
 OnMode &#58;= 0;
 OffMode &#58;= 0;
 PlayNotes &#58;= FALSE;
 SetArrayLength&#40;CurrentNotes , 0&#41;;
 CurrentNotesLen &#58;= 0;
end;

// Global variables
var Miditmp      &#58; TMidi;

//////////////////////////////
// callback proc
//////////////////////////////
procedure Callback&#40;n&#58;integer&#41;;
var i &#58; integer;
var vol &#58; single;
begin
    if &#40;n = RowIn&#41; then begin
        CurrentNotesLen &#58;= GetLength&#40;RowIn&#41;;

        SetArrayLength&#40;CurrentNotes , CurrentNotesLen&#41;;
        SetArrayLength&#40;LastNotes , CurrentNotesLen&#41;;
        i &#58;= 0;
        while i < CurrentNotesLen  do begin
            
            vol &#58;= GetDataArrayValue&#40;RowIn, i&#41;;
            CurrentNotes&#91;i&#93; &#58;= vol;     
            i &#58;= i+1;
        end;
    end
    else if &#40;n = OnModeIn&#41; then begin
        OnMode &#58;= round&#40; GetValue&#40;OnModeIn&#41; &#41;;
    end
    else if &#40;n = OffModeIn&#41; then begin
        OffMode &#58;= round&#40; GetValue&#40;OffModeIn&#41; &#41;;
    end
    else if &#40;n=MidVolRangeIn&#41; then begin
         MidVolRange &#58;= round&#40; GetValue&#40;MidVolRangeIn&#41; &#41;;
    end
    else if &#40;n = BaseOctaveIn&#41; then begin
        BaseOctave &#58;= round&#40; GetValue&#40;BaseOctaveIn&#41; &#41;;
    end
    else if &#40;n = TickIn&#41; then begin
        
        NbOfMidiNotes &#58;= 0; 
        
        i &#58;= 0;
        while i < CurrentNotesLen  do begin

            if &#40;&#40;OnMode = 1&#41; and  &#40;CurrentNotes&#91;i&#93; <> LastNotes&#91;i&#93;&#41; and  &#40;CurrentNotes&#91;i&#93; > 0&#41;&#41;
            or &#40;&#40;OnMode = 0&#41; and  &#40;CurrentNotes&#91;i&#93; > 0&#41;&#41;
            or &#40;&#40;OffMode = 1&#41; and  &#40;CurrentNotes&#91;i&#93; = 0&#41;&#41;
            then begin
                Miditmp.Channel &#58;= byte&#40;1&#41;;
                 if currentNotes&#91;i&#93;>0 then begin
                    Miditmp.Msg &#58;= MID_NOTE_ON;
                    end
                    else begin
                    Miditmp.Msg &#58;= MID_NOTE_OFF;
                    end;
                Miditmp.Data1 &#58;= byte&#40; &#40;BaseOctave * OCTAVE_RANGE&#41; + i&#41;;
                Miditmp.Data2 &#58;= round&#40;MidVolRange * CurrentNotes&#91;i&#93;&#41;;

                SetMidiArrayValue&#40;MidiOut, NbOfMidiNotes ,Miditmp&#41;;  // set output value
                NbOfMidiNotes &#58;= NbOfMidiNotes + 1;
            end; 
            LastNotes&#91;i&#93; &#58;= CurrentNotes&#91;i&#93;;    
            i &#58;= i+1;
        end;
        SetLength&#40;MidiOut,NbOfMidiNotes&#41;; 
        PlayNotes &#58;= TRUE;
    end;
end;


//////////////////////////////
// main proc
//////////////////////////////
Procedure Process;
var i &#58; integer;
var len &#58; integer;
var vol &#58; single;
begin
    if PlayNotes then  begin
        PlayNotes &#58;= FALSE;
    end
    else begin
        SetLength&#40;MidiOut,0&#41;;
    end;
end;
Seb.Dub

23fx23
Member
Posts: 2545
Contact:

Unread post by 23fx23 » 24 Nov 2010, 11:08

cool! well done.

User avatar
nay-seven
Site Admin
Posts: 5684
Location: rennes France
Contact:

Unread post by nay-seven » 24 Nov 2010, 11:29

great !
don't have test but in the old matrix_fall_seq_example, the fade mode send velocity too , so what the difference precisely with yours.?

23fx23
Member
Posts: 2545
Contact:

Unread post by 23fx23 » 24 Nov 2010, 13:05

mmm yes that's why i had doubts saying it was already coded, you re right.

don't remember what i moded then, and why but i definitely changed something lol
now checkin booth i see the script is different in a section where i put something that seems to make a note off when cell is 0,
the other was not really muting the note by sending a noteoff, but sending a velocity of 0 if i well remember or something like that.
to be honest i don't remember , but i needed that to fix something lol

ethnix73
Member
Posts: 604
Location: France, Caen
Contact:

Unread post by ethnix73 » 24 Nov 2010, 13:16

There is an inlet for velocity. So you can set different velocities for each note (=column) in toggle mode with an another matrix for example.

This is not the "lighter on cpu" solution but i needed it for an important modification for the base patch for the launchpad, to make it polyphonic...I decided to use different matrix module for note, velo, octave and lenght settings.
Seb.Dub

User avatar
nay-seven
Site Admin
Posts: 5684
Location: rennes France
Contact:

Unread post by nay-seven » 24 Nov 2010, 13:21

ok, thanks, that make sense, could be useful

Post Reply

Who is online

Users browsing this forum: No registered users and 20 guests