Welcome to %s forums

BrainModular Users Forum

Login Register

scripts--midi output array size question

I need help on a Patch
Post Reply
woodslanding
Member
Posts: 1327
Contact:

Unread post by woodslanding » 03 Dec 2008, 20:10

If I have a script that both takes in midi, and may also create it, how would I set the midi output array size??

Or is this not really possible?

Thanks as ever!
-eric
Custom Ryzen 5900x MATX build, Win10, Fireface UFX, touchscreen
Custom 2 manual midi keyboard
Usine, Kontakt, Reaktor, Synthmaster, Byome, Arturia, Soundtoys, Unify

bsork
Site Admin
Posts: 1334
Location: Asker, Norway
Contact:

Unread post by bsork » 03 Dec 2008, 23:14

You should use separate parameters for input and output (but I guess you already do...).

Just use a counter when populating the output array, and set the size after filling it. Remember that the size is the last index number + 1. It may seem a bit weird that you can enter values in the array even beyond the existing size, but you can. You can see examples of that in a lot of the MIDI scripts in Usine.

And if you think it's confusing, I can tell you that I more than once have had to check that this really is the way it's being done...
Bjørn S

woodslanding
Member
Posts: 1327
Contact:

Unread post by woodslanding » 03 Dec 2008, 23:55

wow, that IS counter-intuitive. Or unintuitive use of counters....

Thanks!
-e
Custom Ryzen 5900x MATX build, Win10, Fireface UFX, touchscreen
Custom 2 manual midi keyboard
Usine, Kontakt, Reaktor, Synthmaster, Byome, Arturia, Soundtoys, Unify

bsork
Site Admin
Posts: 1334
Location: Asker, Norway
Contact:

Unread post by bsork » 04 Dec 2008, 08:53

It reminds me stuff I've encountered (Ha! managed to use a word with "counter" in it!:) ) in other environments/languages, especially with handling of strings. Maybe not so weird after after all...?
Bjørn S

woodslanding
Member
Posts: 1327
Contact:

Unread post by woodslanding » 04 Dec 2008, 18:49

I suppose there is a hidden vector[] behind the scenes....

I assume I don't need to worry if I don't fill up the output array--if I filter some messages, I don't need to create 'dummy' messages for the output array do I?

I have my module working now. After some testing, I'll upload to the user section. Then you can tell me how to make it twice as efficient ;)

-e
Custom Ryzen 5900x MATX build, Win10, Fireface UFX, touchscreen
Custom 2 manual midi keyboard
Usine, Kontakt, Reaktor, Synthmaster, Byome, Arturia, Soundtoys, Unify

bsork
Site Admin
Posts: 1334
Location: Asker, Norway
Contact:

Unread post by bsork » 04 Dec 2008, 23:04

woodslanding wrote:I assume I don't need to worry if I don't fill up the output array--if I filter some messages, I don't need to create 'dummy' messages for the output array do I?
No - just add the MIDI messages you want and set the size when you're through. I'm pretty sure that the maximum length is 512 messages per execution block/array though, but you would have to create a really OTT patch to have problems with that limit. That said, I do have a feeling that your MIDI patches are bigger and more complex than most of us would ever dream of creating.... :)

Looking forward to to have a look at the ideas and solutions you've come up with!
Bjørn S

woodslanding
Member
Posts: 1327
Contact:

Unread post by woodslanding » 06 Dec 2008, 05:37

I don't actually send that much midi. But I like a lot of control about -where- it goes.

That said, I'm now wondering if I should be using midi at all.... what about vsts with more than 127 parameters? Maybe I should be doing most of this with OSC instead. I mean, data comes in through USB via midi, so my thought is to keep it there. But... I only have 16 ot 32 midi control sources, and I may have hundreds of destinations.... but I'm not at all sure how OSC maps to VST parameters.

And anyway, maybe Oliver is figuring out a much better way to address this issue, right now!

This may all just be a learning experience for all I know. Getting me up to speed on Pascal, FI! (I'd rather be getting up to
speed on C++ though!) And this may all be supplanted by features in 4.1 anyway....

Just so you know where I stand, here is the script as it exists:

Code: Select all

(*

Requires an input file in the form:
1$modwh
7$volume
11$expression
112$osc2PW

etc.... haven't figured out how to read tabs yet.  I alphabetize them in excel first.... the script
doesn't care what order they're in.

inputs--2 text inputs for directory and file (directory should come from buss if a bunch of these
are being used in the workspace, for portability.)

Each set of ins and outs should be hooked up to one fader and one switch:

The fader's value controls the line of the input file--cable it to 'vstParam'
The fader should not display its 'fader' element, as the line of the file isn't important data to the user. 
The fader's 'caption' is controlled by the 'name' output, and shows the name of the selected parameter.
So it's basically being used like a one-element list, or a text fader.

The 'switch' output should be cabled to the 'enable' input.  hey that's easy!
The 'value' output should be cabled to the switch's 'caption'.  Now the switch shows the midi
input value, in the range 0 to 99, or '--' if the control is not enabled.
The 'valHUE' output goes to the switch's 'color'.

Finally, connect a midi knob to the midi input, and make sure the 'ccNum' input matches what the
knob sends.... viola--pretty colors, and instant reassignment by name to any parameter of your VST.

*)


type midiCC = Record
    name   : string;
    number : integer;
end;

var st          : TStringList;

var line        : string;
var delimiter   : string;
var position    : integer;
var i           : integer;

var chCount     : integer;
var ccCount     : integer;
var count       : string;





var controls    : array of  midiCC;
var name          : string;
var number        : integer;

var filename    : string;
var dirPath     : string;
var fileIn      : Tparameter;   // file name
var dirIn       : Tparameter;   // directory address

var midiIn      : Tparameter;   // midi IN
var parCountOUT : Tparameter;   // length of parameterList
var midiOut     : Tparameter;   // midi output

var enableIN        : Array of Tparameter;   // enable control
var ccnumberIN      : Array of Tparameter;
var vstParamIN      : Array of Tparameter;
var captionOUT      : Array of Tparameter;
var valHueOUT      : Array of Tparameter;
var valueOUT        : Array of Tparameter;

var enabled         : Array of boolean;
var inputCCs        : Array of integer;  //these are the input CC#s to look for a match
var parameterOuts   : Array of integer;  //this is the key to get the output param#

var interval        : integer;
var cycle           : integer;
var parameterIndex  : integer;
//var key             : integer;
var first           : boolean;

var midi           : TMidi;
var msgCount       : integer;
var msgNumber      : integer;
var current        : integer;
//var control        : integer;
var red            : integer;
var green          : integer;
var blue           : integer;

// initialisation : create parameters
procedure init;

begin  
    chCount := 4;
    cycle := 0;
    interval := 64;
    first := TRUE;

    fileIn      := CreateParam('fileName',ptTextField);     SetIsOutput(fileIn,false);
    setStringValue(fileIn, 'pro5CCs.txt');
 
    dirIn       := CreateParam('dirPath',ptTextField);      SetIsOutput(dirIn,false);
    setStringValue(dirIn, 'c:usinedata');

    midiIn := CreateParam('MIDIin',ptMidi);                 SetIsOutput(midiIn,false); 
    midiOut := CreateParam('MIDIout',ptMidi);               SetIsInput(midiOut,false);
    
    parCountOUT  := CreateParam('ccCount', ptdataField);    SetIsInput(parCountOUT,false);
    setDefaultValue(parCountOUT, 127);   
    
    // set array lengths
    SetArrayLength(ccNumberIN, chCount);
    SetArrayLength(enableIN, chCount);
    SetArrayLength(vstParamIN, chCount);
    //SetArrayLength(ctrlTypeIN, chCount);
    SetArrayLength(enableIN, chCount);
    SetArrayLength(captionOUT, chCount);
    SetArrayLength(valueOUT, chCount);
    SetArrayLength(valHueOUT, chCount);

       
    SetArrayLength(enabled, chCount); 
    SetArrayLength(inputCCs, chCount);
    SetArrayLength(parameterOuts, chCount);
    
    
    // create channels 
    for i := 0 to (chCount - 1) do begin
        
        count := IntToStr(i+1);
        
        // chCount
        ccNumberIN[i]:= CreateParam('ccNum' + count, ptdataField);
        setMax(ccNumberIN[i], 127);
        setMin(ccNumberIN[i], 0);
        SetFormat(ccNumberIN[i],'%.0f');
        SetIsOutput(ccNumberIN[i], false);
        
        enableIN[i] := CreateParam('enable' + count, ptSwitch);             
        SetIsOutput(enableIN[i],false);
    
        vstParamIN[i] := CreateParam('vstParam'+ count, ptdataFader);
        SetIsOutput(vstParamIN[i], false);
        setMax(vstParamIN[i], 127);
        setMin(vstParamIN[i], 0);
        SetFormat(vstParamIN[i],'%.0f');

        // outs
        captionOUT[i] := CreateParam('name' + count, ptTextField);
        SetIsInput(captionOut[i], false);
        
        // use for text of enable switch
        valueOUT[i] := CreateParam('value' + count, ptTextField);
        // use for background of parameter fader
        valHueOUT[i] := CreateParam('valHUE' + count, ptDataField);
        
        SetIsInput(valueOUT[i], false);
        SetIsInput(valHueOUT[i], false);
    end;
    

end;

function midiDecStr(val : integer) : string;
begin

    result := intToStr(trunc((val * 100/128)));
end;

function boolToStr(isOn : boolean) : string;
begin
    if isOn then
    begin
        result := 'ON';
    end
    else
    begin
        result := '--';
    end;
end;

function singleToBool(val : single) : boolean ;
begin
    if val = 0 then
    begin
        result := FALSE;
    end
    else
    begin
        result := TRUE;
    end;
end;

function midiToColor(midiVal : integer): integer;
begin
    midiVal := (midiVal * 2);
    red := midiVal;
    if (midiVal > 128) then
    begin
        green := (256 - midival) * 2;
    end else
    begin
        green := midival * 2;
    end;
    blue := 256 - midiVal;
    midiVal:= red + (green * 256) + (blue * 256 * 256);
    writeln('rgb = ' + intToStr(red) + ', ' + intToStr(green) + ', ' + intToStr(blue));
    result := midiVal;
end;
    
procedure processCCs; // here we figure out if it's a cc# that we want to process....
begin
    current := midi.data1;
    writeln('control ' + intToStr(i) + '  ' + intToStr(inputCCs[i]));
    if (current = inputCCs[i]) then
        begin
        midi.data1 := parameterOuts[i];   
        SetMidiArrayValue(midiOUT, msgNumber, midi);
        SetStringValue(valueOUT[i], midiDecStr(midi.data2));
        SetValue(valHueOUT[i], midiToColor(midi.data2));        
    end;
end;

procedure loadCCs;  // a post-init method to load the file
begin
    filename  := getStringValue(fileIn);
    dirPath  := getStringValue(dirIn);
    delimiter := '$';
    st := TStringList.create;
    st.clear;
    st.loadfromFile(dirPath + '' + filename);
    
    ccCount := st.count;
    setArrayLength(controls, ccCount);
    setValue(parCountOUT, ccCount - 1);
    for i := 0 to (st.count-1) do
    begin    
        line := st.strings[i];
        position := pos(delimiter, line);                
        name := copy(line, position + 1, length(line));
        number := strtoInt(copy(line, 0, position - 1));
        controls[i].name := name;
        controls[i].number := number;
        writeln(controls[0].name + ' ' + intToStr(controls[0].number));
    end; 
    st.free;
end;



//////////////////////////////
// main proc
begin
    
    if first then
    begin
        loadCCs;
        first := false;
    end;    
    cycle := (cycle + 1) MOD 2000;
    
    IF ((cycle MOD interval) = 0) THEN
    begin
        for i := 0 to (chCount - 1) do
        begin
              
            parameterIndex := trunc(getValue(vstParamIN[i])); // this is the key for the param map
            parameterOUts[i] := controls[parameterIndex].number;  // these are the output parameter #s
            setStringValue(captionOUT[i], controls[parameterIndex].name); // set the string outs
            enabled[i] := singleToBool(getValue(enableIn[i]));
            inputCCs[i] := trunc(getValue(ccNumberIN[i]));
    
            if (enabled[i] = FALSE) then
            begin
                setStringValue(valueOUT[i],'--');
            end;           
        end;       
    end;
    
    
    msgCount := GetLength(midiIN);  // get the number of incoming midi codes 
    SetLength(midiOut, msgCount);
    if msgCount > 0 then 
    begin
        for msgNumber := 0 to msgCount-1 do
        begin 
            GetMidiArrayValue(midiIN, msgNumber, midi);
            for i := 0 to (chCount - 1) do
            begin
                if (midi.msg = 176) and (enabled[i])
                then
                begin
                    processCCs;
                end
                else
            end;
        end;
    end
    
    // no midi in this block....
    ELSE BEGIN
        SetLength(midiOut, 0);
    END;
end.
cheers!
-eric
Custom Ryzen 5900x MATX build, Win10, Fireface UFX, touchscreen
Custom 2 manual midi keyboard
Usine, Kontakt, Reaktor, Synthmaster, Byome, Arturia, Soundtoys, Unify

amiga909
Member
Posts: 324
Contact:

Unread post by amiga909 » 06 Dec 2008, 11:21

tkx for this script draft.

fascinating idea, keep on :)

Post Reply

Who is online

Users browsing this forum: No registered users and 16 guests