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