ArrayArrayArrayArrayArrayArrayArrayArrayArrayArrayArrayArrayArrayArrayArrayArrayArrayArrayArrayArrayArrayArrayArrayArrayArray
Statistics: Posted by woodslanding — 10 Jan 2010, 11:47 CODE: Statistics: Posted by woodslanding — 10 Jan 2010, 11:32 CODE: Statistics: Posted by woodslanding — 10 Jan 2010, 11:18 Statistics: Posted by bsork — 04 Dec 2009, 16:15 Statistics: Posted by gurulogic — 04 Dec 2009, 03:17 Statistics: Posted by bsork — 03 Dec 2009, 21:44 Statistics: Posted by gurulogic — 03 Dec 2009, 19:19
tomorrow....
]]>
So I put in a couple of booleans to decide whether to send the note offs and disable the instrument, but then I called the actual methods from within process. Seems to work! Here's the code:(*/////////////////////////////////////////////////////// CHANNEL // Version 2009-11-21; author: eric moon//// based on work by Bsork and amiga909//////////////////////////////////////////////////////*)// This 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 AT and send them out a separate output// read CC64 values (or a CC of your choice) to withhold noteoffs until the sus pedal is released.// limit to minimum and maximum notes--one range affects all inputs, as it's assumed you'll typically be using one input at a time// 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 new notesOns as long as it is held// It is designed to function as part of a mixer channel strip, running between several keyboards and a vsti.// When the 'learn' function is enabled, notes are sent out output 2// the first note sets the lower range, the second note sets the upper limit.// when both notes are sent, learn is disabled, and notes go to output 1 as usual.CONST SUS_PED= 64; //change if you use an unorthodox CC for sustaining.CONST INPUT_COUNT = 2; //allows up to 16 inputs, one per channelCONST NOTE_ON = 144;CONST NOTE_OFF = 128;CONST CONTROL = 176;CONST PITCHBEND = 224;VAR noteList : ARRAY OF boolean;VAR transList : ARRAY OF integer;VAR midi,noteOff : TMidi; var midiIns : ARRAY OF Tparameter;var enables : ARRAY OF TParameter;var notesOut : Tparameter;var otherOut : Tparameter; // all CCs except the sustain value go out this output. So does AT and PgChvar octave : TParameter;var semi : TParameter;var hiNote : TParameter;var lowNote : TParameter;var drone : TParameter; // sustains, but ignores new noteonsvar outChan : TParameter; // everything goes out one channel. It's a channel strip. Use more if you need other channels!var instEnable: TParameter;var lower : Tparameter;var upper : Tparameter; var learn : TParameter;VAR octVal, semiVal, transpose : integer;VAR hiVal, lowVal : integer; VAR midiInCount : integer;VAR otherOutCount, notesOutCount : integer;VAR key, inputNum, byteNum : integer; VAR minChn, maxChn, minKey, maxKey : integer;VAR outputChannel : integer;VAR isSustained,noInput : boolean;VAR isEnabled : Array of boolean;VAR learning : boolean;VAR droning : boolean;VAR release : boolean;VAR disablable : boolean;var learnCount : integer;//////////////////////////////////////////////////////// initialize//////////////////////////////////////////////////////PROCEDURE init; BEGIN minChn := INPUT_COUNT - 1; // these are initially set to their opposite extremes.... maxChn := 0; minKey := 128; maxKey := 0; isSustained := FALSE; setArrayLength(noteList, 128); FOR key:=0 TO 127 DO BEGIN noteList[key]:=FALSE; END; SetArrayLength(transList, 128); FOR key:=0 TO 127 DO BEGIN transList[key]:=0; END; setArrayLength(midiIns, INPUT_COUNT); setArrayLength(enables, INPUT_COUNT); FOR inputNum := 0 TO INPUT_COUNT - 1 DO BEGIN enables[inputNum] := CreateParam('enable ' + intToStr(inputNum + 1),ptSwitch); SetValue(enables[inputNum], 1); SetIsOutPut(enables[inputNum],false); END; octave := CreateParam('octave',ptDataFader); SetIsOutPut(octave,false); semi := CreateParam('semi',ptDataFader); SetIsOutPut(semi,false); SetFormat(octave,'%.0f'); SetMin(octave,-4); SetMax(octave,4); SetFormat(semi,'%.0f'); SetMin(semi,-7); SetMax(semi,7); hiNote := CreateParam('high note',ptMidiNoteFader); SetIsOutPut(hiNote,false); lowNote := CreateParam('low note',ptMidiNoteFader); SetIsOutPut(lowNote,false); outChan := CreateParam('output chan', ptDataFader); SetIsOutPut(outchan,false); SetFormat(outChan,'%.0f'); SetMin(outChan,1); SetMax(outChan,16); SetValue(lowNote, 10); SetValue(hiNote, 115); drone := CreateParam('drone', ptSwitch); SetIsOutput(drone,false); instEnable := CreateParam('inst enable', ptSwitch); SetIsInput(instEnable,false); FOR inputNum := 0 TO INPUT_COUNT - 1 DO BEGIN midiIns[inputNum] := CreateParam('MIDIin ' + intToStr(inputNum + 1) ,ptMidi); SetIsOutPut(midiIns[inputNum],false); END; notesOut := CreateParam('NoteMIDI',ptMidi); SetIsInput(notesOut,false); otherOut := CreateParam('otherMIDI',ptMidi); SetIsInput(otherOut,false); learn := CreateParam('learn',ptButton); SetIsOutPut(learn,false); lower := CreateParam('lower',ptMidiNoteFader); SetIsInPut(lower,false); upper := CreateParam('upper',ptMidiNoteFader); SetIsInPut(upper,false); notesOutCount := 0; otherOutCount := 0; learnCount := 0; disablable := FALSE; droning := FALSE; release := FALSE; SetArrayLength(isEnabled, INPUT_COUNT); END;// <F> isNoteOn: //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// FUNCTION isNoteOn(midi: tMidi): boolean;BEGIN IF (midi.msg = NOTE_ON) AND (midi.data2>0) THEN BEGIN result := true; END ELSE BEGIN result := false; END;END;// <F> isNoteOff: //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// FUNCTION isNoteOff(midi: tMidi): boolean;BEGIN IF (midi.msg = NOTE_OFF) OR ((midi.msg = NOTE_ON) AND (midi.data2 = 0)) THEN BEGIN result := true; END ELSE BEGIN result := false; END;END; // <F> isSusPed: //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// FUNCTION isSusPed(midi: tMidi) : boolean;BEGIN IF (midi.msg = CONTROL) AND (midi.data1 = SUS_PED) THEN BEGIN result := true; END ELSE BEGIN result := false; END;END; // <F> isPitchBend: //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// FUNCTION isPitchBend(midi: tMidi): boolean;BEGIN IF (midi.msg = PITCHBEND) THEN BEGIN result := true; END ELSE BEGIN result := false; END;END;// <F> global function inRange--eliminates only noteons outside the range limits FUNCTION inRange(midi: tMidi) : boolean;BEGIN IF (isNoteOn(midi)) AND (midi.data1 > lowVal) AND (midi.data1 < hiVal) THEN BEGIN result := TRUE; END ELSE BEGIN result := FALSE; END; END;// <F> isClear//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^//FUNCTION isClear() : boolean; // can we stop this loop as soon as a key = true?? Didn't like 'while'VAR clear : boolean;BEGIN clear := TRUE; BEGIN FOR key:= minKey TO maxKey DO BEGIN IF (noteList[key] = TRUE) THEN BEGIN clear := FALSE; END; END; END; result := clear; END;// <F> ReleaseNotes --when you release the sustain, or release the drone, or change the output channel//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^//PROCEDURE ReleaseNotes;BEGIN FOR key:= minKey TO maxKey DO BEGIN IF (noteList[key] = TRUE) THEN BEGIN noteOff.msg := NOTE_OFF; noteOff.channel := outputChannel; // byte is a conversion--is this needed? noteOff.data1 := key; noteOff.data2 := 0; setMidiArrayValue(notesOut, notesOutCount, noteOff); strace('sending noteOff for ' + intToStr(key)); notesOutCount := notesOutCount + 1; noteList[key] := FALSE; END; END; END; // Global Procedure StoreNoteOffs--just de-inlined for readability//----------------------------------------------//PROCEDURE StoreNoteOffs;BEGIN IF (midi.data1 > maxKey) THEN BEGIN maxKey := midi.data1; END; IF (midi.data1 < minKey) THEN BEGIN minKey := midi.data1; END; noteList[midi.data1] := TRUE;END;// Callback//----------------------------------------------// procedure Callback(n:integer);BEGIN if (n = hiNote) then begin hiVal := round(getValue(hiNote)); setValue(upper, hiVal); end else if (n = lowNote) then begin lowVal := round(getValue(lowNote)); setValue(lower, lowVal); end else if (n = learn) and (getValue(n) = 1) then begin learning:= TRUE; strace('learning...'); learnCount := 0; end else if (learnCount = 2) then begin // we've just learned, so we want to send out lower and upper learning := FALSE; learnCount := 0; strace(' finishedlearning'); end else begin // get input values octVal := trunc(getValue(octave)); semival := trunc(getValue(semi)); transpose := (octVal * 12) + semiVal; outputChannel := trunc(getValue(outChan)); droning := (getValue(drone) = 1); // see if any input is enabled.... noInput := TRUE; FOR inputNum := 0 to INPUT_COUNT - 1 DO BEGIN IF getValue(enables[inputNum]) = 1 THEN BEGIN isEnabled[inputNum] := TRUE; noInput := FALSE; END ELSE BEGIN isEnabled[inputNum] := FALSE; END; END; // release notes if the drone has just been turned off, or if all inputs and notes are off, or if the channel is changed IF ((n = drone) and (not(Droning))) OR ((noInput = TRUE) AND (isClear() = TRUE)) OR (n = outChan) THEN BEGIN strace('releasing notes'); release := true; // booleans to check in process disablable := true; END ELSE BEGIN setValue(instEnable, 1); END; end;END; //////////////////////////////////////////////////////// process//////////////////////////////////////////////////////PROCEDURE PROCESS;BEGIN notesOutCount := 0; otherOutCount := 0; if release then releaseNotes; FOR inputNum := 0 to INPUT_COUNT - 1 DO BEGIN midiInCount := getLength(midiIns[inputNum]); FOR byteNum := 0 TO (midiInCount - 1) DO BEGIN // process input getMidiArrayValue(midiIns[inputNum], byteNum, midi); midi.channel := outputChannel; if (learning) then begin IF (isNoteOn(midi)) and (learnCount = 0) THEN BEGIN lowVal := midi.data1; setValue(lower, lowVal ); learnCount := 1; setMidiArrayValue(otherOut, otherOutCount, midi); otherOutCount := otherOutCount + 1; strace('learnCount = ' + intToStr(learnCount)); END ELSE IF (isNoteOn(midi)) and (learnCount = 1) THEN BEGIN hiVal := midi.data1; setValue(upper, hiVal); learnCount := 2; learning := FALSE; // we've set our outs.... setMidiArrayValue(otherOut, otherOutCount, midi); otherOutCount := otherOutCount + 1; END; end else if (droning) then begin // basically ignore all midi when droning setMidiArrayValue(otherOut, otherOutCount, midi); otherOutCount := otherOutCount + 1; end else begin If isSusPed(midi) THEN BEGIN if (midi.data2 > 64) THEN BEGIN isSustained := true; END ELSE BEGIN isSustained := false; ReleaseNotes; // send noteoffs when the sus pedal is released END; END; IF isNoteOn(midi) AND (inRange(midi)) AND (isEnabled[inputNum]) THEN BEGIN //note on, sus on, store and send transList[midi.data1] := transpose; midi.data1 := midi.data1 + transpose; IF (isSustained = TRUE) THEN BEGIN StoreNoteOffs; setMidiArrayValue(notesOut, notesOutCount, midi); notesOutCount := notesOutCount + 1; END ELSE BEGIN // valid noteon, sus off, send it out setMidiArrayValue(notesOut, notesOutCount, midi); notesOutCount := notesOutCount + 1; END; END ELSE IF isNoteOff(midi) AND (isSustained = FALSE) THEN BEGIN // valid noteoff, sus off, send it out midi.data1 := midi.data1 + transList[midi.data1]; setMidiArrayValue(notesOut, notesOutCount, midi); notesOutCount := notesOutCount + 1; END ELSE IF isPitchBend(midi) THEN BEGIN // send PB along with the notes midi.channel := outputChannel; setMidiArrayValue(notesOut, notesOutCount, midi); notesOutCount := notesOutCount + 1; END ELSE IF (NOT(isNoteOn(midi))) AND (NOT(isNoteOff(midi))) AND (NOT(isPitchBend(midi))) THEN BEGIN //not a note, pb or sus pedal event setMidiArrayValue(otherOut, otherOutCount, midi); otherOutCount := otherOutCount + 1; END; end; END; END; setLength(notesOut, notesOutCount); setLength(otherOut, otherOutCount); if disablable then setValue(instEnable, 0); END;
]]>
And I finally got around to checking the drone out, and it actually works. Sort of. Problem is, the noteOffs are not going out the output, even though my strace shows the code is getting called with correct values. So I'm wondering if this is somehow related to the problems above.
I tried moving the noteOut count resetting to the beginning of process, but that just gave me a bunch of stuck notes.
So thanks for any tips. This is pretty close to working!(*/////////////////////////////////////////////////////// CHANNEL // Version 2009-11-21; author: eric moon//// based on work by Bsork and amiga909//////////////////////////////////////////////////////*)// This 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 AT and send them out a separate output// read CC64 values (or a CC of your choice) to withhold noteoffs until the sus pedal is released.// limit to minimum and maximum notes--one range affects all inputs, as it's assumed you'll typically be using one input at a time// 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 new notesOns as long as it is held// It is designed to function as part of a mixer channel strip, running between several keyboards and a vsti.// When the 'learn' function is enabled, notes are sent out output 2// the first note sets the lower range, the second note sets the upper limit.// when both notes are sent, learn is disabled, and notes go to output 1 as usual.CONST SUS_PED= 64; //change if you use an unorthodox CC for sustaining.CONST INPUT_COUNT = 2; //allows up to 16 inputs, one per channelCONST NOTE_ON = 144;CONST NOTE_OFF = 128;CONST CONTROL = 176;CONST PITCHBEND = 224;VAR noteList : ARRAY OF boolean;VAR transList : ARRAY OF integer;VAR midi,noteOff : TMidi; var midiIns : ARRAY OF Tparameter;var enables : ARRAY OF TParameter;var notesOut : Tparameter;var otherOut : Tparameter; // all CCs except the sustain value go out this output. So does AT and PgChvar octave : TParameter;var semi : TParameter;var hiNote : TParameter;var lowNote : TParameter;var drone : TParameter; // sustains, but ignores new noteonsvar outChan : TParameter; // everything goes out one channel. It's a channel strip. Use more if you need other channels!var instEnable: TParameter;var lower : Tparameter;var upper : Tparameter; var learn : TParameter;VAR octVal, semiVal, transpose : integer;VAR hiVal, lowVal : integer; VAR midiInCount : integer;VAR otherOutCount, notesOutCount : integer;VAR key, inputNum, byteNum : integer; VAR minChn, maxChn, minKey, maxKey : integer;VAR outputChannel : integer;VAR isSustained,noInput : boolean;VAR isEnabled : Array of boolean;VAR learning : boolean;VAR droning : boolean;var learnCount : integer;//////////////////////////////////////////////////////// initialize//////////////////////////////////////////////////////PROCEDURE init; BEGIN minChn := INPUT_COUNT - 1; // these are initially set to their opposite extremes.... maxChn := 0; minKey := 128; maxKey := 0; isSustained := FALSE; setArrayLength(noteList, 128); FOR key:=0 TO 127 DO BEGIN noteList[key]:=FALSE; END; SetArrayLength(transList, 128); FOR key:=0 TO 127 DO BEGIN transList[key]:=0; END; setArrayLength(midiIns, INPUT_COUNT); setArrayLength(enables, INPUT_COUNT); FOR inputNum := 0 TO INPUT_COUNT - 1 DO BEGIN enables[inputNum] := CreateParam('enable ' + intToStr(inputNum + 1),ptSwitch); SetValue(enables[inputNum], 1); SetIsOutPut(enables[inputNum],false); END; octave := CreateParam('octave',ptDataFader); SetIsOutPut(octave,false); semi := CreateParam('semi',ptDataFader); SetIsOutPut(semi,false); SetFormat(octave,'%.0f'); SetMin(octave,-4); SetMax(octave,4); SetFormat(semi,'%.0f'); SetMin(semi,-7); SetMax(semi,7); hiNote := CreateParam('high note',ptMidiNoteFader); SetIsOutPut(hiNote,false); lowNote := CreateParam('low note',ptMidiNoteFader); SetIsOutPut(lowNote,false); outChan := CreateParam('output chan', ptDataFader); SetIsOutPut(outchan,false); SetFormat(outChan,'%.0f'); SetMin(outChan,1); SetMax(outChan,16); SetValue(lowNote, 10); SetValue(hiNote, 115); drone := CreateParam('drone', ptSwitch); SetIsOutput(drone,false); instEnable := CreateParam('inst enable', ptSwitch); SetIsInput(instEnable,false); FOR inputNum := 0 TO INPUT_COUNT - 1 DO BEGIN midiIns[inputNum] := CreateParam('MIDIin ' + intToStr(inputNum + 1) ,ptMidi); SetIsOutPut(midiIns[inputNum],false); END; notesOut := CreateParam('NoteMIDI',ptMidi); SetIsInput(notesOut,false); otherOut := CreateParam('otherMIDI',ptMidi); SetIsInput(otherOut,false); learn := CreateParam('learn',ptButton); SetIsOutPut(learn,false); lower := CreateParam('lower',ptMidiNoteFader); SetIsInPut(lower,false); upper := CreateParam('upper',ptMidiNoteFader); SetIsInPut(upper,false); notesOutCount := 0; otherOutCount := 0; learnCount := 0; SetArrayLength(isEnabled, INPUT_COUNT); END;// <F> isNoteOn: //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// FUNCTION isNoteOn(midi: tMidi): boolean;BEGIN IF (midi.msg = NOTE_ON) AND (midi.data2>0) THEN BEGIN result := true; END ELSE BEGIN result := false; END;END;// <F> isNoteOff: //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// FUNCTION isNoteOff(midi: tMidi): boolean;BEGIN IF (midi.msg = NOTE_OFF) OR ((midi.msg = NOTE_ON) AND (midi.data2 = 0)) THEN BEGIN result := true; END ELSE BEGIN result := false; END;END; // <F> isSusPed: //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// FUNCTION isSusPed(midi: tMidi) : boolean;BEGIN IF (midi.msg = CONTROL) AND (midi.data1 = SUS_PED) THEN BEGIN result := true; END ELSE BEGIN result := false; END;END; // <F> isPitchBend: //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// FUNCTION isPitchBend(midi: tMidi): boolean;BEGIN IF (midi.msg = PITCHBEND) THEN BEGIN result := true; END ELSE BEGIN result := false; END;END;// <F> global function inRange--eliminates only noteons outside the range limits FUNCTION inRange(midi: tMidi) : boolean;BEGIN IF (isNoteOn(midi)) AND (midi.data1 > lowVal) AND (midi.data1 < hiVal) THEN BEGIN result := TRUE; END ELSE BEGIN result := FALSE; END; END;// <F> isClear//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^//FUNCTION isClear() : boolean; // can we stop this loop as soon as a key = true?? Didn't like 'while'VAR clear : boolean;BEGIN clear := TRUE; BEGIN FOR key:= minKey TO maxKey DO BEGIN IF (noteList[key] = TRUE) THEN BEGIN clear := FALSE; END; END; END; result := clear; END;// <F> ReleaseNotes --when you release the sustain, or release the drone, or change the output channel//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^//PROCEDURE ReleaseNotes;BEGIN FOR key:= minKey TO maxKey DO BEGIN IF (noteList[key] = TRUE) THEN BEGIN noteOff.msg := NOTE_OFF; noteOff.channel := outputChannel; // byte is a conversion--is this needed? noteOff.data1 := key; noteOff.data2 := 0; setMidiArrayValue(notesOut, notesOutCount, noteOff);strace('sending noteOff for ' + intToStr(key)); notesOutCount := notesOutCount + 1; noteList[key] := FALSE; END; END; END; // Global Procedure StoreNoteOffs--just de-inlined for readability//----------------------------------------------//PROCEDURE StoreNoteOffs;BEGIN IF (midi.data1 > maxKey) THEN BEGIN maxKey := midi.data1; END; IF (midi.data1 < minKey) THEN BEGIN minKey := midi.data1; END; noteList[midi.data1] := TRUE;END;// Callback//----------------------------------------------// procedure Callback(n:integer);BEGIN if (n = hiNote) then begin hiVal := round(getValue(hiNote)); setValue(upper, hiVal); end else if (n = lowNote) then begin lowVal := round(getValue(lowNote)); setValue(lower, lowVal); end else if (n = learn) and (getValue(n) = 1) then begin learning:= TRUE; strace('learning...'); learnCount := 0; end else if (learnCount = 2) then begin learning := FALSE; learnCount := 0; strace(' finishedlearning'); end else begin // get input values octVal := trunc(getValue(octave)); semival := trunc(getValue(semi)); transpose := (octVal * 12) + semiVal; outputChannel := trunc(getValue(outChan)); droning := (getValue(drone) = 1); // see if any input is enabled.... noInput := TRUE; FOR inputNum := 0 to INPUT_COUNT - 1 DO BEGIN IF getValue(enables[inputNum]) = 1 THEN BEGIN isEnabled[inputNum] := TRUE; noInput := FALSE; END ELSE BEGIN isEnabled[inputNum] := FALSE; END; END; // release notes if the drone has just been turned off, or if all inputs and notes are off, or if the channel is changed IF ((n = drone) and (not(Droning))) OR ((noInput = TRUE) AND (isClear() = TRUE)) OR (n = outChan) THEN BEGIN strace('releasing notes'); releaseNotes; setValue(instEnable, 0); END ELSE BEGIN setValue(instEnable, 1); END; end;END; //////////////////////////////////////////////////////// process//////////////////////////////////////////////////////PROCEDURE PROCESS;BEGIN notesOutCount := 0; otherOutCount := 0; FOR inputNum := 0 to INPUT_COUNT - 1 DO BEGIN midiInCount := getLength(midiIns[inputNum]); FOR byteNum := 0 TO (midiInCount - 1) DO BEGIN // process input getMidiArrayValue(midiIns[inputNum], byteNum, midi); midi.channel := outputChannel; if (learning) then begin IF (isNoteOn(midi)) and (learnCount = 0) THEN BEGIN lowVal := midi.data1; setValue(lower, lowVal ); learnCount := 1; setMidiArrayValue(otherOut, otherOutCount, midi); otherOutCount := otherOutCount + 1; strace('learnCount = ' + intToStr(learnCount)); END ELSE IF (isNoteOn(midi)) and (learnCount = 1) THEN BEGIN hiVal := midi.data1; setValue(upper, hiVal); learnCount := 2; learning := FALSE; // we've set our outs.... setMidiArrayValue(otherOut, otherOutCount, midi); otherOutCount := otherOutCount + 1; END; end else if (droning) then begin // basically ignore all midi when droning setMidiArrayValue(otherOut, otherOutCount, midi); otherOutCount := otherOutCount + 1; end else begin If isSusPed(midi) THEN BEGIN if (midi.data2 > 64) THEN BEGIN isSustained := true; END ELSE BEGIN isSustained := false; ReleaseNotes; // send noteoffs when the sus pedal is released END; END; IF isNoteOn(midi) AND (inRange(midi)) AND (isEnabled[inputNum]) THEN BEGIN //note on, sus on, store and send transList[midi.data1] := transpose; midi.data1 := midi.data1 + transpose; IF (isSustained = TRUE) THEN BEGIN StoreNoteOffs; setMidiArrayValue(notesOut, notesOutCount, midi); notesOutCount := notesOutCount + 1; END ELSE BEGIN // valid noteon, sus off, send it out setMidiArrayValue(notesOut, notesOutCount, midi); notesOutCount := notesOutCount + 1; END; END ELSE IF isNoteOff(midi) AND (isSustained = FALSE) THEN BEGIN // valid noteoff, sus off, send it out midi.data1 := midi.data1 + transList[midi.data1]; setMidiArrayValue(notesOut, notesOutCount, midi); notesOutCount := notesOutCount + 1; END ELSE IF isPitchBend(midi) THEN BEGIN // send PB along with the notes midi.channel := outputChannel; setMidiArrayValue(notesOut, notesOutCount, midi); notesOutCount := notesOutCount + 1; END ELSE IF (NOT(isNoteOn(midi))) AND (NOT(isNoteOff(midi))) AND (NOT(isPitchBend(midi))) THEN BEGIN //not a note, pb or sus pedal event setMidiArrayValue(otherOut, otherOutCount, midi); otherOutCount := otherOutCount + 1; END; end; END; END; setLength(notesOut, notesOutCount); setLength(otherOut, otherOutCount); END;
]]>
I will try to implement stuff like this, but the more straight-forward stuff like filtering, transposition, rerouting and value scaling will have the priority.
]]>
]]>
There are some things that MungRack do that I have no plans of implementing, but there are also stuff that I - from reading the docs - don't think it will do; like the sustain/sustenotu/hold stuff mentioned before in this topic. I will also try to do my best to avoid hanging notes, even when changing channel/note range/transpose/output parameters when notes are sounding.
Just to recap a little; what I'm working on is a patch with a script to handle various filters and transformers, and I also plan to create smaller, single function version patches with most, if not all, the transformers etc.
Still got a lot of work to do, I'm afraid...
]]>
]]>
Statistics: Posted by woodslanding — 26 Nov 2009, 20:46
Statistics: Posted by bsork — 26 Nov 2009, 11:50
Statistics: Posted by woodslanding — 26 Nov 2009, 10:28
CODE:
i := 0;WHILE i < cnt DO BEGIN do_something... i := i + 1;END;Statistics: Posted by bsork — 26 Nov 2009, 09:41
Statistics: Posted by woodslanding — 26 Nov 2009, 08:56
CODE:
(*/////////////////////////////////////////////////////// CHANNEL // Version 2009-11-21; author: eric moon//// based on work by Bsork and amiga909//////////////////////////////////////////////////////*)// This 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 AT and send them out a separate output// read CC64 values (or a CC of your choice) to withhold noteoffs until the sus pedal is released.// limit to minimum and maximum notes--one range affects all inputs, as it's assumed you'll typically be using one input at a time// 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 new notesOns as long as it is held// It is designed to function as part of a mixer channel strip, running between several keyboards and a vsti.CONST SUS_PED= 64; //change if you use an unorthodox CC for sustaining.CONST INPUT_COUNT = 2; //allows up to 16 inputs, one per channelCONST NOTE_ON = 144;CONST NOTE_OFF = 128;CONST CONTROL = 176;CONST PITCHBEND = 224;VAR noteList : ARRAY OF boolean;VAR transList : ARRAY OF integer;VAR midi,noteOff : TMidi; var midiIns : ARRAY OF Tparameter;var enables : ARRAY OF TParameter;var notesOut : Tparameter;var otherOut : Tparameter; // all CCs except the sustain value go out this output. So does AT and PgChvar octave : TParameter;var semi : TParameter;var hiNote : TParameter;var lowNote : TParameter;var drone : TParameter; // sustains, but ignores new noteonsvar outChan : TParameter; // everything goes out one channel. It's a channel strip. Use more if you need other channels!var instBypass: TParameter; VAR octVal, semiVal, transpose : integer;VAR hiVal, lowVal : integer; VAR midiInCount : integer;VAR otherOutCount, notesOutCount : integer;VAR key, inputNum, byteNum : integer; VAR minChn, maxChn, minKey, maxKey : integer;VAR outputChannel : integer;VAR isSustained,noInput : boolean;VAR isEnabled : Array of boolean;//////////////////////////////////////////////////////// initialize//////////////////////////////////////////////////////PROCEDURE init; BEGIN minChn := INPUT_COUNT - 1; // these are initially set to their opposite extremes.... maxChn := 0; minKey := 128; maxKey := 0; isSustained := FALSE; setArrayLength(noteList, 128); FOR key:=0 TO 127 DO BEGIN noteList[key]:=FALSE; END; SetArrayLength(transList, 128); FOR key:=0 TO 127 DO BEGIN transList[key]:=0; END; setArrayLength(midiIns, INPUT_COUNT); setArrayLength(enables, INPUT_COUNT); FOR inputNum := 0 TO INPUT_COUNT - 1 DO BEGIN enables[inputNum] := CreateParam('enable ' + intToStr(inputNum + 1),ptSwitch); SetValue(enables[inputNum], 1); SetIsOutPut(enables[inputNum],false); END; octave := CreateParam('octave',ptDataFader); SetIsOutPut(octave,false); semi := CreateParam('semi',ptDataFader); SetIsOutPut(semi,false); SetFormat(octave,'%.0f'); SetMin(octave,-4); SetMax(octave,4); SetFormat(semi,'%.0f'); SetMin(semi,-7); SetMax(semi,7); hiNote := CreateParam('high note',ptMidiNoteFader); SetIsOutPut(hiNote,false); lowNote := CreateParam('low note',ptMidiNoteFader); SetIsOutPut(lowNote,false); outChan := CreateParam('output chan', ptDataFader); SetIsOutPut(outchan,false); SetFormat(outChan,'%.0f'); SetMin(outChan,1); SetMax(outChan,16); SetValue(lowNote, 10); SetValue(hiNote, 115); drone := CreateParam('drone', ptSwitch); SetIsOutput(drone,false); instBypass := CreateParam('inst bypass', ptSwitch); SetIsInput(instBypass,false); FOR inputNum := 0 TO INPUT_COUNT - 1 DO BEGIN midiIns[inputNum] := CreateParam('MIDIin ' + intToStr(inputNum + 1) ,ptMidi); SetIsOutPut(midiIns[inputNum],false); END; notesOut := CreateParam('Notes Out',ptMidi); SetIsInput(notesOut,false); otherOut := CreateParam('other Out',ptMidi); SetIsInput(otherOut,false); notesOutCount := 0; otherOutCount := 0; SetArrayLength(isEnabled, INPUT_COUNT); END;// <F> isNoteOn: //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// FUNCTION isNoteOn(midi: tMidi): boolean;BEGIN IF (midi.msg = NOTE_ON) AND (midi.data2>0) THEN BEGIN result := true; END ELSE BEGIN result := false; END;END;// <F> isNoteOff: //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// FUNCTION isNoteOff(midi: tMidi): boolean;BEGIN IF (midi.msg = NOTE_OFF) OR ((midi.msg = NOTE_ON) AND (midi.data2 = 0)) THEN BEGIN result := true; END ELSE BEGIN result := false; END;END; // <F> isSusPed: //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// FUNCTION isSusPed(midi: tMidi) : boolean;BEGIN IF (midi.msg = CONTROL) AND (midi.data1 = SUS_PED) THEN BEGIN result := true; END ELSE BEGIN result := false; END;END; // <F> isPitchBend: //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// FUNCTION isPitchBend(midi: tMidi): boolean;BEGIN IF (midi.msg = PITCHBEND) THEN BEGIN result := true; END ELSE BEGIN result := false; END;END;// <F> global function inRange--eliminates only noteons outside the range limits FUNCTION inRange(midi: tMidi) : boolean;BEGIN IF (isNoteOn(midi)) AND (midi.data1 > lowVal) AND (midi.data1 < hiVal) THEN BEGIN result := TRUE; END ELSE BEGIN result := FALSE; END; END;// <F> isClear//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^//FUNCTION isClear() : boolean; // can we stop this loop as soon as a key = true?? Didn't like 'while'VAR clear : boolean;BEGIN clear := TRUE; BEGIN FOR key:= minKey TO maxKey DO BEGIN IF (noteList[key] = TRUE) THEN BEGIN clear := FALSE; END; END; END; result := clear; END;// <F> ReleaseNotes --when you release the sustain, or release the drone, or change the output channel//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^//PROCEDURE ReleaseNotes;BEGIN FOR key:= minKey TO maxKey DO BEGIN IF (noteList[key] = TRUE) THEN BEGIN noteOff.msg := NOTE_OFF; noteOff.channel := outputChannel; // byte is a conversion--is this needed? noteOff.data1 := key; noteOff.data2 := 0; setMidiArrayValue(notesOut, notesOutCount, noteOff); //danger when called from callback? notesOutCount := notesOutCount + 1; noteList[key] := FALSE; END; END; END; // Global Procedure StoreNoteOffs--just de-inlined for readability//----------------------------------------------//PROCEDURE StoreNoteOffs;BEGIN IF (midi.data1 > maxKey) THEN BEGIN maxKey := midi.data1; END; IF (midi.data1 < minKey) THEN BEGIN minKey := midi.data1; END; noteList[midi.data1] := TRUE;END;// Callback//----------------------------------------------// procedure Callback(n:integer);BEGIN // get input values hiVal := trunc(getValue(hiNote)); lowVal := trunc(getValue(lowNote)); octVal := trunc(getValue(octave)); semival := trunc(getValue(semi)); transpose := (octVal * 12) + semiVal;writeln('transpose = ' + intToStr(transpose)); outputChannel := trunc(getValue(outChan)); // see if any input is enabled.... noInput := TRUE; FOR inputNum := 0 to INPUT_COUNT - 1 DO BEGIN IF getValue(enables[inputNum]) = 1 THEN BEGIN isEnabled[inputNum] := TRUE; noInput := FALSE; END ELSE BEGIN isEnabled[inputNum] := FALSE; END; END; // release notes if the drone has just been turned off, or if all inputs and notes are off, or if the channel is changed IF ((n = drone) and (getValue(drone) = 0)) OR ((noInput = TRUE) AND (isClear() = TRUE)) OR (n = outChan) THEN BEGIN releaseNotes; // can I call this from callback? setValue(instBypass, 1); END ELSE BEGIN setValue(instBypass, 0); END;END; //////////////////////////////////////////////////////// process//////////////////////////////////////////////////////PROCEDURE PROCESS;BEGIN notesOutCount := 0; otherOutCount := 0; FOR inputNum := 0 to INPUT_COUNT - 1 DO BEGIN midiInCount := getLength(midiIns[inputNum]); FOR byteNum := 0 TO (midiInCount - 1) DO BEGIN // process input getMidiArrayValue(midiIns[inputNum], byteNum, midi); midi.channel := outputChannel; If isSusPed(midi) THEN BEGIN if (midi.data2 > 64) THEN BEGIN isSustained := true; END ELSE BEGIN isSustained := false; ReleaseNotes; // send noteoffs when the sus pedal is released END; END; IF isNoteOn(midi) AND (inRange(midi)) AND (isEnabled[inputNum]) THEN BEGIN //note on, sus on, store and send transList[midi.data1] := transpose; midi.data1 := midi.data1 + transpose; IF (isSustained = TRUE) THEN BEGIN StoreNoteOffs; setMidiArrayValue(notesOut, notesOutCount, midi); notesOutCount := notesOutCount + 1; END ELSE BEGIN // valid noteon, sus off, send it out setMidiArrayValue(notesOut, notesOutCount, midi); notesOutCount := notesOutCount + 1; END; END ELSE IF isNoteOff(midi) AND (isSustained = FALSE) THEN BEGIN // valid noteoff, sus off, send it out midi.data1 := midi.data1 + transList[midi.data1]; setMidiArrayValue(notesOut, notesOutCount, midi); notesOutCount := notesOutCount + 1; END ELSE IF isPitchBend(midi) THEN BEGIN // send PB along with the notes midi.channel := outputChannel; setMidiArrayValue(notesOut, notesOutCount, midi); notesOutCount := notesOutCount + 1; END ELSE IF (NOT(isNoteOn(midi))) AND (NOT(isNoteOff(midi))) AND (NOT(isPitchBend(midi))) THEN BEGIN //not a note, pb or sus pedal event setMidiArrayValue(otherOut, otherOutCount, midi); otherOutCount := otherOutCount + 1; END; END; END; setLength(notesOut, notesOutCount); setLength(otherOut, otherOutCount); END;Statistics: Posted by woodslanding — 26 Nov 2009, 08:26
Statistics: Posted by bsork — 25 Nov 2009, 08:53
Statistics: Posted by woodslanding — 25 Nov 2009, 05:24
Statistics: Posted by woodslanding — 25 Nov 2009, 04:56
Statistics: Posted by bsork — 24 Nov 2009, 14:31
CODE:
(*/////////////////////////////////////////////////////// CHANNEL // Version 2009-11-21; author: eric moon//// based on work by Bsork and amiga909//////////////////////////////////////////////////////*)// This 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 AT and send them out a separate output// read CC64 values (or a CC of your choice) to withhold noteoffs until the sus pedal is released.// limit to minimum and maximum notes--one range affects all inputs, as it's assumed you'll typically be using one input at a time// 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 new notesOns as long as it is held// It is designed to function as part of a mixer channel strip, running between several keyboards and a vsti.CONST SUS_PED= 64; //change if you use an unorthodox CC for sustaining.CONST INPUT_COUNT = 2; //number of midi note sourcesCONST NOTE_ON = 144;CONST NOTE_OFF = 128;CONST CONTROL = 176;CONST PITCHBEND = 224;VAR noteList : ARRAY OF boolean;VAR transList : ARRAY OF integer;VAR midi,noteOff : TMidi; var midiIns : ARRAY OF Tparameter;var enables : ARRAY OF TParameter;var notesOut : Tparameter;var otherOut : Tparameter; // all CCs except the sustain value go out this output. So does AT and PgChvar octave : TParameter;var semi : TParameter;var hiNote : TParameter;var lowNote : TParameter;var drone : TParameter; // sustains, but ignores new noteonsvar outChan : TParameter; // everything goes out one channel. It's a channel strip. Use more if you need other channels!var instBypass: TParameter; VAR octVal, semiVal, transpose : integer;VAR hiVal, lowVal : integer; VAR midiInCount : integer;VAR otherOutCount, notesOutCount : integer;VAR key, inputNum, byteNum : integer; VAR minChn, maxChn, minKey, maxKey : integer;VAR outputChannel : integer;VAR isSustained,noInput : boolean;VAR isEnabled : Array of boolean;//////////////////////////////////////////////////////// initialize//////////////////////////////////////////////////////PROCEDURE init; BEGIN minChn := INPUT_COUNT - 1; // these are initially set to their opposite extremes.... maxChn := 0; minKey := 128; maxKey := 0; isSustained := FALSE; setArrayLength(noteList, 128); FOR key:=0 TO 127 DO BEGIN noteList[key]:=FALSE; END; SetArrayLength(transList, 128); FOR key:=0 TO 127 DO BEGIN transList[key]:=0; END; setArrayLength(midiIns, INPUT_COUNT); setArrayLength(enables, INPUT_COUNT); FOR inputNum := 0 TO INPUT_COUNT - 1 DO BEGIN enables[inputNum] := CreateParam('enable ' + intToStr(inputNum + 1),ptSwitch); SetValue(enables[inputNum], 1); SetIsOutPut(enables[inputNum],false); END; octave := CreateParam('octave',ptDataFader); SetIsOutPut(octave,false); semi := CreateParam('semi',ptDataFader); SetIsOutPut(semi,false); SetFormat(octave,'%.0f'); SetMin(octave,-4); SetMax(octave,4); SetFormat(semi,'%.0f'); SetMin(semi,-7); SetMax(semi,7); hiNote := CreateParam('high note',ptMidiNoteFader); SetIsOutPut(hiNote,false); lowNote := CreateParam('low note',ptMidiNoteFader); SetIsOutPut(lowNote,false); outChan := CreateParam('output chan', ptDataFader); SetIsOutPut(outchan,false); SetFormat(outChan,'%.0f'); SetMin(outChan,1); SetMax(outChan,16); SetValue(lowNote, 10); SetValue(hiNote, 115); drone := CreateParam('drone', ptSwitch); SetIsOutput(drone,false); instBypass := CreateParam('inst bypass', ptSwitch); SetIsInput(instBypass,false); FOR inputNum := 0 TO INPUT_COUNT - 1 DO BEGIN midiIns[inputNum] := CreateParam('MIDIin ' + intToStr(inputNum + 1) ,ptMidi); SetIsOutPut(midiIns[inputNum],false); END; notesOut := CreateParam('Notes Out',ptMidi); SetIsInput(notesOut,false); otherOut := CreateParam('other Out',ptMidi); SetIsInput(otherOut,false); SetArrayLength(isEnabled, INPUT_COUNT); END;// <F> isNoteOn: //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// FUNCTION isNoteOn(midi: tMidi): boolean;BEGIN IF (midi.msg = NOTE_ON) AND (midi.data2>0) THEN BEGIN result := true; END ELSE BEGIN result := false; END;END;// <F> isNoteOff: //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// FUNCTION isNoteOff(midi: tMidi): boolean;BEGIN IF (midi.msg = NOTE_OFF) OR ((midi.msg = NOTE_ON) AND (midi.data2 = 0)) THEN BEGIN result := true; END ELSE BEGIN result := false; END;END; // <F> isSusPed: //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// FUNCTION isSusPed(midi: tMidi) : boolean;BEGIN IF (midi.msg = CONTROL) AND (midi.data1 = SUS_PED) THEN BEGIN result := true; END ELSE BEGIN result := false; END;END; // <F> isPitchBend: //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// FUNCTION isPitchBend(midi: tMidi): boolean;BEGIN IF (midi.msg = PITCHBEND) THEN BEGIN result := true; END ELSE BEGIN result := false; END;END;// <F> global function inRange--eliminates only noteons outside the range limits FUNCTION inRange(midi: tMidi) : boolean;BEGIN IF (isNoteOn(midi)) AND (midi.data1 > lowVal) AND (midi.data1 < hiVal) THEN BEGIN result := TRUE; END ELSE BEGIN result := FALSE; END; END;// <F> isClear//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^//FUNCTION isClear() : boolean; // can we stop this loop as soon as a key = true?? Didn't like 'while'VAR clear : boolean;BEGIN clear := TRUE; BEGIN FOR key:= minKey TO maxKey DO BEGIN IF (noteList[key] = TRUE) THEN BEGIN clear := FALSE; END; END; END; result := clear; END;// <F> ReleaseNotes --when you release the sustain, or release the drone, or change the output channel//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^//PROCEDURE ReleaseNotes;BEGIN FOR key:= minKey TO maxKey DO BEGIN IF (noteList[key] = TRUE) THEN BEGIN noteOff.msg := NOTE_OFF; noteOff.channel := outputChannel; // byte is a conversion--is this needed? noteOff.data1 := key; noteOff.data2 := 0; setMidiArrayValue(notesOut, notesOutCount, noteOff); //danger when called from callback? notesOutCount := notesOutCount + 1; noteList[key] := FALSE; END; END; END; // Global Procedure StoreNoteOffs--just de-inlined for readability//----------------------------------------------//PROCEDURE StoreNoteOffs;BEGIN IF (midi.data1 > maxKey) THEN BEGIN maxKey := midi.data1; END; IF (midi.data1 < minKey) THEN BEGIN minKey := midi.data1; END; noteList[midi.data1] := TRUE;END;// Callback//----------------------------------------------// procedure Callback(n:integer);BEGIN // get input values hiVal := trunc(getValue(hiNote)); lowVal := trunc(getValue(lowNote)); octVal := trunc(getValue(octave)); semival := trunc(getValue(semi)); transpose := (octVal * 12) + semiVal;writeln('transpose = ' + intToStr(transpose)); outputChannel := trunc(getValue(outChan)); // see if any input is enabled.... noInput := TRUE; FOR inputNum := 0 to INPUT_COUNT - 1 DO BEGIN IF getValue(enables[inputNum]) = 1 THEN BEGIN isEnabled[inputNum] := TRUE; noInput := FALSE; END ELSE BEGIN isEnabled[inputNum] := FALSE; END; END; // release notes if the drone has just been turned off, or if all inputs and notes are off, or if the channel is changed IF ((n = drone) and (getValue(drone) = 0)) OR ((noInput = TRUE) AND (isClear() = TRUE)) OR (n = outChan) THEN BEGIN releaseNotes; // can I call this from callback? setValue(instBypass, 1); END ELSE BEGIN setValue(instBypass, 0); END;END; //////////////////////////////////////////////////////// process//////////////////////////////////////////////////////PROCEDURE PROCESS;BEGIN FOR inputNum := 0 to INPUT_COUNT - 1 DO BEGIN midiInCount := getLength(midiIns[inputNum]); IF (midiInCount > 0) THEN BEGIN notesOutCount := 0; otherOutCount := 0; FOR byteNum := 0 TO (midiInCount - 1) DO BEGIN // process input getMidiArrayValue(midiIns[inputNum], byteNum, midi); midi.channel := outputChannel; If isSusPed(midi) THEN BEGIN if (midi.data2 > 64) THEN BEGIN isSustained := true; END ELSE BEGIN isSustained := false; ReleaseNotes; // send noteoffs when the sus pedal is released END; END; IF isNoteOn(midi) AND (inRange(midi)) AND (isEnabled[inputNum]) THEN BEGIN //note on, sus on, store and send IF (isSustained = TRUE) THEN BEGIN StoreNoteOffs; setMidiArrayValue(notesOut, notesOutCount, midi); notesOutCount := notesOutCount + 1; END ELSE BEGIN // valid noteon, sus off, send it out transList[midi.data1] := transpose; midi.data1 := midi.data1 + transpose; setMidiArrayValue(notesOut, notesOutCount, midi); notesOutCount := notesOutCount + 1; END; END ELSE IF isNoteOff(midi) AND (isSustained = FALSE) THEN BEGIN // valid noteoff, sus off, send it out midi.data1 := midi.data1 + transList[midi.data1]; setMidiArrayValue(notesOut, notesOutCount, midi); notesOutCount := notesOutCount + 1; END ELSE IF isPitchBend(midi) THEN BEGIN // send PB along with the notes midi.channel := outputChannel; setMidiArrayValue(notesOut, notesOutCount, midi); notesOutCount := notesOutCount + 1; END ELSE IF (NOT(isNoteOn(midi))) AND (NOT(isNoteOff(midi))) AND (NOT(isPitchBend(midi))) THEN BEGIN //not a note, pb or sus pedal event setMidiArrayValue(otherOut, otherOutCount, midi); otherOutCount := otherOutCount + 1; END; END; // process input setLength(notesOut, notesOutCount); setLength(otherOut, otherOutCount); END ELSE BEGIN setLength(notesOut,0); setLength(otherOut, 0); END; END; END;Statistics: Posted by woodslanding — 24 Nov 2009, 09:00
CODE:
VAR pParam1, pParam2, pParam3 : tParameter;VAR param1, param2, param3 : single;VAR doUpdate : boolean;....PROCEDURE Init;BEGIN pParam1 := CreateParam('param 1', ... pParam2 := CreateParam('param 2', ... pParam3 := CreateParam('param 3', ... doUpdate := FALSE;END;PROCEDURE GetParams;BEGIN param1 := GetValue(pParam1); param2 := GetValue(pParam2); param3 := GetValue(pParam3); END;PROCEDURE Callback(n ; integer);BEGIN // You can of course use IF-statements instead of CASE CASE n OF pParam1 : doUpdate := TRUE; pParam2 : doUpdate := TRUE; pParam3 : doUpdate := TRUE; END;END;PROCEDURE Process;BEGIN IF (doUpdate) THEN BEGIN GetParams; doUpdate := FALSE; END; ...END;Statistics: Posted by bsork — 23 Nov 2009, 21:52
Statistics: Posted by woodslanding — 10 Jan 2010, 11:47
CODE:
(*/////////////////////////////////////////////////////// CHANNEL // Version 2009-11-21; author: eric moon//// based on work by Bsork and amiga909//////////////////////////////////////////////////////*)// This 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 AT and send them out a separate output// read CC64 values (or a CC of your choice) to withhold noteoffs until the sus pedal is released.// limit to minimum and maximum notes--one range affects all inputs, as it's assumed you'll typically be using one input at a time// 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 new notesOns as long as it is held// It is designed to function as part of a mixer channel strip, running between several keyboards and a vsti.// When the 'learn' function is enabled, notes are sent out output 2// the first note sets the lower range, the second note sets the upper limit.// when both notes are sent, learn is disabled, and notes go to output 1 as usual.CONST SUS_PED= 64; //change if you use an unorthodox CC for sustaining.CONST INPUT_COUNT = 2; //allows up to 16 inputs, one per channelCONST NOTE_ON = 144;CONST NOTE_OFF = 128;CONST CONTROL = 176;CONST PITCHBEND = 224;VAR noteList : ARRAY OF boolean;VAR transList : ARRAY OF integer;VAR midi,noteOff : TMidi; var midiIns : ARRAY OF Tparameter;var enables : ARRAY OF TParameter;var notesOut : Tparameter;var otherOut : Tparameter; // all CCs except the sustain value go out this output. So does AT and PgChvar octave : TParameter;var semi : TParameter;var hiNote : TParameter;var lowNote : TParameter;var drone : TParameter; // sustains, but ignores new noteonsvar outChan : TParameter; // everything goes out one channel. It's a channel strip. Use more if you need other channels!var instEnable: TParameter;var lower : Tparameter;var upper : Tparameter; var learn : TParameter;VAR octVal, semiVal, transpose : integer;VAR hiVal, lowVal : integer; VAR midiInCount : integer;VAR otherOutCount, notesOutCount : integer;VAR key, inputNum, byteNum : integer; VAR minChn, maxChn, minKey, maxKey : integer;VAR outputChannel : integer;VAR isSustained,noInput : boolean;VAR isEnabled : Array of boolean;VAR learning : boolean;VAR droning : boolean;VAR release : boolean;VAR disablable : boolean;var learnCount : integer;//////////////////////////////////////////////////////// initialize//////////////////////////////////////////////////////PROCEDURE init; BEGIN minChn := INPUT_COUNT - 1; // these are initially set to their opposite extremes.... maxChn := 0; minKey := 128; maxKey := 0; isSustained := FALSE; setArrayLength(noteList, 128); FOR key:=0 TO 127 DO BEGIN noteList[key]:=FALSE; END; SetArrayLength(transList, 128); FOR key:=0 TO 127 DO BEGIN transList[key]:=0; END; setArrayLength(midiIns, INPUT_COUNT); setArrayLength(enables, INPUT_COUNT); FOR inputNum := 0 TO INPUT_COUNT - 1 DO BEGIN enables[inputNum] := CreateParam('enable ' + intToStr(inputNum + 1),ptSwitch); SetValue(enables[inputNum], 1); SetIsOutPut(enables[inputNum],false); END; octave := CreateParam('octave',ptDataFader); SetIsOutPut(octave,false); semi := CreateParam('semi',ptDataFader); SetIsOutPut(semi,false); SetFormat(octave,'%.0f'); SetMin(octave,-4); SetMax(octave,4); SetFormat(semi,'%.0f'); SetMin(semi,-7); SetMax(semi,7); hiNote := CreateParam('high note',ptMidiNoteFader); SetIsOutPut(hiNote,false); lowNote := CreateParam('low note',ptMidiNoteFader); SetIsOutPut(lowNote,false); outChan := CreateParam('output chan', ptDataFader); SetIsOutPut(outchan,false); SetFormat(outChan,'%.0f'); SetMin(outChan,1); SetMax(outChan,16); SetValue(lowNote, 10); SetValue(hiNote, 115); drone := CreateParam('drone', ptSwitch); SetIsOutput(drone,false); instEnable := CreateParam('inst enable', ptSwitch); SetIsInput(instEnable,false); FOR inputNum := 0 TO INPUT_COUNT - 1 DO BEGIN midiIns[inputNum] := CreateParam('MIDIin ' + intToStr(inputNum + 1) ,ptMidi); SetIsOutPut(midiIns[inputNum],false); END; notesOut := CreateParam('NoteMIDI',ptMidi); SetIsInput(notesOut,false); otherOut := CreateParam('otherMIDI',ptMidi); SetIsInput(otherOut,false); learn := CreateParam('learn',ptButton); SetIsOutPut(learn,false); lower := CreateParam('lower',ptMidiNoteFader); SetIsInPut(lower,false); upper := CreateParam('upper',ptMidiNoteFader); SetIsInPut(upper,false); notesOutCount := 0; otherOutCount := 0; learnCount := 0; disablable := FALSE; droning := FALSE; release := FALSE; SetArrayLength(isEnabled, INPUT_COUNT); END;// <F> isNoteOn: //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// FUNCTION isNoteOn(midi: tMidi): boolean;BEGIN IF (midi.msg = NOTE_ON) AND (midi.data2>0) THEN BEGIN result := true; END ELSE BEGIN result := false; END;END;// <F> isNoteOff: //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// FUNCTION isNoteOff(midi: tMidi): boolean;BEGIN IF (midi.msg = NOTE_OFF) OR ((midi.msg = NOTE_ON) AND (midi.data2 = 0)) THEN BEGIN result := true; END ELSE BEGIN result := false; END;END; // <F> isSusPed: //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// FUNCTION isSusPed(midi: tMidi) : boolean;BEGIN IF (midi.msg = CONTROL) AND (midi.data1 = SUS_PED) THEN BEGIN result := true; END ELSE BEGIN result := false; END;END; // <F> isPitchBend: //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// FUNCTION isPitchBend(midi: tMidi): boolean;BEGIN IF (midi.msg = PITCHBEND) THEN BEGIN result := true; END ELSE BEGIN result := false; END;END;// <F> global function inRange--eliminates only noteons outside the range limits FUNCTION inRange(midi: tMidi) : boolean;BEGIN IF (isNoteOn(midi)) AND (midi.data1 > lowVal) AND (midi.data1 < hiVal) THEN BEGIN result := TRUE; END ELSE BEGIN result := FALSE; END; END;// <F> isClear//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^//FUNCTION isClear() : boolean; // can we stop this loop as soon as a key = true?? Didn't like 'while'VAR clear : boolean;BEGIN clear := TRUE; BEGIN FOR key:= minKey TO maxKey DO BEGIN IF (noteList[key] = TRUE) THEN BEGIN clear := FALSE; END; END; END; result := clear; END;// <F> ReleaseNotes --when you release the sustain, or release the drone, or change the output channel//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^//PROCEDURE ReleaseNotes;BEGIN FOR key:= minKey TO maxKey DO BEGIN IF (noteList[key] = TRUE) THEN BEGIN noteOff.msg := NOTE_OFF; noteOff.channel := outputChannel; // byte is a conversion--is this needed? noteOff.data1 := key; noteOff.data2 := 0; setMidiArrayValue(notesOut, notesOutCount, noteOff); strace('sending noteOff for ' + intToStr(key)); notesOutCount := notesOutCount + 1; noteList[key] := FALSE; END; END; END; // Global Procedure StoreNoteOffs--just de-inlined for readability//----------------------------------------------//PROCEDURE StoreNoteOffs;BEGIN IF (midi.data1 > maxKey) THEN BEGIN maxKey := midi.data1; END; IF (midi.data1 < minKey) THEN BEGIN minKey := midi.data1; END; noteList[midi.data1] := TRUE;END;// Callback//----------------------------------------------// procedure Callback(n:integer);BEGIN if (n = hiNote) then begin hiVal := round(getValue(hiNote)); setValue(upper, hiVal); end else if (n = lowNote) then begin lowVal := round(getValue(lowNote)); setValue(lower, lowVal); end else if (n = learn) and (getValue(n) = 1) then begin learning:= TRUE; strace('learning...'); learnCount := 0; end else if (learnCount = 2) then begin // we've just learned, so we want to send out lower and upper learning := FALSE; learnCount := 0; strace(' finishedlearning'); end else begin // get input values octVal := trunc(getValue(octave)); semival := trunc(getValue(semi)); transpose := (octVal * 12) + semiVal; outputChannel := trunc(getValue(outChan)); droning := (getValue(drone) = 1); // see if any input is enabled.... noInput := TRUE; FOR inputNum := 0 to INPUT_COUNT - 1 DO BEGIN IF getValue(enables[inputNum]) = 1 THEN BEGIN isEnabled[inputNum] := TRUE; noInput := FALSE; END ELSE BEGIN isEnabled[inputNum] := FALSE; END; END; // release notes if the drone has just been turned off, or if all inputs and notes are off, or if the channel is changed IF ((n = drone) and (not(Droning))) OR ((noInput = TRUE) AND (isClear() = TRUE)) OR (n = outChan) THEN BEGIN strace('releasing notes'); release := true; // booleans to check in process disablable := true; END ELSE BEGIN setValue(instEnable, 1); END; end;END; //////////////////////////////////////////////////////// process//////////////////////////////////////////////////////PROCEDURE PROCESS;BEGIN notesOutCount := 0; otherOutCount := 0; if release then releaseNotes; FOR inputNum := 0 to INPUT_COUNT - 1 DO BEGIN midiInCount := getLength(midiIns[inputNum]); FOR byteNum := 0 TO (midiInCount - 1) DO BEGIN // process input getMidiArrayValue(midiIns[inputNum], byteNum, midi); midi.channel := outputChannel; if (learning) then begin IF (isNoteOn(midi)) and (learnCount = 0) THEN BEGIN lowVal := midi.data1; setValue(lower, lowVal ); learnCount := 1; setMidiArrayValue(otherOut, otherOutCount, midi); otherOutCount := otherOutCount + 1; strace('learnCount = ' + intToStr(learnCount)); END ELSE IF (isNoteOn(midi)) and (learnCount = 1) THEN BEGIN hiVal := midi.data1; setValue(upper, hiVal); learnCount := 2; learning := FALSE; // we've set our outs.... setMidiArrayValue(otherOut, otherOutCount, midi); otherOutCount := otherOutCount + 1; END; end else if (droning) then begin // basically ignore all midi when droning setMidiArrayValue(otherOut, otherOutCount, midi); otherOutCount := otherOutCount + 1; end else begin If isSusPed(midi) THEN BEGIN if (midi.data2 > 64) THEN BEGIN isSustained := true; END ELSE BEGIN isSustained := false; ReleaseNotes; // send noteoffs when the sus pedal is released END; END; IF isNoteOn(midi) AND (inRange(midi)) AND (isEnabled[inputNum]) THEN BEGIN //note on, sus on, store and send transList[midi.data1] := transpose; midi.data1 := midi.data1 + transpose; IF (isSustained = TRUE) THEN BEGIN StoreNoteOffs; setMidiArrayValue(notesOut, notesOutCount, midi); notesOutCount := notesOutCount + 1; END ELSE BEGIN // valid noteon, sus off, send it out setMidiArrayValue(notesOut, notesOutCount, midi); notesOutCount := notesOutCount + 1; END; END ELSE IF isNoteOff(midi) AND (isSustained = FALSE) THEN BEGIN // valid noteoff, sus off, send it out midi.data1 := midi.data1 + transList[midi.data1]; setMidiArrayValue(notesOut, notesOutCount, midi); notesOutCount := notesOutCount + 1; END ELSE IF isPitchBend(midi) THEN BEGIN // send PB along with the notes midi.channel := outputChannel; setMidiArrayValue(notesOut, notesOutCount, midi); notesOutCount := notesOutCount + 1; END ELSE IF (NOT(isNoteOn(midi))) AND (NOT(isNoteOff(midi))) AND (NOT(isPitchBend(midi))) THEN BEGIN //not a note, pb or sus pedal event setMidiArrayValue(otherOut, otherOutCount, midi); otherOutCount := otherOutCount + 1; END; end; END; END; setLength(notesOut, notesOutCount); setLength(otherOut, otherOutCount); if disablable then setValue(instEnable, 0); END;Statistics: Posted by woodslanding — 10 Jan 2010, 11:32
CODE:
(*/////////////////////////////////////////////////////// CHANNEL // Version 2009-11-21; author: eric moon//// based on work by Bsork and amiga909//////////////////////////////////////////////////////*)// This 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 AT and send them out a separate output// read CC64 values (or a CC of your choice) to withhold noteoffs until the sus pedal is released.// limit to minimum and maximum notes--one range affects all inputs, as it's assumed you'll typically be using one input at a time// 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 new notesOns as long as it is held// It is designed to function as part of a mixer channel strip, running between several keyboards and a vsti.// When the 'learn' function is enabled, notes are sent out output 2// the first note sets the lower range, the second note sets the upper limit.// when both notes are sent, learn is disabled, and notes go to output 1 as usual.CONST SUS_PED= 64; //change if you use an unorthodox CC for sustaining.CONST INPUT_COUNT = 2; //allows up to 16 inputs, one per channelCONST NOTE_ON = 144;CONST NOTE_OFF = 128;CONST CONTROL = 176;CONST PITCHBEND = 224;VAR noteList : ARRAY OF boolean;VAR transList : ARRAY OF integer;VAR midi,noteOff : TMidi; var midiIns : ARRAY OF Tparameter;var enables : ARRAY OF TParameter;var notesOut : Tparameter;var otherOut : Tparameter; // all CCs except the sustain value go out this output. So does AT and PgChvar octave : TParameter;var semi : TParameter;var hiNote : TParameter;var lowNote : TParameter;var drone : TParameter; // sustains, but ignores new noteonsvar outChan : TParameter; // everything goes out one channel. It's a channel strip. Use more if you need other channels!var instEnable: TParameter;var lower : Tparameter;var upper : Tparameter; var learn : TParameter;VAR octVal, semiVal, transpose : integer;VAR hiVal, lowVal : integer; VAR midiInCount : integer;VAR otherOutCount, notesOutCount : integer;VAR key, inputNum, byteNum : integer; VAR minChn, maxChn, minKey, maxKey : integer;VAR outputChannel : integer;VAR isSustained,noInput : boolean;VAR isEnabled : Array of boolean;VAR learning : boolean;VAR droning : boolean;var learnCount : integer;//////////////////////////////////////////////////////// initialize//////////////////////////////////////////////////////PROCEDURE init; BEGIN minChn := INPUT_COUNT - 1; // these are initially set to their opposite extremes.... maxChn := 0; minKey := 128; maxKey := 0; isSustained := FALSE; setArrayLength(noteList, 128); FOR key:=0 TO 127 DO BEGIN noteList[key]:=FALSE; END; SetArrayLength(transList, 128); FOR key:=0 TO 127 DO BEGIN transList[key]:=0; END; setArrayLength(midiIns, INPUT_COUNT); setArrayLength(enables, INPUT_COUNT); FOR inputNum := 0 TO INPUT_COUNT - 1 DO BEGIN enables[inputNum] := CreateParam('enable ' + intToStr(inputNum + 1),ptSwitch); SetValue(enables[inputNum], 1); SetIsOutPut(enables[inputNum],false); END; octave := CreateParam('octave',ptDataFader); SetIsOutPut(octave,false); semi := CreateParam('semi',ptDataFader); SetIsOutPut(semi,false); SetFormat(octave,'%.0f'); SetMin(octave,-4); SetMax(octave,4); SetFormat(semi,'%.0f'); SetMin(semi,-7); SetMax(semi,7); hiNote := CreateParam('high note',ptMidiNoteFader); SetIsOutPut(hiNote,false); lowNote := CreateParam('low note',ptMidiNoteFader); SetIsOutPut(lowNote,false); outChan := CreateParam('output chan', ptDataFader); SetIsOutPut(outchan,false); SetFormat(outChan,'%.0f'); SetMin(outChan,1); SetMax(outChan,16); SetValue(lowNote, 10); SetValue(hiNote, 115); drone := CreateParam('drone', ptSwitch); SetIsOutput(drone,false); instEnable := CreateParam('inst enable', ptSwitch); SetIsInput(instEnable,false); FOR inputNum := 0 TO INPUT_COUNT - 1 DO BEGIN midiIns[inputNum] := CreateParam('MIDIin ' + intToStr(inputNum + 1) ,ptMidi); SetIsOutPut(midiIns[inputNum],false); END; notesOut := CreateParam('NoteMIDI',ptMidi); SetIsInput(notesOut,false); otherOut := CreateParam('otherMIDI',ptMidi); SetIsInput(otherOut,false); learn := CreateParam('learn',ptButton); SetIsOutPut(learn,false); lower := CreateParam('lower',ptMidiNoteFader); SetIsInPut(lower,false); upper := CreateParam('upper',ptMidiNoteFader); SetIsInPut(upper,false); notesOutCount := 0; otherOutCount := 0; learnCount := 0; SetArrayLength(isEnabled, INPUT_COUNT); END;// <F> isNoteOn: //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// FUNCTION isNoteOn(midi: tMidi): boolean;BEGIN IF (midi.msg = NOTE_ON) AND (midi.data2>0) THEN BEGIN result := true; END ELSE BEGIN result := false; END;END;// <F> isNoteOff: //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// FUNCTION isNoteOff(midi: tMidi): boolean;BEGIN IF (midi.msg = NOTE_OFF) OR ((midi.msg = NOTE_ON) AND (midi.data2 = 0)) THEN BEGIN result := true; END ELSE BEGIN result := false; END;END; // <F> isSusPed: //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// FUNCTION isSusPed(midi: tMidi) : boolean;BEGIN IF (midi.msg = CONTROL) AND (midi.data1 = SUS_PED) THEN BEGIN result := true; END ELSE BEGIN result := false; END;END; // <F> isPitchBend: //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// FUNCTION isPitchBend(midi: tMidi): boolean;BEGIN IF (midi.msg = PITCHBEND) THEN BEGIN result := true; END ELSE BEGIN result := false; END;END;// <F> global function inRange--eliminates only noteons outside the range limits FUNCTION inRange(midi: tMidi) : boolean;BEGIN IF (isNoteOn(midi)) AND (midi.data1 > lowVal) AND (midi.data1 < hiVal) THEN BEGIN result := TRUE; END ELSE BEGIN result := FALSE; END; END;// <F> isClear//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^//FUNCTION isClear() : boolean; // can we stop this loop as soon as a key = true?? Didn't like 'while'VAR clear : boolean;BEGIN clear := TRUE; BEGIN FOR key:= minKey TO maxKey DO BEGIN IF (noteList[key] = TRUE) THEN BEGIN clear := FALSE; END; END; END; result := clear; END;// <F> ReleaseNotes --when you release the sustain, or release the drone, or change the output channel//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^//PROCEDURE ReleaseNotes;BEGIN FOR key:= minKey TO maxKey DO BEGIN IF (noteList[key] = TRUE) THEN BEGIN noteOff.msg := NOTE_OFF; noteOff.channel := outputChannel; // byte is a conversion--is this needed? noteOff.data1 := key; noteOff.data2 := 0; setMidiArrayValue(notesOut, notesOutCount, noteOff);strace('sending noteOff for ' + intToStr(key)); notesOutCount := notesOutCount + 1; noteList[key] := FALSE; END; END; END; // Global Procedure StoreNoteOffs--just de-inlined for readability//----------------------------------------------//PROCEDURE StoreNoteOffs;BEGIN IF (midi.data1 > maxKey) THEN BEGIN maxKey := midi.data1; END; IF (midi.data1 < minKey) THEN BEGIN minKey := midi.data1; END; noteList[midi.data1] := TRUE;END;// Callback//----------------------------------------------// procedure Callback(n:integer);BEGIN if (n = hiNote) then begin hiVal := round(getValue(hiNote)); setValue(upper, hiVal); end else if (n = lowNote) then begin lowVal := round(getValue(lowNote)); setValue(lower, lowVal); end else if (n = learn) and (getValue(n) = 1) then begin learning:= TRUE; strace('learning...'); learnCount := 0; end else if (learnCount = 2) then begin learning := FALSE; learnCount := 0; strace(' finishedlearning'); end else begin // get input values octVal := trunc(getValue(octave)); semival := trunc(getValue(semi)); transpose := (octVal * 12) + semiVal; outputChannel := trunc(getValue(outChan)); droning := (getValue(drone) = 1); // see if any input is enabled.... noInput := TRUE; FOR inputNum := 0 to INPUT_COUNT - 1 DO BEGIN IF getValue(enables[inputNum]) = 1 THEN BEGIN isEnabled[inputNum] := TRUE; noInput := FALSE; END ELSE BEGIN isEnabled[inputNum] := FALSE; END; END; // release notes if the drone has just been turned off, or if all inputs and notes are off, or if the channel is changed IF ((n = drone) and (not(Droning))) OR ((noInput = TRUE) AND (isClear() = TRUE)) OR (n = outChan) THEN BEGIN strace('releasing notes'); releaseNotes; setValue(instEnable, 0); END ELSE BEGIN setValue(instEnable, 1); END; end;END; //////////////////////////////////////////////////////// process//////////////////////////////////////////////////////PROCEDURE PROCESS;BEGIN notesOutCount := 0; otherOutCount := 0; FOR inputNum := 0 to INPUT_COUNT - 1 DO BEGIN midiInCount := getLength(midiIns[inputNum]); FOR byteNum := 0 TO (midiInCount - 1) DO BEGIN // process input getMidiArrayValue(midiIns[inputNum], byteNum, midi); midi.channel := outputChannel; if (learning) then begin IF (isNoteOn(midi)) and (learnCount = 0) THEN BEGIN lowVal := midi.data1; setValue(lower, lowVal ); learnCount := 1; setMidiArrayValue(otherOut, otherOutCount, midi); otherOutCount := otherOutCount + 1; strace('learnCount = ' + intToStr(learnCount)); END ELSE IF (isNoteOn(midi)) and (learnCount = 1) THEN BEGIN hiVal := midi.data1; setValue(upper, hiVal); learnCount := 2; learning := FALSE; // we've set our outs.... setMidiArrayValue(otherOut, otherOutCount, midi); otherOutCount := otherOutCount + 1; END; end else if (droning) then begin // basically ignore all midi when droning setMidiArrayValue(otherOut, otherOutCount, midi); otherOutCount := otherOutCount + 1; end else begin If isSusPed(midi) THEN BEGIN if (midi.data2 > 64) THEN BEGIN isSustained := true; END ELSE BEGIN isSustained := false; ReleaseNotes; // send noteoffs when the sus pedal is released END; END; IF isNoteOn(midi) AND (inRange(midi)) AND (isEnabled[inputNum]) THEN BEGIN //note on, sus on, store and send transList[midi.data1] := transpose; midi.data1 := midi.data1 + transpose; IF (isSustained = TRUE) THEN BEGIN StoreNoteOffs; setMidiArrayValue(notesOut, notesOutCount, midi); notesOutCount := notesOutCount + 1; END ELSE BEGIN // valid noteon, sus off, send it out setMidiArrayValue(notesOut, notesOutCount, midi); notesOutCount := notesOutCount + 1; END; END ELSE IF isNoteOff(midi) AND (isSustained = FALSE) THEN BEGIN // valid noteoff, sus off, send it out midi.data1 := midi.data1 + transList[midi.data1]; setMidiArrayValue(notesOut, notesOutCount, midi); notesOutCount := notesOutCount + 1; END ELSE IF isPitchBend(midi) THEN BEGIN // send PB along with the notes midi.channel := outputChannel; setMidiArrayValue(notesOut, notesOutCount, midi); notesOutCount := notesOutCount + 1; END ELSE IF (NOT(isNoteOn(midi))) AND (NOT(isNoteOff(midi))) AND (NOT(isPitchBend(midi))) THEN BEGIN //not a note, pb or sus pedal event setMidiArrayValue(otherOut, otherOutCount, midi); otherOutCount := otherOutCount + 1; END; end; END; END; setLength(notesOut, notesOutCount); setLength(otherOut, otherOutCount); END;Statistics: Posted by woodslanding — 10 Jan 2010, 11:18
Statistics: Posted by bsork — 04 Dec 2009, 16:15
Statistics: Posted by gurulogic — 04 Dec 2009, 03:17
Statistics: Posted by bsork — 03 Dec 2009, 21:44
Statistics: Posted by gurulogic — 03 Dec 2009, 19:19
Statistics: Posted by woodslanding — 26 Nov 2009, 20:46
Statistics: Posted by bsork — 26 Nov 2009, 11:50
Statistics: Posted by woodslanding — 26 Nov 2009, 10:28
CODE:
i := 0;WHILE i < cnt DO BEGIN do_something... i := i + 1;END;Statistics: Posted by bsork — 26 Nov 2009, 09:41
Statistics: Posted by woodslanding — 26 Nov 2009, 08:56
CODE:
(*/////////////////////////////////////////////////////// CHANNEL // Version 2009-11-21; author: eric moon//// based on work by Bsork and amiga909//////////////////////////////////////////////////////*)// This 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 AT and send them out a separate output// read CC64 values (or a CC of your choice) to withhold noteoffs until the sus pedal is released.// limit to minimum and maximum notes--one range affects all inputs, as it's assumed you'll typically be using one input at a time// 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 new notesOns as long as it is held// It is designed to function as part of a mixer channel strip, running between several keyboards and a vsti.CONST SUS_PED= 64; //change if you use an unorthodox CC for sustaining.CONST INPUT_COUNT = 2; //allows up to 16 inputs, one per channelCONST NOTE_ON = 144;CONST NOTE_OFF = 128;CONST CONTROL = 176;CONST PITCHBEND = 224;VAR noteList : ARRAY OF boolean;VAR transList : ARRAY OF integer;VAR midi,noteOff : TMidi; var midiIns : ARRAY OF Tparameter;var enables : ARRAY OF TParameter;var notesOut : Tparameter;var otherOut : Tparameter; // all CCs except the sustain value go out this output. So does AT and PgChvar octave : TParameter;var semi : TParameter;var hiNote : TParameter;var lowNote : TParameter;var drone : TParameter; // sustains, but ignores new noteonsvar outChan : TParameter; // everything goes out one channel. It's a channel strip. Use more if you need other channels!var instBypass: TParameter; VAR octVal, semiVal, transpose : integer;VAR hiVal, lowVal : integer; VAR midiInCount : integer;VAR otherOutCount, notesOutCount : integer;VAR key, inputNum, byteNum : integer; VAR minChn, maxChn, minKey, maxKey : integer;VAR outputChannel : integer;VAR isSustained,noInput : boolean;VAR isEnabled : Array of boolean;//////////////////////////////////////////////////////// initialize//////////////////////////////////////////////////////PROCEDURE init; BEGIN minChn := INPUT_COUNT - 1; // these are initially set to their opposite extremes.... maxChn := 0; minKey := 128; maxKey := 0; isSustained := FALSE; setArrayLength(noteList, 128); FOR key:=0 TO 127 DO BEGIN noteList[key]:=FALSE; END; SetArrayLength(transList, 128); FOR key:=0 TO 127 DO BEGIN transList[key]:=0; END; setArrayLength(midiIns, INPUT_COUNT); setArrayLength(enables, INPUT_COUNT); FOR inputNum := 0 TO INPUT_COUNT - 1 DO BEGIN enables[inputNum] := CreateParam('enable ' + intToStr(inputNum + 1),ptSwitch); SetValue(enables[inputNum], 1); SetIsOutPut(enables[inputNum],false); END; octave := CreateParam('octave',ptDataFader); SetIsOutPut(octave,false); semi := CreateParam('semi',ptDataFader); SetIsOutPut(semi,false); SetFormat(octave,'%.0f'); SetMin(octave,-4); SetMax(octave,4); SetFormat(semi,'%.0f'); SetMin(semi,-7); SetMax(semi,7); hiNote := CreateParam('high note',ptMidiNoteFader); SetIsOutPut(hiNote,false); lowNote := CreateParam('low note',ptMidiNoteFader); SetIsOutPut(lowNote,false); outChan := CreateParam('output chan', ptDataFader); SetIsOutPut(outchan,false); SetFormat(outChan,'%.0f'); SetMin(outChan,1); SetMax(outChan,16); SetValue(lowNote, 10); SetValue(hiNote, 115); drone := CreateParam('drone', ptSwitch); SetIsOutput(drone,false); instBypass := CreateParam('inst bypass', ptSwitch); SetIsInput(instBypass,false); FOR inputNum := 0 TO INPUT_COUNT - 1 DO BEGIN midiIns[inputNum] := CreateParam('MIDIin ' + intToStr(inputNum + 1) ,ptMidi); SetIsOutPut(midiIns[inputNum],false); END; notesOut := CreateParam('Notes Out',ptMidi); SetIsInput(notesOut,false); otherOut := CreateParam('other Out',ptMidi); SetIsInput(otherOut,false); notesOutCount := 0; otherOutCount := 0; SetArrayLength(isEnabled, INPUT_COUNT); END;// <F> isNoteOn: //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// FUNCTION isNoteOn(midi: tMidi): boolean;BEGIN IF (midi.msg = NOTE_ON) AND (midi.data2>0) THEN BEGIN result := true; END ELSE BEGIN result := false; END;END;// <F> isNoteOff: //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// FUNCTION isNoteOff(midi: tMidi): boolean;BEGIN IF (midi.msg = NOTE_OFF) OR ((midi.msg = NOTE_ON) AND (midi.data2 = 0)) THEN BEGIN result := true; END ELSE BEGIN result := false; END;END; // <F> isSusPed: //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// FUNCTION isSusPed(midi: tMidi) : boolean;BEGIN IF (midi.msg = CONTROL) AND (midi.data1 = SUS_PED) THEN BEGIN result := true; END ELSE BEGIN result := false; END;END; // <F> isPitchBend: //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// FUNCTION isPitchBend(midi: tMidi): boolean;BEGIN IF (midi.msg = PITCHBEND) THEN BEGIN result := true; END ELSE BEGIN result := false; END;END;// <F> global function inRange--eliminates only noteons outside the range limits FUNCTION inRange(midi: tMidi) : boolean;BEGIN IF (isNoteOn(midi)) AND (midi.data1 > lowVal) AND (midi.data1 < hiVal) THEN BEGIN result := TRUE; END ELSE BEGIN result := FALSE; END; END;// <F> isClear//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^//FUNCTION isClear() : boolean; // can we stop this loop as soon as a key = true?? Didn't like 'while'VAR clear : boolean;BEGIN clear := TRUE; BEGIN FOR key:= minKey TO maxKey DO BEGIN IF (noteList[key] = TRUE) THEN BEGIN clear := FALSE; END; END; END; result := clear; END;// <F> ReleaseNotes --when you release the sustain, or release the drone, or change the output channel//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^//PROCEDURE ReleaseNotes;BEGIN FOR key:= minKey TO maxKey DO BEGIN IF (noteList[key] = TRUE) THEN BEGIN noteOff.msg := NOTE_OFF; noteOff.channel := outputChannel; // byte is a conversion--is this needed? noteOff.data1 := key; noteOff.data2 := 0; setMidiArrayValue(notesOut, notesOutCount, noteOff); //danger when called from callback? notesOutCount := notesOutCount + 1; noteList[key] := FALSE; END; END; END; // Global Procedure StoreNoteOffs--just de-inlined for readability//----------------------------------------------//PROCEDURE StoreNoteOffs;BEGIN IF (midi.data1 > maxKey) THEN BEGIN maxKey := midi.data1; END; IF (midi.data1 < minKey) THEN BEGIN minKey := midi.data1; END; noteList[midi.data1] := TRUE;END;// Callback//----------------------------------------------// procedure Callback(n:integer);BEGIN // get input values hiVal := trunc(getValue(hiNote)); lowVal := trunc(getValue(lowNote)); octVal := trunc(getValue(octave)); semival := trunc(getValue(semi)); transpose := (octVal * 12) + semiVal;writeln('transpose = ' + intToStr(transpose)); outputChannel := trunc(getValue(outChan)); // see if any input is enabled.... noInput := TRUE; FOR inputNum := 0 to INPUT_COUNT - 1 DO BEGIN IF getValue(enables[inputNum]) = 1 THEN BEGIN isEnabled[inputNum] := TRUE; noInput := FALSE; END ELSE BEGIN isEnabled[inputNum] := FALSE; END; END; // release notes if the drone has just been turned off, or if all inputs and notes are off, or if the channel is changed IF ((n = drone) and (getValue(drone) = 0)) OR ((noInput = TRUE) AND (isClear() = TRUE)) OR (n = outChan) THEN BEGIN releaseNotes; // can I call this from callback? setValue(instBypass, 1); END ELSE BEGIN setValue(instBypass, 0); END;END; //////////////////////////////////////////////////////// process//////////////////////////////////////////////////////PROCEDURE PROCESS;BEGIN notesOutCount := 0; otherOutCount := 0; FOR inputNum := 0 to INPUT_COUNT - 1 DO BEGIN midiInCount := getLength(midiIns[inputNum]); FOR byteNum := 0 TO (midiInCount - 1) DO BEGIN // process input getMidiArrayValue(midiIns[inputNum], byteNum, midi); midi.channel := outputChannel; If isSusPed(midi) THEN BEGIN if (midi.data2 > 64) THEN BEGIN isSustained := true; END ELSE BEGIN isSustained := false; ReleaseNotes; // send noteoffs when the sus pedal is released END; END; IF isNoteOn(midi) AND (inRange(midi)) AND (isEnabled[inputNum]) THEN BEGIN //note on, sus on, store and send transList[midi.data1] := transpose; midi.data1 := midi.data1 + transpose; IF (isSustained = TRUE) THEN BEGIN StoreNoteOffs; setMidiArrayValue(notesOut, notesOutCount, midi); notesOutCount := notesOutCount + 1; END ELSE BEGIN // valid noteon, sus off, send it out setMidiArrayValue(notesOut, notesOutCount, midi); notesOutCount := notesOutCount + 1; END; END ELSE IF isNoteOff(midi) AND (isSustained = FALSE) THEN BEGIN // valid noteoff, sus off, send it out midi.data1 := midi.data1 + transList[midi.data1]; setMidiArrayValue(notesOut, notesOutCount, midi); notesOutCount := notesOutCount + 1; END ELSE IF isPitchBend(midi) THEN BEGIN // send PB along with the notes midi.channel := outputChannel; setMidiArrayValue(notesOut, notesOutCount, midi); notesOutCount := notesOutCount + 1; END ELSE IF (NOT(isNoteOn(midi))) AND (NOT(isNoteOff(midi))) AND (NOT(isPitchBend(midi))) THEN BEGIN //not a note, pb or sus pedal event setMidiArrayValue(otherOut, otherOutCount, midi); otherOutCount := otherOutCount + 1; END; END; END; setLength(notesOut, notesOutCount); setLength(otherOut, otherOutCount); END;Statistics: Posted by woodslanding — 26 Nov 2009, 08:26
Statistics: Posted by bsork — 25 Nov 2009, 08:53
Statistics: Posted by woodslanding — 25 Nov 2009, 05:24
Statistics: Posted by woodslanding — 25 Nov 2009, 04:56
Statistics: Posted by bsork — 24 Nov 2009, 14:31
CODE:
(*/////////////////////////////////////////////////////// CHANNEL // Version 2009-11-21; author: eric moon//// based on work by Bsork and amiga909//////////////////////////////////////////////////////*)// This 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 AT and send them out a separate output// read CC64 values (or a CC of your choice) to withhold noteoffs until the sus pedal is released.// limit to minimum and maximum notes--one range affects all inputs, as it's assumed you'll typically be using one input at a time// 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 new notesOns as long as it is held// It is designed to function as part of a mixer channel strip, running between several keyboards and a vsti.CONST SUS_PED= 64; //change if you use an unorthodox CC for sustaining.CONST INPUT_COUNT = 2; //number of midi note sourcesCONST NOTE_ON = 144;CONST NOTE_OFF = 128;CONST CONTROL = 176;CONST PITCHBEND = 224;VAR noteList : ARRAY OF boolean;VAR transList : ARRAY OF integer;VAR midi,noteOff : TMidi; var midiIns : ARRAY OF Tparameter;var enables : ARRAY OF TParameter;var notesOut : Tparameter;var otherOut : Tparameter; // all CCs except the sustain value go out this output. So does AT and PgChvar octave : TParameter;var semi : TParameter;var hiNote : TParameter;var lowNote : TParameter;var drone : TParameter; // sustains, but ignores new noteonsvar outChan : TParameter; // everything goes out one channel. It's a channel strip. Use more if you need other channels!var instBypass: TParameter; VAR octVal, semiVal, transpose : integer;VAR hiVal, lowVal : integer; VAR midiInCount : integer;VAR otherOutCount, notesOutCount : integer;VAR key, inputNum, byteNum : integer; VAR minChn, maxChn, minKey, maxKey : integer;VAR outputChannel : integer;VAR isSustained,noInput : boolean;VAR isEnabled : Array of boolean;//////////////////////////////////////////////////////// initialize//////////////////////////////////////////////////////PROCEDURE init; BEGIN minChn := INPUT_COUNT - 1; // these are initially set to their opposite extremes.... maxChn := 0; minKey := 128; maxKey := 0; isSustained := FALSE; setArrayLength(noteList, 128); FOR key:=0 TO 127 DO BEGIN noteList[key]:=FALSE; END; SetArrayLength(transList, 128); FOR key:=0 TO 127 DO BEGIN transList[key]:=0; END; setArrayLength(midiIns, INPUT_COUNT); setArrayLength(enables, INPUT_COUNT); FOR inputNum := 0 TO INPUT_COUNT - 1 DO BEGIN enables[inputNum] := CreateParam('enable ' + intToStr(inputNum + 1),ptSwitch); SetValue(enables[inputNum], 1); SetIsOutPut(enables[inputNum],false); END; octave := CreateParam('octave',ptDataFader); SetIsOutPut(octave,false); semi := CreateParam('semi',ptDataFader); SetIsOutPut(semi,false); SetFormat(octave,'%.0f'); SetMin(octave,-4); SetMax(octave,4); SetFormat(semi,'%.0f'); SetMin(semi,-7); SetMax(semi,7); hiNote := CreateParam('high note',ptMidiNoteFader); SetIsOutPut(hiNote,false); lowNote := CreateParam('low note',ptMidiNoteFader); SetIsOutPut(lowNote,false); outChan := CreateParam('output chan', ptDataFader); SetIsOutPut(outchan,false); SetFormat(outChan,'%.0f'); SetMin(outChan,1); SetMax(outChan,16); SetValue(lowNote, 10); SetValue(hiNote, 115); drone := CreateParam('drone', ptSwitch); SetIsOutput(drone,false); instBypass := CreateParam('inst bypass', ptSwitch); SetIsInput(instBypass,false); FOR inputNum := 0 TO INPUT_COUNT - 1 DO BEGIN midiIns[inputNum] := CreateParam('MIDIin ' + intToStr(inputNum + 1) ,ptMidi); SetIsOutPut(midiIns[inputNum],false); END; notesOut := CreateParam('Notes Out',ptMidi); SetIsInput(notesOut,false); otherOut := CreateParam('other Out',ptMidi); SetIsInput(otherOut,false); SetArrayLength(isEnabled, INPUT_COUNT); END;// <F> isNoteOn: //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// FUNCTION isNoteOn(midi: tMidi): boolean;BEGIN IF (midi.msg = NOTE_ON) AND (midi.data2>0) THEN BEGIN result := true; END ELSE BEGIN result := false; END;END;// <F> isNoteOff: //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// FUNCTION isNoteOff(midi: tMidi): boolean;BEGIN IF (midi.msg = NOTE_OFF) OR ((midi.msg = NOTE_ON) AND (midi.data2 = 0)) THEN BEGIN result := true; END ELSE BEGIN result := false; END;END; // <F> isSusPed: //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// FUNCTION isSusPed(midi: tMidi) : boolean;BEGIN IF (midi.msg = CONTROL) AND (midi.data1 = SUS_PED) THEN BEGIN result := true; END ELSE BEGIN result := false; END;END; // <F> isPitchBend: //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// FUNCTION isPitchBend(midi: tMidi): boolean;BEGIN IF (midi.msg = PITCHBEND) THEN BEGIN result := true; END ELSE BEGIN result := false; END;END;// <F> global function inRange--eliminates only noteons outside the range limits FUNCTION inRange(midi: tMidi) : boolean;BEGIN IF (isNoteOn(midi)) AND (midi.data1 > lowVal) AND (midi.data1 < hiVal) THEN BEGIN result := TRUE; END ELSE BEGIN result := FALSE; END; END;// <F> isClear//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^//FUNCTION isClear() : boolean; // can we stop this loop as soon as a key = true?? Didn't like 'while'VAR clear : boolean;BEGIN clear := TRUE; BEGIN FOR key:= minKey TO maxKey DO BEGIN IF (noteList[key] = TRUE) THEN BEGIN clear := FALSE; END; END; END; result := clear; END;// <F> ReleaseNotes --when you release the sustain, or release the drone, or change the output channel//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^//PROCEDURE ReleaseNotes;BEGIN FOR key:= minKey TO maxKey DO BEGIN IF (noteList[key] = TRUE) THEN BEGIN noteOff.msg := NOTE_OFF; noteOff.channel := outputChannel; // byte is a conversion--is this needed? noteOff.data1 := key; noteOff.data2 := 0; setMidiArrayValue(notesOut, notesOutCount, noteOff); //danger when called from callback? notesOutCount := notesOutCount + 1; noteList[key] := FALSE; END; END; END; // Global Procedure StoreNoteOffs--just de-inlined for readability//----------------------------------------------//PROCEDURE StoreNoteOffs;BEGIN IF (midi.data1 > maxKey) THEN BEGIN maxKey := midi.data1; END; IF (midi.data1 < minKey) THEN BEGIN minKey := midi.data1; END; noteList[midi.data1] := TRUE;END;// Callback//----------------------------------------------// procedure Callback(n:integer);BEGIN // get input values hiVal := trunc(getValue(hiNote)); lowVal := trunc(getValue(lowNote)); octVal := trunc(getValue(octave)); semival := trunc(getValue(semi)); transpose := (octVal * 12) + semiVal;writeln('transpose = ' + intToStr(transpose)); outputChannel := trunc(getValue(outChan)); // see if any input is enabled.... noInput := TRUE; FOR inputNum := 0 to INPUT_COUNT - 1 DO BEGIN IF getValue(enables[inputNum]) = 1 THEN BEGIN isEnabled[inputNum] := TRUE; noInput := FALSE; END ELSE BEGIN isEnabled[inputNum] := FALSE; END; END; // release notes if the drone has just been turned off, or if all inputs and notes are off, or if the channel is changed IF ((n = drone) and (getValue(drone) = 0)) OR ((noInput = TRUE) AND (isClear() = TRUE)) OR (n = outChan) THEN BEGIN releaseNotes; // can I call this from callback? setValue(instBypass, 1); END ELSE BEGIN setValue(instBypass, 0); END;END; //////////////////////////////////////////////////////// process//////////////////////////////////////////////////////PROCEDURE PROCESS;BEGIN FOR inputNum := 0 to INPUT_COUNT - 1 DO BEGIN midiInCount := getLength(midiIns[inputNum]); IF (midiInCount > 0) THEN BEGIN notesOutCount := 0; otherOutCount := 0; FOR byteNum := 0 TO (midiInCount - 1) DO BEGIN // process input getMidiArrayValue(midiIns[inputNum], byteNum, midi); midi.channel := outputChannel; If isSusPed(midi) THEN BEGIN if (midi.data2 > 64) THEN BEGIN isSustained := true; END ELSE BEGIN isSustained := false; ReleaseNotes; // send noteoffs when the sus pedal is released END; END; IF isNoteOn(midi) AND (inRange(midi)) AND (isEnabled[inputNum]) THEN BEGIN //note on, sus on, store and send IF (isSustained = TRUE) THEN BEGIN StoreNoteOffs; setMidiArrayValue(notesOut, notesOutCount, midi); notesOutCount := notesOutCount + 1; END ELSE BEGIN // valid noteon, sus off, send it out transList[midi.data1] := transpose; midi.data1 := midi.data1 + transpose; setMidiArrayValue(notesOut, notesOutCount, midi); notesOutCount := notesOutCount + 1; END; END ELSE IF isNoteOff(midi) AND (isSustained = FALSE) THEN BEGIN // valid noteoff, sus off, send it out midi.data1 := midi.data1 + transList[midi.data1]; setMidiArrayValue(notesOut, notesOutCount, midi); notesOutCount := notesOutCount + 1; END ELSE IF isPitchBend(midi) THEN BEGIN // send PB along with the notes midi.channel := outputChannel; setMidiArrayValue(notesOut, notesOutCount, midi); notesOutCount := notesOutCount + 1; END ELSE IF (NOT(isNoteOn(midi))) AND (NOT(isNoteOff(midi))) AND (NOT(isPitchBend(midi))) THEN BEGIN //not a note, pb or sus pedal event setMidiArrayValue(otherOut, otherOutCount, midi); otherOutCount := otherOutCount + 1; END; END; // process input setLength(notesOut, notesOutCount); setLength(otherOut, otherOutCount); END ELSE BEGIN setLength(notesOut,0); setLength(otherOut, 0); END; END; END;Statistics: Posted by woodslanding — 24 Nov 2009, 09:00
CODE:
VAR pParam1, pParam2, pParam3 : tParameter;VAR param1, param2, param3 : single;VAR doUpdate : boolean;....PROCEDURE Init;BEGIN pParam1 := CreateParam('param 1', ... pParam2 := CreateParam('param 2', ... pParam3 := CreateParam('param 3', ... doUpdate := FALSE;END;PROCEDURE GetParams;BEGIN param1 := GetValue(pParam1); param2 := GetValue(pParam2); param3 := GetValue(pParam3); END;PROCEDURE Callback(n ; integer);BEGIN // You can of course use IF-statements instead of CASE CASE n OF pParam1 : doUpdate := TRUE; pParam2 : doUpdate := TRUE; pParam3 : doUpdate := TRUE; END;END;PROCEDURE Process;BEGIN IF (doUpdate) THEN BEGIN GetParams; doUpdate := FALSE; END; ...END;Statistics: Posted by bsork — 23 Nov 2009, 21:52