ArrayArrayArrayArrayArrayArrayArrayArrayArrayArray
Statistics: Posted by Ander — 27 Sep 2018, 13:02
With some filtering and merging I solve the key range split.
I created a new thread were I will share my advances.
]]>
Statistics: Posted by Ander — 25 Sep 2018, 02:11
Statistics: Posted by woodslanding — 19 Apr 2010, 01:50
CODE:
(*/////////////////////////////////////////////////////// CHANNEL // Version 2010-03-28; author: eric moon//// based on work by Bsork and amiga909//////////////////////////////////////////////////////*)// MIDI Channel Strip:// it is designed to function as part of a mixer channel strip, running between several keyboards and a vsti.// takes a number of midi inputs (on separate cables, for visual clarity)// and performs the following operations on each.// enable, disable--per input// strip CCs and send them out a separate output// limit to minimum and maximum notes--one range affects all inputs// transpose--again, one range for all inputs.// output rechannelizing--all outs are a single channel. Use multiple strips to control multi-timbral modules.// bypass output for turning off unused instruments. waits for all notes to be released....// Drone switch that keeps current notes sounding, but discards all note input as long as it is held// Midi learn for note range:// When learn is turned on, midi note output is suspended// the first noteNumber sets the low end of the range, the second noteNumber sets the upper limit.// once both notes are sent, notes go to main output as usual.// support for inverse range, if low note is above high noteCONST INPUT_COUNT = 2; // could handle any number, I think!CONST NOTEON = Byte(144);CONST NOTEOFF = Byte(128);CONST CONTROL = Byte(176);CONST PITCHBEND = Byte(224);CONST AFTERTOUCH = Byte(208);VAR heldNotes : ARRAY OF boolean;VAR transList : ARRAY OF integer; VAR isEnabled : Array of boolean;VAR pMidiINS,pEnableINS : ARRAY OF TParameter;VAR midiInCounts : ARRAY OF integer;VAR pTransposeIN, pDroneIN,pOutChanIN, pLearnIN, pLowNoteIn, pHiNoteIn : TParameter; VAR pPassOut,pRejectOut,pBypassOut, pLowNoteOut, pHiNoteOut : Tparameter; VAR transpose, hiVal, lowVal : integer; VAR passCount, rejectCount, learnCount, minKey, maxKey, outChan : integer;VAR isLearning, isDroning, doRelease, bypassReady : boolean;/////////////////////////// INITIALIZE /////////////////////////////////////PROCEDURE init; VAR i : integer; BEGIN transpose := 0; hiVal:= 120; lowVal := 12; passCount := 0; rejectCount := 0; learnCount := 0; minKey := 128; maxKey := 0; outChan := 1; isLearning := FALSE; isDroning := FALSE; doRelease := FALSE; bypassReady := FALSE; setArrayLength(pMidiINS, INPUT_COUNT); setArrayLength(pEnableINS, INPUT_COUNT); setArrayLength(isEnabled, INPUT_COUNT); setArrayLength(midiInCounts, INPUT_COUNT); FOR i:=0 TO INPUT_COUNT DO midiInCounts[i]:=0; setArrayLength(heldNotes, 128); FOR i:=0 TO 127 DO heldNotes[i]:=FALSE; SetArrayLength(transList, 128); FOR i:=0 TO 127 DO transList[i]:=0; FOR i := 0 TO INPUT_COUNT - 1 DO BEGIN pEnableINS[i] := CreateParam('enable ' + intToStr(i + 1),ptSwitch); SetIsOutPut(pEnableINS[i],false); END; pBypassOut := CreateParam('inst bypass', ptSwitch); SetIsInput(pBypassOut,false); pTransposeIN := CreateParam('Transpose',ptDataFader); SetIsOutPut(pTransposeIN,false); pOutChanIN := CreateParam('out ch',ptMidiNoteFader); SetIsOutPut(pOutChanIN,false); pLearnIN := CreateParam('learn',ptButton); SetIsOutPut(pLearnIN,false); pHiNoteIN := CreateParam('high note',ptMidiNoteFader); SetIsOutPut(pHiNoteIN,false); pHiNoteOUT := CreateParam('hi note', ptDataField); SetIsInPut(pHiNoteOut,false); pLowNoteIN := CreateParam('low note',ptMidiNoteFader); SetIsOutPut(pLowNoteIN,false); pLowNoteOUT := CreateParam('low note',ptDataField); SetIsInPut(pLowNoteOut,false); pDroneIN := CreateParam('drone', ptSwitch); SetIsOutput(pDroneIN,false); SetFormat(pTransposeIN,'%.0f'); SetMin(pTransposeIN,-48); SetMax(pTransposeIN,48); SetFormat(pOutChanIN,'%.0f'); SetMin(pOutChanIN,1); SetMax(pOutChanIN,16); FOR i := 0 TO INPUT_COUNT - 1 DO BEGIN pMidiINS[i] := CreateParam('MIDIin ' + intToStr(i + 1) ,ptMidi); SetIsOutPut(pMidiINS[i],false); END; pPassOut := CreateParam('passed MIDI',ptMidi); SetIsInput(pPassOut,false); pRejectOut := CreateParam('rejected MIDI',ptMidi); SetIsInput(pRejectOut,false);END; /////////////////////////// MIDI OUTPUT METHODS ////////////////////////////////////PROCEDURE PassOut(midi : tMidi);BEGIN midi.channel := BYTE(outChan); SetMidiArrayValue(pPassOut, passCount, midi); passCount := passCount + 1;END;PROCEDURE RejectOut(midi : tMidi);BEGIN midi.channel := BYTE(outChan); SetMidiArrayValue(pRejectOut, rejectCount, midi); rejectCount := rejectCount + 1;END;///////////////////////// MIDI MESSAGE TESTS ///////////////////////////////////////FUNCTION IsNote (midi : tMidi) : Boolean;BEGIN IsNote := ((midi.msg = NOTEON) OR (midi.msg = NOTEOFF));END;FUNCTION IsNoteOn (midi : tMidi) : Boolean;BEGIN IsNoteOn := ((midi.msg = NOTEON) AND (midi.data2 > 0));END;FUNCTION IsNoteOff (midi : tMidi) : Boolean;BEGIN IsNoteOff := (midi.msg = NOTEOFF) OR ((midi.msg = NOTEON) AND (midi.data2 = 0));END;////////////////////////// OTHER TESTS ////////////////////////////////////////FUNCTION UpdateBypass() : INTEGER;VAR i : integer;BEGIN bypassReady := TRUE; FOR i := 0 to (INPUT_COUNT - 1) DO BEGIN if isEnabled[i] THEN BEGIN bypassReady := FALSE; setValue(pBypassOut, 0); END; END; IF bypassReady AND isClear() THEN setValue(pBypassOUT, 1); END; FUNCTION isInRange(noteNumber : integer ) : Boolean;VAR inRange : Boolean;VAR reversed : Boolean;BEGIN reversed := (lowVal >= hiVal); IF reversed THEN isInRange := (noteNumber < hiVal) OR (noteNumber > lowVal) ELSE isInRange := (noteNumber <= hiVal) AND (noteNumber >= lowVal); END;//////////////////////// SETTERS ////////////////////////////////////////////PROCEDURE SetLowVal(n : integer);BEGIN setValue(pLowNoteOut, n); lowVal := n;END;PROCEDURE SetHiVal(n : integer);BEGIN setValue(pHiNoteOut, n); hiVal := n;END;//////////////////////// PROCESS MIDI ////////////////////////////////////////////FUNCTION bstr(b : boolean) : string;BEGIN if b THEN bstr := 'TRUE' else bstr := 'FALSE'; END;PROCEDURE ProcessMidi(midi : tMidi; enabled : boolean);BEGIN IF isLearning THEN processLearn(midi) ELSE IF not(isDroning) THEN BEGIN // pass PB and AT with notes IF (midi.msg = PITCHBEND) OR (midi.msg = AFTERTOUCH) THEN passOut(midi) ELSE IF NOT(IsNote(midi)) THEN rejectOut(midi) // everything else deals with note data.... ELSE IF IsInRange(midi.data1)and enabled THEN BEGIN IF isNoteOn(midi) THEN BEGIN ProcessNoteOn(midi, enabled); END ELSE BEGIN ProcessNoteOff(midi) END; END ELSE rejectOut(midi); //notes that are out of range IF doRelease THEN sendNoteOffs(false); END; END;PROCEDURE ProcessLearn(midi : tMidi);BEGIN IF (isNoteOn(midi)) and (learnCount = 0) THEN BEGIN lowVal := midi.data1; setValue(pLowNoteOUT, lowVal); learnCount := 1; END ELSE IF (isNoteOn(midi)) and (learnCount = 1) THEN BEGIN hiVal := midi.data1; setValue(pHiNoteOUT, hiVal); learnCount := 0; isLearning := FALSE; // we've set our outs.... END;END;PROCEDURE ProcessNoteOn(midi : tMidi; enabled : boolean);BEGIN IF enabled THEN BEGIN transList[midi.data1] := transpose; midi.data1 := midi.data1 + transpose; PassOut(midi); heldNotes[midi.data1] := TRUE; IF (midi.data1 > maxKey) THEN maxKey := midi.data1; IF (midi.data1 < minKey) THEN minKey := midi.data1; END;END;PROCEDURE ProcessNoteOff(midi : Tmidi);BEGIN midi.data1 := midi.data1 + transList[midi.data1]; heldNotes[midi.data1] := FALSE; PassOut(midi); IF bypassReady AND isClear() THEN BEGIN setValue(pBypassOut, 1); isDroning := FALSE; bypassReady := FALSE; END;END;PROCEDURE ProcessDrone(n : integer);BEGIN IF n = 0 THEN SendNoteOffs(TRUE); isDroning := n > 0; END;FUNCTION isClear() : boolean;VAR key : integer; VAR clear : boolean;BEGIN clear := TRUE; FOR key:= minKey TO maxKey DO IF heldNotes[key] = TRUE THEN clear := FALSE; isClear := clear;END;PROCEDURE SendNoteOffs(closeAll : boolean);VAR key : integer;VAR midi : tMidi;BEGIN FOR key:= minKey TO maxKey DO BEGIN IF (heldNotes[key] = FALSE) OR closeAll THEN BEGIN midi.msg := NOTEOFF; midi.channel := Byte(outChan); midi.data1 := key; midi.data2 := 0; passOut(midi); heldNotes[key] := FALSE; END; END; doRelease := FALSE;END;//////////////////////// CALLBACK /////////////////////////////////////////////PROCEDURE Callback(n: integer);VAR i : integer;BEGIN FOR i := 0 to INPUT_COUNT - 1 DO BEGIN CASE n OF pEnableINS[i] : BEGIN isEnabled[i] := getValue(n) > 0; UpdateBypass(); END; pMidiINS[i] : midiInCounts[i] := GetLength(n); END; END; CASE n OF pLearnIN : isLearning := TRUE; pOutChanIN : outChan := Byte(trunc(getValue(n))); pTransposeIN : transpose := (trunc(getValue(n))); pHiNoteIN : setHiVal(trunc(getValue(n))); pLowNoteIN : setLowVal(trunc(getValue(n))); pDroneIN : ProcessDrone(trunc(getValue(n))); END;END;///////////////////////// PROCESS //////////////////////////////////////////PROCEDURE Process;VAR i, inputNum : Integer;VAR currMsg : tMidi;BEGIN FOR inputNum := 0 TO (INPUT_COUNT - 1) DO BEGIN FOR i := 0 TO (midiInCounts[inputNum] - 1) DO BEGIN GetMidiArrayValue(pMidiINS[inputNum], i, currMsg); ProcessMidi(currMsg, isEnabled[inputNum]); END; END; SetLength(pPassOut, passCount); SetLength(pRejectOut, rejectCount); passCount := 0; rejectCount := 0;END;Statistics: Posted by woodslanding — 19 Apr 2010, 00:16
Statistics: Posted by Ben J — 18 Apr 2010, 07:06
Statistics: Posted by gurulogic — 17 Apr 2010, 11:10

Statistics: Posted by nay-seven — 17 Apr 2010, 10:58
Statistics: Posted by Ben J — 17 Apr 2010, 09:36
Statistics: Posted by Ander — 27 Sep 2018, 13:02
Statistics: Posted by Ander — 25 Sep 2018, 02:11
Statistics: Posted by woodslanding — 19 Apr 2010, 01:50
CODE:
(*/////////////////////////////////////////////////////// CHANNEL // Version 2010-03-28; author: eric moon//// based on work by Bsork and amiga909//////////////////////////////////////////////////////*)// MIDI Channel Strip:// it is designed to function as part of a mixer channel strip, running between several keyboards and a vsti.// takes a number of midi inputs (on separate cables, for visual clarity)// and performs the following operations on each.// enable, disable--per input// strip CCs and send them out a separate output// limit to minimum and maximum notes--one range affects all inputs// transpose--again, one range for all inputs.// output rechannelizing--all outs are a single channel. Use multiple strips to control multi-timbral modules.// bypass output for turning off unused instruments. waits for all notes to be released....// Drone switch that keeps current notes sounding, but discards all note input as long as it is held// Midi learn for note range:// When learn is turned on, midi note output is suspended// the first noteNumber sets the low end of the range, the second noteNumber sets the upper limit.// once both notes are sent, notes go to main output as usual.// support for inverse range, if low note is above high noteCONST INPUT_COUNT = 2; // could handle any number, I think!CONST NOTEON = Byte(144);CONST NOTEOFF = Byte(128);CONST CONTROL = Byte(176);CONST PITCHBEND = Byte(224);CONST AFTERTOUCH = Byte(208);VAR heldNotes : ARRAY OF boolean;VAR transList : ARRAY OF integer; VAR isEnabled : Array of boolean;VAR pMidiINS,pEnableINS : ARRAY OF TParameter;VAR midiInCounts : ARRAY OF integer;VAR pTransposeIN, pDroneIN,pOutChanIN, pLearnIN, pLowNoteIn, pHiNoteIn : TParameter; VAR pPassOut,pRejectOut,pBypassOut, pLowNoteOut, pHiNoteOut : Tparameter; VAR transpose, hiVal, lowVal : integer; VAR passCount, rejectCount, learnCount, minKey, maxKey, outChan : integer;VAR isLearning, isDroning, doRelease, bypassReady : boolean;/////////////////////////// INITIALIZE /////////////////////////////////////PROCEDURE init; VAR i : integer; BEGIN transpose := 0; hiVal:= 120; lowVal := 12; passCount := 0; rejectCount := 0; learnCount := 0; minKey := 128; maxKey := 0; outChan := 1; isLearning := FALSE; isDroning := FALSE; doRelease := FALSE; bypassReady := FALSE; setArrayLength(pMidiINS, INPUT_COUNT); setArrayLength(pEnableINS, INPUT_COUNT); setArrayLength(isEnabled, INPUT_COUNT); setArrayLength(midiInCounts, INPUT_COUNT); FOR i:=0 TO INPUT_COUNT DO midiInCounts[i]:=0; setArrayLength(heldNotes, 128); FOR i:=0 TO 127 DO heldNotes[i]:=FALSE; SetArrayLength(transList, 128); FOR i:=0 TO 127 DO transList[i]:=0; FOR i := 0 TO INPUT_COUNT - 1 DO BEGIN pEnableINS[i] := CreateParam('enable ' + intToStr(i + 1),ptSwitch); SetIsOutPut(pEnableINS[i],false); END; pBypassOut := CreateParam('inst bypass', ptSwitch); SetIsInput(pBypassOut,false); pTransposeIN := CreateParam('Transpose',ptDataFader); SetIsOutPut(pTransposeIN,false); pOutChanIN := CreateParam('out ch',ptMidiNoteFader); SetIsOutPut(pOutChanIN,false); pLearnIN := CreateParam('learn',ptButton); SetIsOutPut(pLearnIN,false); pHiNoteIN := CreateParam('high note',ptMidiNoteFader); SetIsOutPut(pHiNoteIN,false); pHiNoteOUT := CreateParam('hi note', ptDataField); SetIsInPut(pHiNoteOut,false); pLowNoteIN := CreateParam('low note',ptMidiNoteFader); SetIsOutPut(pLowNoteIN,false); pLowNoteOUT := CreateParam('low note',ptDataField); SetIsInPut(pLowNoteOut,false); pDroneIN := CreateParam('drone', ptSwitch); SetIsOutput(pDroneIN,false); SetFormat(pTransposeIN,'%.0f'); SetMin(pTransposeIN,-48); SetMax(pTransposeIN,48); SetFormat(pOutChanIN,'%.0f'); SetMin(pOutChanIN,1); SetMax(pOutChanIN,16); FOR i := 0 TO INPUT_COUNT - 1 DO BEGIN pMidiINS[i] := CreateParam('MIDIin ' + intToStr(i + 1) ,ptMidi); SetIsOutPut(pMidiINS[i],false); END; pPassOut := CreateParam('passed MIDI',ptMidi); SetIsInput(pPassOut,false); pRejectOut := CreateParam('rejected MIDI',ptMidi); SetIsInput(pRejectOut,false);END; /////////////////////////// MIDI OUTPUT METHODS ////////////////////////////////////PROCEDURE PassOut(midi : tMidi);BEGIN midi.channel := BYTE(outChan); SetMidiArrayValue(pPassOut, passCount, midi); passCount := passCount + 1;END;PROCEDURE RejectOut(midi : tMidi);BEGIN midi.channel := BYTE(outChan); SetMidiArrayValue(pRejectOut, rejectCount, midi); rejectCount := rejectCount + 1;END;///////////////////////// MIDI MESSAGE TESTS ///////////////////////////////////////FUNCTION IsNote (midi : tMidi) : Boolean;BEGIN IsNote := ((midi.msg = NOTEON) OR (midi.msg = NOTEOFF));END;FUNCTION IsNoteOn (midi : tMidi) : Boolean;BEGIN IsNoteOn := ((midi.msg = NOTEON) AND (midi.data2 > 0));END;FUNCTION IsNoteOff (midi : tMidi) : Boolean;BEGIN IsNoteOff := (midi.msg = NOTEOFF) OR ((midi.msg = NOTEON) AND (midi.data2 = 0));END;////////////////////////// OTHER TESTS ////////////////////////////////////////FUNCTION UpdateBypass() : INTEGER;VAR i : integer;BEGIN bypassReady := TRUE; FOR i := 0 to (INPUT_COUNT - 1) DO BEGIN if isEnabled[i] THEN BEGIN bypassReady := FALSE; setValue(pBypassOut, 0); END; END; IF bypassReady AND isClear() THEN setValue(pBypassOUT, 1); END; FUNCTION isInRange(noteNumber : integer ) : Boolean;VAR inRange : Boolean;VAR reversed : Boolean;BEGIN reversed := (lowVal >= hiVal); IF reversed THEN isInRange := (noteNumber < hiVal) OR (noteNumber > lowVal) ELSE isInRange := (noteNumber <= hiVal) AND (noteNumber >= lowVal); END;//////////////////////// SETTERS ////////////////////////////////////////////PROCEDURE SetLowVal(n : integer);BEGIN setValue(pLowNoteOut, n); lowVal := n;END;PROCEDURE SetHiVal(n : integer);BEGIN setValue(pHiNoteOut, n); hiVal := n;END;//////////////////////// PROCESS MIDI ////////////////////////////////////////////FUNCTION bstr(b : boolean) : string;BEGIN if b THEN bstr := 'TRUE' else bstr := 'FALSE'; END;PROCEDURE ProcessMidi(midi : tMidi; enabled : boolean);BEGIN IF isLearning THEN processLearn(midi) ELSE IF not(isDroning) THEN BEGIN // pass PB and AT with notes IF (midi.msg = PITCHBEND) OR (midi.msg = AFTERTOUCH) THEN passOut(midi) ELSE IF NOT(IsNote(midi)) THEN rejectOut(midi) // everything else deals with note data.... ELSE IF IsInRange(midi.data1)and enabled THEN BEGIN IF isNoteOn(midi) THEN BEGIN ProcessNoteOn(midi, enabled); END ELSE BEGIN ProcessNoteOff(midi) END; END ELSE rejectOut(midi); //notes that are out of range IF doRelease THEN sendNoteOffs(false); END; END;PROCEDURE ProcessLearn(midi : tMidi);BEGIN IF (isNoteOn(midi)) and (learnCount = 0) THEN BEGIN lowVal := midi.data1; setValue(pLowNoteOUT, lowVal); learnCount := 1; END ELSE IF (isNoteOn(midi)) and (learnCount = 1) THEN BEGIN hiVal := midi.data1; setValue(pHiNoteOUT, hiVal); learnCount := 0; isLearning := FALSE; // we've set our outs.... END;END;PROCEDURE ProcessNoteOn(midi : tMidi; enabled : boolean);BEGIN IF enabled THEN BEGIN transList[midi.data1] := transpose; midi.data1 := midi.data1 + transpose; PassOut(midi); heldNotes[midi.data1] := TRUE; IF (midi.data1 > maxKey) THEN maxKey := midi.data1; IF (midi.data1 < minKey) THEN minKey := midi.data1; END;END;PROCEDURE ProcessNoteOff(midi : Tmidi);BEGIN midi.data1 := midi.data1 + transList[midi.data1]; heldNotes[midi.data1] := FALSE; PassOut(midi); IF bypassReady AND isClear() THEN BEGIN setValue(pBypassOut, 1); isDroning := FALSE; bypassReady := FALSE; END;END;PROCEDURE ProcessDrone(n : integer);BEGIN IF n = 0 THEN SendNoteOffs(TRUE); isDroning := n > 0; END;FUNCTION isClear() : boolean;VAR key : integer; VAR clear : boolean;BEGIN clear := TRUE; FOR key:= minKey TO maxKey DO IF heldNotes[key] = TRUE THEN clear := FALSE; isClear := clear;END;PROCEDURE SendNoteOffs(closeAll : boolean);VAR key : integer;VAR midi : tMidi;BEGIN FOR key:= minKey TO maxKey DO BEGIN IF (heldNotes[key] = FALSE) OR closeAll THEN BEGIN midi.msg := NOTEOFF; midi.channel := Byte(outChan); midi.data1 := key; midi.data2 := 0; passOut(midi); heldNotes[key] := FALSE; END; END; doRelease := FALSE;END;//////////////////////// CALLBACK /////////////////////////////////////////////PROCEDURE Callback(n: integer);VAR i : integer;BEGIN FOR i := 0 to INPUT_COUNT - 1 DO BEGIN CASE n OF pEnableINS[i] : BEGIN isEnabled[i] := getValue(n) > 0; UpdateBypass(); END; pMidiINS[i] : midiInCounts[i] := GetLength(n); END; END; CASE n OF pLearnIN : isLearning := TRUE; pOutChanIN : outChan := Byte(trunc(getValue(n))); pTransposeIN : transpose := (trunc(getValue(n))); pHiNoteIN : setHiVal(trunc(getValue(n))); pLowNoteIN : setLowVal(trunc(getValue(n))); pDroneIN : ProcessDrone(trunc(getValue(n))); END;END;///////////////////////// PROCESS //////////////////////////////////////////PROCEDURE Process;VAR i, inputNum : Integer;VAR currMsg : tMidi;BEGIN FOR inputNum := 0 TO (INPUT_COUNT - 1) DO BEGIN FOR i := 0 TO (midiInCounts[inputNum] - 1) DO BEGIN GetMidiArrayValue(pMidiINS[inputNum], i, currMsg); ProcessMidi(currMsg, isEnabled[inputNum]); END; END; SetLength(pPassOut, passCount); SetLength(pRejectOut, rejectCount); passCount := 0; rejectCount := 0;END;Statistics: Posted by woodslanding — 19 Apr 2010, 00:16
Statistics: Posted by Ben J — 18 Apr 2010, 07:06
Statistics: Posted by gurulogic — 17 Apr 2010, 11:10

Statistics: Posted by nay-seven — 17 Apr 2010, 10:58
Statistics: Posted by Ben J — 17 Apr 2010, 09:36