Posted: 04 Nov 2008, 02:59
can anyone tell me why my script is sending noteoffs when I use the expression2 controller? (presumably expression1 also does it, but I haven't checked that) It's also correctly sending out expression values.... these noteoffs SEEM to be causing clicks in the B4, but that may be zipper noise..... not sure
thanks as ever for any help!!
-e
Code: Select all
TYPE tTransp = ARRAY OF integer;
VAR transpositions : ARRAY OF tTransp;
// parameters declaration
var input : Tparameter; // midi input
var output : Tparameter; // midi output
var key1 : Tparameter; // output notes from keyboard 1
var key2 : Tparameter; // output notes from keyboard 2
var exp : Tparameter; // send out a volume control signal
var out1on : Tparameter; // enable output 1
var out2on : Tparameter; // enable output 2
var disable : Tparameter; // boolean control out for disabling VST if no keyboard is controlling it
var semi : TParameter; // transpose by semi-tone
var octave : TParameter; // transpose by octave
var split : Tparameter; // pitch below or above which notes are not sent
var upper : Tparameter; // send pitches above the split if on. otherwise send pitches below.
var outCH : Tparameter; // rechannelize input. Value of 0 leaves input channel unchanged
var exp1ch : integer;
var exp1cc : integer;
var exp2ch : integer;
var exp2cc : integer;
var exp1val : single;
var exp2val : single;
var outputCH : integer;
var bytecount : integer;
var midiLen : integer;
var midi : TMidi;
var transpose : integer;
var splitVal : integer;
var upperVal : integer;
var key1Val : integer;
var key2Val : integer;
var key1ch : integer;
var key2ch : integer;
var i : integer;
var channel : integer;
var noteCount : integer;
var disabled : boolean;
// initialisation
PROCEDURE init;
BEGIN
output := CreateParam('MIDIout',ptMidi); SetIsInput(Output,false);
key1 := CreateParam('key1', ptSwitch); SetIsOutput(key1,false);
key2 := CreateParam('key2', ptSwitch); SetIsOutput(key2,false);
split := CreateParam('split',ptMidiNoteFader); SetIsOutput(split,false);
upper := CreateParam('upper',ptSwitch); SetIsOutput(upper,false);
exp := CreateParam('expression',ptDataField); SetIsInput(exp,false);
out1on := CreateParam('out1 enable',ptDataField); SetIsInput(out1on,false);
out2on := CreateParam('out2 enable',ptDataField); SetIsInput(out2on,false);
disable := CreateParam('vstBypass',ptDataField); SetIsInput(disable,false);
input := CreateParam('MIDIin',ptMidi); SetIsOutput(Input,false);
semi := CreateParam('semi',ptDataField); SetIsOutput(semi,false);
octave := CreateParam('8va',ptDataField); SetIsOutput(octave,false);
outCH := CreateParam('outCH', ptDataField); SetIsOutput(outCH,false);
key1ch := 1;
key2ch := 2;
exp1ch := 1;
exp1cc := 4;
exp2ch := 2;
exp2cc := 3;
noteCount := 0;
SetArrayLength(transpositions, 2);
FOR i := 0 TO 1 DO // we are going to ignore midi data on any but the 2 keyboard channels...
SetArrayLength(transpositions[i], 128);
//default values and formats
SetDefaultValue(upper,1);
SetDefaultValue(key1,1);
SetDefaultValue(key2,1);
SetFormat(split,'%.0f');
SetMin(split,1);
SetMax(split,127);
SetDefaultValue(split,1);
SetFormat(semi,'%.0f');
SetMin(semi,-7);
SetMax(semi,7);
SetDefaultValue(semi,0);
SetFormat(octave,'%.0f');
SetMin(octave,-4);
SetMax(octave,4);
SetDefaultValue(octave,0);
SetDefaultValue(outCH,1);
end;
PROCEDURE CreateOut(ch, msg, data1, data2 : integer);
BEGIN
midi.msg := byte(msg);
midi.data1 := byte(data1);
midi.data2 := byte(data2);
midi.channel := byte(ch);
SetMidiArrayValue(output, bytecount, midi);
END; // CreateOut
PROCEDURE processNoteOns;
BEGIN
//writeln('in noteon loop');
IF (((channel = key1ch) AND (key1Val = 1)) OR ((channel = key2ch) AND (key2Val = 1)))
AND (((midi.data1 >= splitVal) AND (upperVal = 1)) OR ((midi.data1 < splitVal) AND (upperVal = 0)))
THEN BEGIN
transpositions[channel - 1][midi.data1] := transpose; // only works if keyboard ch's are 1 and 2....
midi.data1 := midi.data1 + transpose;
midi.channel := outputCH;
SetMidiArrayValue(output, bytecount, midi);
//noteCount := noteCount + 1; // increase count of held notes
END;
END; //process Noteons
PROCEDURE processNoteOffs;
BEGIN
midi.data1 := midi.data1 + transpositions[channel - 1][midi.data1]; // Retrieve stored transpose and add to NoteOff
midi.channel := outputCH;
SetMidiArrayValue(output, bytecount, midi);
//noteCount := noteCount - 1; // decrease count of held notes
writeln('in notes off = ' + intToStr(noteCount));
END; //processNoteoffs
PROCEDURE processSustain;
BEGIN
IF (midi.data2 < 64) THEN //send sus up on all instruments, selected or not...
BEGIN
midi.channel := outputCH;
SetMidiArrayValue(output, bytecount, midi);
END
ELSE IF (((channel = 1) AND (key1Val = 1)) OR ((channel = 2) AND (key2Val = 1))) THEN
BEGIN
IF (midi.data2 >= 64) THEN //send sus down only on selected instruments
BEGIN
midi.channel := outputCH;
SetMidiArrayValue(output, bytecount, midi);
END;
END;
END; // process sustain
PROCEDURE disableVST; // not used yet
BEGIN
disabled := ( (key1val = 0) AND (key2val = 0));
// IF (disabled) THEN
// wait until all notes are off before doing this--how??
// and don't undo it when notes are back on!
// IF (noteCount = 0) THEN
// BEGIN
// CreateOut(outputCH, 208, 0, 0); //reset aftertouch
// CreateOut(outputCH, 224, 0, 64); //reset pitchbend
// CreateOut(outputCH, 176, 1, 0); //reset mod wheel
// setValue(disable, 1);
// setValue(out1on, 0);
// setValue(out2on, 0);
// END
// ELSE BEGIN
// setValue(disable, 0);
// END
// ELSE
setValue(disable, 0);
END; // disable vst
PROCEDURE processExpression1;
BEGIN
exp1val := (midi.data2)/128;
setValue(exp, exp1val);
END;
PROCEDURE processExpression2;
BEGIN
exp2val := (midi.data2)/128;
setValue(exp, exp2Val);
END;
PROCEDURE processControllers;
BEGIN
SetMidiArrayValue(output, bytecount, midi);
END;
// main
BEGIN
// set variables from inputs
transpose := trunc(GetValue(semi) + ((getValue(octave) * 12)));
splitVal := trunc(getValue(split));
upperVal := trunc(getValue(upper));
key1Val := trunc(getValue(key1));
key2Val := trunc(getValue(key2));
outputCh := trunc(getValue(outCH));
// disable the VST if nothing is controlling it
disableVST;
setValue(out1on, key1val);
setValue(out2on, key2val);
midiLen := GetLength(input);
IF (midiLen > 0) THEN
BEGIN
SetLength(output, midiLen);
// process midi
FOR bytecount := 0 TO (midiLen - 1) DO
BEGIN
GetMidiArrayValue(input, bytecount, midi);
channel := midi.channel;
IF ((midi.msg = 144) AND (midi.data2 > 0))
THEN BEGIN // Noteon
processNoteons;
END
ELSE IF ((midi.msg = 128)
OR ((midi.msg = 144) AND (midi.data2 = 0))) THEN
BEGIN // NoteOff
processNoteoffs;
END
ELSE IF (midi.msg = 176) AND (midi.data1 = 64) THEN
BEGIN
processSustain;
END
ELSE IF (midi.msg = 176) AND (midi.channel = exp1ch) AND (midi.data1 = exp1cc) THEN
BEGIN
processExpression1;
END
ELSE IF (midi.msg = 176) AND (midi.channel = exp2ch) AND (midi.data1 = exp2cc) THEN
BEGIN
processExpression2;
END
ELSE IF (midi.msg = 176) THEN
BEGIN
processControllers;
END;
END;
END
// no midi in this block....
ELSE BEGIN
SetLength(output, 0);
END;
END.-e