ArrayArrayArrayArrayArrayArrayArrayArrayArrayArrayArrayArrayArrayArrayArrayArrayArrayArrayArrayArrayArrayArrayArrayArrayArray
Statistics: Posted by woodslanding — 28 Oct 2008, 16:45
Statistics: Posted by bsork — 28 Oct 2008, 13:00
CODE:
//////////////////////////////////////////////////////// transpose midi note// 2008-10-24: @Bsork, first version // 2008-10-26: @amiga909, 'wrap around' added //////////////////////////////////////////////////////VAR pIn, pOut, pTransp, pWrapAround : tParameter;TYPE tTransp = ARRAY OF integer;VAR transp : ARRAY OF tTransp;VAR tmp : tMidi;VAR len, transpose, i, tempTransp : integer;PROCEDURE Init;BEGIN pIn := CreateParam('midi in', ptMidi); SetIsOutput(pIn, FALSE); pOut := CreateParam('midi out', ptMidi); SetIsInput(pOut, FALSE); pTransp := CreateParam('transpose', ptDataFader); SetIsOutput(pTransp, FALSE); SetFormat(pTransp, '%.0f'); SetMin(pTransp, -127); SetMax(pTransp, 127); pWrapAround := CreateParam('wrap around', ptSwitch); SetIsOutput(pWrapAround, FALSE); SetArrayLength(transp, 16); FOR i := 0 TO 15 DO // A two-dimensional array; [16 channels][128 transpose values] SetArrayLength(transp[i], 128);END; // expects a noteOn msg with velocity > 0; outputs the transposed note value [0-127]FUNCTION calcTranspose (t: integer; wrap: single): integer;BEGIN IF wrap > 0 THEN BEGIN // IF (t > 127) THEN result := t - 128 ELSE IF (t < 0) THEN result := t + 128; END ELSE BEGIN IF t > 127 THEN result:= 127 ELSE IF t < 0 THEN result:=0 ELSE result:=t; END; END;// mainBEGIN len := GetLength(pIn); IF (len > 0) THEN BEGIN transpose := trunc(GetValue(pTransp)); SetLength(pOut, len); FOR i := 0 TO (len - 1) DO BEGIN GetMidiArrayValue(pIn, i, tmp); tempTransp := transpose + tmp.data1; IF (tmp.msg = 144) AND (tmp.data2 > 0) THEN BEGIN // NoteOn tempTransp:= calcTranspose(tempTransp, GetValue(pWrapAround)); transp[tmp.channel - 1][tmp.data1] := tempTransp; tmp.data1 := tempTransp; SetMidiArrayValue(pOut, i, tmp); END ELSE IF (tmp.msg = 128) or ((tmp.data2 = 144) and (tmp.data2 = 0)) THEN // NoteOff tmp.data1 := transp[tmp.channel - 1][tmp.data1]; SetMidiArrayValue(pOut, i, tmp); END; END ELSE BEGIN SetLength(pOut, 0); END;END.I'd like to add a little "party trick" if someone else is testing your rig: Add an LFO or random generator to the transpose value as I did when testing, it's quite confusing when the same key changes notes all the time!
Statistics: Posted by amiga909 — 26 Oct 2008, 15:26
I'd like to add a little "party trick" if someone else is testing your rig: Add an LFO or random generator to the transpose value as I did when testing, it's quite confusing when the same key changes notes all the time!It's turned the transpose (especially the octave control) into a performance tool!
Statistics: Posted by bsork — 26 Oct 2008, 08:37
CODE:
//// take input from two keyboards and assign one or both to a vst. also split and transpose.TYPE tNoteArr = ARRAY OF boolean;TYPE tStatus = RECORD low : integer; max : integer; sus : boolean; bend : boolean;END;TYPE tTransp = ARRAY OF integer;VAR transpositions : ARRAY OF tTransp;// parameters declarationvar input : Tparameter; // midi inputvar output : Tparameter; // midi outputvar key1 : Tparameter; // output notes from keyboard 1var key2 : Tparameter; // output notes from keyboard 2// these are not implemented yet....soon.var volKey1 : Tparameter; // send out a volume control signal for keyboard 1, if enabled as a sourcevar volKey2 : Tparameter; // send out a volume control signal for keyboard 2, if enabled as a sourcevar enable : Tparameter; // boolean control out for disabling VST if no keyboard is controlling itvar outCH : Tparameter; // rechannelize input. Value of 0 leaves output channel unchangedvar semi : TParameter; // transpose by semi-tonevar octave : TParameter; // transpose by octavevar split : Tparameter; // pitch below or above which notes are not sentvar upper : Tparameter; // send pitches above the split if on. otherwise send pitches below.var bytecount : integer;var midiLen : integer;var midi : TMidi;var transpose : integer;var splitVal : integer;var upperVal : integer;var key1Val : single;var key2Val : single;var key1ch : integer;var key2ch : integer;var i : integer;var channel : integer;// initialisation PROCEDURE init;BEGIN output := CreateParam('MIDIout',ptMidi); SetIsInput(Output,false); volKey1 := CreateParam('volK1',ptMidi); SetIsInput(volKey1,false); volKey2 := CreateParam('volK2',ptMidi); SetIsInput(volKey2,false); enable := CreateParam('vstEnable',ptDataField); SetIsInput(enable,false); input := CreateParam('MIDIin',ptMidi); SetIsOutput(Input,false); semi := CreateParam('semi',ptDataField); SetIsOutput(semi,false); octave := CreateParam('8va',ptDataField); SetIsOutput(octave,false); split := CreateParam('split',ptMidiNoteFader); SetIsOutput(split,false); upper := CreateParam('upper',ptSwitch); SetIsOutput(upper,false); key1 := CreateParam('key1', ptSwitch); SetIsOutput(key1,false); key2 := CreateParam('key2', ptSwitch); SetIsOutput(key2,false); outCH := CreateParam('outCH', ptDataField); SetIsOutput(outCH,false); key1ch := 1; key2ch := 2; SetArrayLength(transpositions, 2); FOR i := 0 TO 1 DO // we are going to ignore midi data on any but the 2 keyboard channels... SetArrayLength(transpositions[i], 128); //default values and formats SetDefaultValue(upper,1); SetDefaultValue(key1,1); SetDefaultValue(key2,1); SetFormat(split,'%.0f'); SetMin(split,1); SetMax(split,127); SetDefaultValue(split,1); SetFormat(semi,'%.0f'); SetMin(semi,-7); SetMax(semi,7); SetDefaultValue(semi,0); SetFormat(octave,'%.0f'); SetMin(octave,-4); SetMax(octave,4); SetDefaultValue(octave,0)end;PROCEDURE processNoteOns;BEGIN writeln('in noteon loop'); IF (((channel = key1ch) AND (key1Val = 1)) OR ((channel = key2ch) AND (key2Val = 1))) AND (((midi.data1 >= splitVal) AND (upperVal = 1)) OR ((midi.data1 < splitVal) AND (upperVal = 0))) THEN BEGIN transpositions[channel - 1][midi.data1] := transpose; // only works if keyboard ch's are 1 and 2.... midi.data1 := midi.data1 + transpose; SetMidiArrayValue(output, bytecount, midi); END; END; //process NoteonsPROCEDURE processNoteOffs;BEGIN midi.data1 := midi.data1 + transpositions[channel - 1][midi.data1]; // Retrieve stored transpose and add to NoteOff SetMidiArrayValue(output, bytecount, midi);END; //processNoteoffsPROCEDURE processSustain; // untestedBEGIN IF (midi.data1 < 64) THEN //send sus up on all instruments, selected or not... BEGIN SetMidiArrayValue(output, bytecount, midi); END ELSE IF (((channel = 1) AND (key1Val = 1)) OR ((channel = 2) AND (key2Val = 1))) THEN BEGIN IF (midi.data1 >= 64) THEN //send sus down only on selected instruments BEGIN SetMidiArrayValue(output, bytecount, midi); END; END;END; // process sustain // mainBEGIN midiLen := GetLength(input); IF (midiLen > 0) THEN BEGIN SetLength(output, midiLen); // set variables from inputs transpose := trunc(GetValue(semi) + ((getValue(octave) * 12))); splitVal := trunc(getValue(split)); upperVal := trunc(getValue(upper)); key1Val := trunc(getValue(key1)); key2Val := trunc(getValue(key2)); // process midi FOR bytecount := 0 TO (midiLen - 1) DO BEGIN GetMidiArrayValue(input, bytecount, midi); channel := midi.channel; IF ((midi.msg = 144) AND (midi.data2 > 0)) THEN BEGIN // Noteon processNoteons; END ELSE IF ((midi.msg = 128) OR ((midi.msg = 144) AND (midi.data2 = 0))) THEN BEGIN // NoteOff processNoteoffs; END ELSE IF (midi.msg = 176) THEN BEGIN processSustain; END; ///ELSE IF ((midi.msg = 224) pitchbend, etc. END; END // no midi in this block.... ELSE BEGIN SetLength(output, 0); END;END.Statistics: Posted by woodslanding — 26 Oct 2008, 02:01
CODE:
//////////////////////////////////////////////////////// TEST: midi message 1st byte + midi channel filtering//////////////////////////////////////////////////////// Paramters declarationvar input, txt : Tparameter;var tmp : TMidi;var len, i: integer; // initialisation procedureprocedure init;begin input := CreateParam('input',ptMidi); SetIsOutput(input,false); txt := CreateParam('txt',ptTextField); SetIsInput(txt,false);end;procedure writeMidi(m: TMidi);var s: string;beginsetLength(txt,50);s:= '[msg: ' + intToStr(m.msg) +'] [chn:'+ intToStr(m.channel) + ']';setStringValue(txt,s);writeln(s);end; // Main Loop procedurebegin len := getLength(input); if len > 0 then begin for i:=0 to len-1 do begin getMidiArrayValue(input,i,tmp); if (tmp.msg = 144) or (tmp.msg = 128) then writeMidi(tmp); if ((tmp.msg > 144) and (tmp.msg < 160)) or ((tmp.msg > 128) and (tmp.msg < 144)) then writeMidi(tmp); end; end;end.Statistics: Posted by amiga909 — 25 Oct 2008, 14:47
Statistics: Posted by bsork — 24 Oct 2008, 22:12
Statistics: Posted by amiga909 — 24 Oct 2008, 15:55
Statistics: Posted by antwan — 24 Oct 2008, 15:23
Statistics: Posted by amiga909 — 24 Oct 2008, 14:57
Statistics: Posted by antwan — 24 Oct 2008, 11:12
Statistics: Posted by woodslanding — 24 Oct 2008, 06:45
CODE:
VAR pIn, pOut, pTransp : tParameter;TYPE tTransp = ARRAY OF integer;VAR transp : ARRAY OF tTransp;VAR tmp : tMidi;VAR len, transpose, i : integer;PROCEDURE Init;BEGIN pIn := CreateParam('midi in', ptMidi); SetIsOutput(pIn, FALSE); pOut := CreateParam('midi out', ptMidi); SetIsInput(pOut, FALSE); pTransp := CreateParam('transpose', ptDataFader); SetIsOutput(pTransp, FALSE); SetFormat(pTransp, '%.0f'); SetMin(pTransp, -24); SetMax(pTransp, 24); SetArrayLength(transp, 16); FOR i := 0 TO 15 DO // A two-dimensional array; [16 channels][128 transpose values] SetArrayLength(transp[i], 128);END; // Init// mainBEGIN len := GetLength(pIn); IF (len > 0) THEN BEGIN transpose := trunc(GetValue(pTransp)); SetLength(pOut, len); FOR i := 0 TO (len - 1) DO BEGIN GetMidiArrayValue(pIn, i, tmp); IF ((tmp.msg = 144) AND (tmp.data2 > 0)) THEN BEGIN // NoteOn transp[tmp.channel - 1][tmp.data1] := transpose; // Store transpose value used for NoteOn tmp.data1 := tmp.data1 + transpose; END ELSE IF ( (tmp.msg = 128) OR ((tmp.msg = 144) AND (tmp.data2 = 0))) THEN BEGIN // NoteOff tmp.data1 := tmp.data1 + transp[tmp.channel - 1][tmp.data1]; // Retrieve stored transpose and add to NoteOff END; SetMidiArrayValue(pOut, i, tmp); END; END ELSE BEGIN SetLength(pOut, 0); END;END.Running test with three RandomMidi modules spitting out notes didn't really give any definitive "winner" in CPU usage. Your script was in fact generally a tiny bit lower, but the occasional spikes that I could see for both was on the other hand generally more pronounced with your script. If I had restricted the script to ignore the MIDI channel, I guess I could have saved a bit on the CPU.Statistics: Posted by bsork — 24 Oct 2008, 01:07
Hence, I'm having trouble understanding the rest of itHowever, instead of using lots of temporary arrys, loops etc, I think it's a lot easier to use the MIDI data for array lookups.
Statistics: Posted by antwan — 23 Oct 2008, 16:33
Statistics: Posted by bsork — 23 Oct 2008, 14:19
CODE:
// ADVANCED MIDI TRANSPOSE// Parameters declarationVAR input : Tparameter;VAR output : Tparameter;VAR transpo : TParameter;// Global variablesVAR i, j, x : integer;VAR nbOfMidi : integer;VAR transpoVal : integer;VAR arrLength : integer;VAR ReceivedMidi : TMidi;VAR notesArray : Array of integer; // This holds the note numbers that are waiting for note offsVAR transpoArray : Array of integer; // This holds the transposition value that was in place when each of the notes in notesArray was addedVAR tempNotesArray : Array of integer; // A temp array used in proc DelArrayIndicesVAR tempTranspoArray : Array of integer; // A temp array used in proc DelArrayIndices// Initialisation - create parametersPROCEDURE init;BEGIN Input := CreateParam('In',ptMidi); Output := CreateParam('Out',ptMidi); transpo := CreateParam('transpo',ptDataFader); SetIsInput(Output,false); SetIsOutPut(Input,false); SetIsOutPut(transpo,false); SetFormat(transpo,'%.0f'); SetMin(transpo,-24); SetMax(transpo,24);END; // initPROCEDURE DelArrayIndices;BEGIN SetArrayLength(tempNotesArray, (arrLength-1)); SetArrayLength(tempTranspoArray, (arrLength-1)); FOR x := 0 TO j-1 DO BEGIN tempNotesArray[x] := notesArray[x]; tempTranspoArray[x] := transpoArray[x]; END; IF j <> arrLength-1 THEN BEGIN FOR x := j+1 TO arrLength-1 DO BEGIN tempNotesArray[x-1] := notesArray[x]; tempTranspoArray[x-1] := transpoArray[x]; END; END; SetArrayLength(notesArray, (arrLength - 1)); SetArrayLength(transpoArray, (arrLength - 1)); notesArray := tempNotesArray; transpoArray := tempTranspoArray; SetArrayLength(tempNotesArray, 0); SetArrayLength(tempTranspoArray, 0); END; // DelArrayIndices // MainBEGIN nbOfMidi := GetLength(input); // get the number of incoming midi codes IF nbOfMidi > 0 THEN BEGIN SetLength(outPut,nbOfMidi); // set the number of output codes transpoVal := trunc(getValue(transpo)); // get the transpo value FOR i := 0 TO nbOfMidi-1 // loop for all input codes, for polyphonic data (chords) DO BEGIN GetMidiArrayValue(input,i,ReceivedMidi); // get each code arrLength := GetArrayLength(notesArray); // Refresh how many notes are waiting for note off // If received midi is NOTE ON then add note to array and current transposition to another array IF (ReceivedMidi.msg = 144) THEN BEGIN SetArrayLength(notesArray, (arrLength + 1)); // Expand note array for new note SetArrayLength(transpoArray, (arrLength + 1)); // Expand transposition value array for new note notesArray[arrLength] := (ReceivedMidi.data1 + transpoVal); // Add note number to newest slot transpoArray[arrLength] := transpoVal; // Add current transposition to newest slot // FOR DEBUGGING // writeln('ADD: ' + intToStr(ReceivedMidi.data1) + ' WITH: ' + intToStr(transpoVal)); ReceivedMidi.data1 := ReceivedMidi.data1 + transpoVal; // Adjust midi with transposition value SetMidiArrayValue(output,i,ReceivedMidi); // Set transformed midi to output END; // If received is NOTE OFF then take current transposition into account, find the note in array and remove from array IF (ReceivedMidi.msg = 128) AND (arrLength > 0) THEN BEGIN FOR j := 0 TO arrLength-1 // Go through all stored notes DO BEGIN IF notesArray[j] = (ReceivedMidi.data1 + transpoArray[j]) THEN BEGIN ReceivedMidi.data1 := (ReceivedMidi.data1 + transpoArray[j]); SetMidiArrayValue(output, i, ReceivedMidi); // Send note off to midi outlet // FOR DEBUGGING // writeln('REMOVE: ' + intToStr(notesArray[j])); DelArrayIndices; // call proc to remove note from arrays BREAK; // Break for-loop END; END; END; END; END ELSE SetLength(outPut,0); // nothing received, set out length to 0END. // mainStatistics: Posted by antwan — 23 Oct 2008, 13:36
Statistics: Posted by antwan — 22 Oct 2008, 07:33
Statistics: Posted by woodslanding — 22 Oct 2008, 05:52
Statistics: Posted by antwan — 21 Oct 2008, 21:48
Statistics: Posted by woodslanding — 21 Oct 2008, 18:31
Statistics: Posted by nay-seven — 19 Oct 2008, 22:44
Statistics: Posted by bsork — 19 Oct 2008, 22:04
Statistics: Posted by woodslanding — 28 Oct 2008, 16:45
Statistics: Posted by bsork — 28 Oct 2008, 13:00
CODE:
//////////////////////////////////////////////////////// transpose midi note// 2008-10-24: @Bsork, first version // 2008-10-26: @amiga909, 'wrap around' added //////////////////////////////////////////////////////VAR pIn, pOut, pTransp, pWrapAround : tParameter;TYPE tTransp = ARRAY OF integer;VAR transp : ARRAY OF tTransp;VAR tmp : tMidi;VAR len, transpose, i, tempTransp : integer;PROCEDURE Init;BEGIN pIn := CreateParam('midi in', ptMidi); SetIsOutput(pIn, FALSE); pOut := CreateParam('midi out', ptMidi); SetIsInput(pOut, FALSE); pTransp := CreateParam('transpose', ptDataFader); SetIsOutput(pTransp, FALSE); SetFormat(pTransp, '%.0f'); SetMin(pTransp, -127); SetMax(pTransp, 127); pWrapAround := CreateParam('wrap around', ptSwitch); SetIsOutput(pWrapAround, FALSE); SetArrayLength(transp, 16); FOR i := 0 TO 15 DO // A two-dimensional array; [16 channels][128 transpose values] SetArrayLength(transp[i], 128);END; // expects a noteOn msg with velocity > 0; outputs the transposed note value [0-127]FUNCTION calcTranspose (t: integer; wrap: single): integer;BEGIN IF wrap > 0 THEN BEGIN // IF (t > 127) THEN result := t - 128 ELSE IF (t < 0) THEN result := t + 128; END ELSE BEGIN IF t > 127 THEN result:= 127 ELSE IF t < 0 THEN result:=0 ELSE result:=t; END; END;// mainBEGIN len := GetLength(pIn); IF (len > 0) THEN BEGIN transpose := trunc(GetValue(pTransp)); SetLength(pOut, len); FOR i := 0 TO (len - 1) DO BEGIN GetMidiArrayValue(pIn, i, tmp); tempTransp := transpose + tmp.data1; IF (tmp.msg = 144) AND (tmp.data2 > 0) THEN BEGIN // NoteOn tempTransp:= calcTranspose(tempTransp, GetValue(pWrapAround)); transp[tmp.channel - 1][tmp.data1] := tempTransp; tmp.data1 := tempTransp; SetMidiArrayValue(pOut, i, tmp); END ELSE IF (tmp.msg = 128) or ((tmp.data2 = 144) and (tmp.data2 = 0)) THEN // NoteOff tmp.data1 := transp[tmp.channel - 1][tmp.data1]; SetMidiArrayValue(pOut, i, tmp); END; END ELSE BEGIN SetLength(pOut, 0); END;END.I'd like to add a little "party trick" if someone else is testing your rig: Add an LFO or random generator to the transpose value as I did when testing, it's quite confusing when the same key changes notes all the time!
Statistics: Posted by amiga909 — 26 Oct 2008, 15:26
I'd like to add a little "party trick" if someone else is testing your rig: Add an LFO or random generator to the transpose value as I did when testing, it's quite confusing when the same key changes notes all the time!It's turned the transpose (especially the octave control) into a performance tool!
Statistics: Posted by bsork — 26 Oct 2008, 08:37
CODE:
//// take input from two keyboards and assign one or both to a vst. also split and transpose.TYPE tNoteArr = ARRAY OF boolean;TYPE tStatus = RECORD low : integer; max : integer; sus : boolean; bend : boolean;END;TYPE tTransp = ARRAY OF integer;VAR transpositions : ARRAY OF tTransp;// parameters declarationvar input : Tparameter; // midi inputvar output : Tparameter; // midi outputvar key1 : Tparameter; // output notes from keyboard 1var key2 : Tparameter; // output notes from keyboard 2// these are not implemented yet....soon.var volKey1 : Tparameter; // send out a volume control signal for keyboard 1, if enabled as a sourcevar volKey2 : Tparameter; // send out a volume control signal for keyboard 2, if enabled as a sourcevar enable : Tparameter; // boolean control out for disabling VST if no keyboard is controlling itvar outCH : Tparameter; // rechannelize input. Value of 0 leaves output channel unchangedvar semi : TParameter; // transpose by semi-tonevar octave : TParameter; // transpose by octavevar split : Tparameter; // pitch below or above which notes are not sentvar upper : Tparameter; // send pitches above the split if on. otherwise send pitches below.var bytecount : integer;var midiLen : integer;var midi : TMidi;var transpose : integer;var splitVal : integer;var upperVal : integer;var key1Val : single;var key2Val : single;var key1ch : integer;var key2ch : integer;var i : integer;var channel : integer;// initialisation PROCEDURE init;BEGIN output := CreateParam('MIDIout',ptMidi); SetIsInput(Output,false); volKey1 := CreateParam('volK1',ptMidi); SetIsInput(volKey1,false); volKey2 := CreateParam('volK2',ptMidi); SetIsInput(volKey2,false); enable := CreateParam('vstEnable',ptDataField); SetIsInput(enable,false); input := CreateParam('MIDIin',ptMidi); SetIsOutput(Input,false); semi := CreateParam('semi',ptDataField); SetIsOutput(semi,false); octave := CreateParam('8va',ptDataField); SetIsOutput(octave,false); split := CreateParam('split',ptMidiNoteFader); SetIsOutput(split,false); upper := CreateParam('upper',ptSwitch); SetIsOutput(upper,false); key1 := CreateParam('key1', ptSwitch); SetIsOutput(key1,false); key2 := CreateParam('key2', ptSwitch); SetIsOutput(key2,false); outCH := CreateParam('outCH', ptDataField); SetIsOutput(outCH,false); key1ch := 1; key2ch := 2; SetArrayLength(transpositions, 2); FOR i := 0 TO 1 DO // we are going to ignore midi data on any but the 2 keyboard channels... SetArrayLength(transpositions[i], 128); //default values and formats SetDefaultValue(upper,1); SetDefaultValue(key1,1); SetDefaultValue(key2,1); SetFormat(split,'%.0f'); SetMin(split,1); SetMax(split,127); SetDefaultValue(split,1); SetFormat(semi,'%.0f'); SetMin(semi,-7); SetMax(semi,7); SetDefaultValue(semi,0); SetFormat(octave,'%.0f'); SetMin(octave,-4); SetMax(octave,4); SetDefaultValue(octave,0)end;PROCEDURE processNoteOns;BEGIN writeln('in noteon loop'); IF (((channel = key1ch) AND (key1Val = 1)) OR ((channel = key2ch) AND (key2Val = 1))) AND (((midi.data1 >= splitVal) AND (upperVal = 1)) OR ((midi.data1 < splitVal) AND (upperVal = 0))) THEN BEGIN transpositions[channel - 1][midi.data1] := transpose; // only works if keyboard ch's are 1 and 2.... midi.data1 := midi.data1 + transpose; SetMidiArrayValue(output, bytecount, midi); END; END; //process NoteonsPROCEDURE processNoteOffs;BEGIN midi.data1 := midi.data1 + transpositions[channel - 1][midi.data1]; // Retrieve stored transpose and add to NoteOff SetMidiArrayValue(output, bytecount, midi);END; //processNoteoffsPROCEDURE processSustain; // untestedBEGIN IF (midi.data1 < 64) THEN //send sus up on all instruments, selected or not... BEGIN SetMidiArrayValue(output, bytecount, midi); END ELSE IF (((channel = 1) AND (key1Val = 1)) OR ((channel = 2) AND (key2Val = 1))) THEN BEGIN IF (midi.data1 >= 64) THEN //send sus down only on selected instruments BEGIN SetMidiArrayValue(output, bytecount, midi); END; END;END; // process sustain // mainBEGIN midiLen := GetLength(input); IF (midiLen > 0) THEN BEGIN SetLength(output, midiLen); // set variables from inputs transpose := trunc(GetValue(semi) + ((getValue(octave) * 12))); splitVal := trunc(getValue(split)); upperVal := trunc(getValue(upper)); key1Val := trunc(getValue(key1)); key2Val := trunc(getValue(key2)); // process midi FOR bytecount := 0 TO (midiLen - 1) DO BEGIN GetMidiArrayValue(input, bytecount, midi); channel := midi.channel; IF ((midi.msg = 144) AND (midi.data2 > 0)) THEN BEGIN // Noteon processNoteons; END ELSE IF ((midi.msg = 128) OR ((midi.msg = 144) AND (midi.data2 = 0))) THEN BEGIN // NoteOff processNoteoffs; END ELSE IF (midi.msg = 176) THEN BEGIN processSustain; END; ///ELSE IF ((midi.msg = 224) pitchbend, etc. END; END // no midi in this block.... ELSE BEGIN SetLength(output, 0); END;END.Statistics: Posted by woodslanding — 26 Oct 2008, 02:01
CODE:
//////////////////////////////////////////////////////// TEST: midi message 1st byte + midi channel filtering//////////////////////////////////////////////////////// Paramters declarationvar input, txt : Tparameter;var tmp : TMidi;var len, i: integer; // initialisation procedureprocedure init;begin input := CreateParam('input',ptMidi); SetIsOutput(input,false); txt := CreateParam('txt',ptTextField); SetIsInput(txt,false);end;procedure writeMidi(m: TMidi);var s: string;beginsetLength(txt,50);s:= '[msg: ' + intToStr(m.msg) +'] [chn:'+ intToStr(m.channel) + ']';setStringValue(txt,s);writeln(s);end; // Main Loop procedurebegin len := getLength(input); if len > 0 then begin for i:=0 to len-1 do begin getMidiArrayValue(input,i,tmp); if (tmp.msg = 144) or (tmp.msg = 128) then writeMidi(tmp); if ((tmp.msg > 144) and (tmp.msg < 160)) or ((tmp.msg > 128) and (tmp.msg < 144)) then writeMidi(tmp); end; end;end.Statistics: Posted by amiga909 — 25 Oct 2008, 14:47
Statistics: Posted by bsork — 24 Oct 2008, 22:12
Statistics: Posted by amiga909 — 24 Oct 2008, 15:55
Statistics: Posted by antwan — 24 Oct 2008, 15:23
Statistics: Posted by amiga909 — 24 Oct 2008, 14:57
Statistics: Posted by antwan — 24 Oct 2008, 11:12
Statistics: Posted by woodslanding — 24 Oct 2008, 06:45
CODE:
VAR pIn, pOut, pTransp : tParameter;TYPE tTransp = ARRAY OF integer;VAR transp : ARRAY OF tTransp;VAR tmp : tMidi;VAR len, transpose, i : integer;PROCEDURE Init;BEGIN pIn := CreateParam('midi in', ptMidi); SetIsOutput(pIn, FALSE); pOut := CreateParam('midi out', ptMidi); SetIsInput(pOut, FALSE); pTransp := CreateParam('transpose', ptDataFader); SetIsOutput(pTransp, FALSE); SetFormat(pTransp, '%.0f'); SetMin(pTransp, -24); SetMax(pTransp, 24); SetArrayLength(transp, 16); FOR i := 0 TO 15 DO // A two-dimensional array; [16 channels][128 transpose values] SetArrayLength(transp[i], 128);END; // Init// mainBEGIN len := GetLength(pIn); IF (len > 0) THEN BEGIN transpose := trunc(GetValue(pTransp)); SetLength(pOut, len); FOR i := 0 TO (len - 1) DO BEGIN GetMidiArrayValue(pIn, i, tmp); IF ((tmp.msg = 144) AND (tmp.data2 > 0)) THEN BEGIN // NoteOn transp[tmp.channel - 1][tmp.data1] := transpose; // Store transpose value used for NoteOn tmp.data1 := tmp.data1 + transpose; END ELSE IF ( (tmp.msg = 128) OR ((tmp.msg = 144) AND (tmp.data2 = 0))) THEN BEGIN // NoteOff tmp.data1 := tmp.data1 + transp[tmp.channel - 1][tmp.data1]; // Retrieve stored transpose and add to NoteOff END; SetMidiArrayValue(pOut, i, tmp); END; END ELSE BEGIN SetLength(pOut, 0); END;END.Running test with three RandomMidi modules spitting out notes didn't really give any definitive "winner" in CPU usage. Your script was in fact generally a tiny bit lower, but the occasional spikes that I could see for both was on the other hand generally more pronounced with your script. If I had restricted the script to ignore the MIDI channel, I guess I could have saved a bit on the CPU.Statistics: Posted by bsork — 24 Oct 2008, 01:07
Hence, I'm having trouble understanding the rest of itHowever, instead of using lots of temporary arrys, loops etc, I think it's a lot easier to use the MIDI data for array lookups.
Statistics: Posted by antwan — 23 Oct 2008, 16:33
Statistics: Posted by bsork — 23 Oct 2008, 14:19
CODE:
// ADVANCED MIDI TRANSPOSE// Parameters declarationVAR input : Tparameter;VAR output : Tparameter;VAR transpo : TParameter;// Global variablesVAR i, j, x : integer;VAR nbOfMidi : integer;VAR transpoVal : integer;VAR arrLength : integer;VAR ReceivedMidi : TMidi;VAR notesArray : Array of integer; // This holds the note numbers that are waiting for note offsVAR transpoArray : Array of integer; // This holds the transposition value that was in place when each of the notes in notesArray was addedVAR tempNotesArray : Array of integer; // A temp array used in proc DelArrayIndicesVAR tempTranspoArray : Array of integer; // A temp array used in proc DelArrayIndices// Initialisation - create parametersPROCEDURE init;BEGIN Input := CreateParam('In',ptMidi); Output := CreateParam('Out',ptMidi); transpo := CreateParam('transpo',ptDataFader); SetIsInput(Output,false); SetIsOutPut(Input,false); SetIsOutPut(transpo,false); SetFormat(transpo,'%.0f'); SetMin(transpo,-24); SetMax(transpo,24);END; // initPROCEDURE DelArrayIndices;BEGIN SetArrayLength(tempNotesArray, (arrLength-1)); SetArrayLength(tempTranspoArray, (arrLength-1)); FOR x := 0 TO j-1 DO BEGIN tempNotesArray[x] := notesArray[x]; tempTranspoArray[x] := transpoArray[x]; END; IF j <> arrLength-1 THEN BEGIN FOR x := j+1 TO arrLength-1 DO BEGIN tempNotesArray[x-1] := notesArray[x]; tempTranspoArray[x-1] := transpoArray[x]; END; END; SetArrayLength(notesArray, (arrLength - 1)); SetArrayLength(transpoArray, (arrLength - 1)); notesArray := tempNotesArray; transpoArray := tempTranspoArray; SetArrayLength(tempNotesArray, 0); SetArrayLength(tempTranspoArray, 0); END; // DelArrayIndices // MainBEGIN nbOfMidi := GetLength(input); // get the number of incoming midi codes IF nbOfMidi > 0 THEN BEGIN SetLength(outPut,nbOfMidi); // set the number of output codes transpoVal := trunc(getValue(transpo)); // get the transpo value FOR i := 0 TO nbOfMidi-1 // loop for all input codes, for polyphonic data (chords) DO BEGIN GetMidiArrayValue(input,i,ReceivedMidi); // get each code arrLength := GetArrayLength(notesArray); // Refresh how many notes are waiting for note off // If received midi is NOTE ON then add note to array and current transposition to another array IF (ReceivedMidi.msg = 144) THEN BEGIN SetArrayLength(notesArray, (arrLength + 1)); // Expand note array for new note SetArrayLength(transpoArray, (arrLength + 1)); // Expand transposition value array for new note notesArray[arrLength] := (ReceivedMidi.data1 + transpoVal); // Add note number to newest slot transpoArray[arrLength] := transpoVal; // Add current transposition to newest slot // FOR DEBUGGING // writeln('ADD: ' + intToStr(ReceivedMidi.data1) + ' WITH: ' + intToStr(transpoVal)); ReceivedMidi.data1 := ReceivedMidi.data1 + transpoVal; // Adjust midi with transposition value SetMidiArrayValue(output,i,ReceivedMidi); // Set transformed midi to output END; // If received is NOTE OFF then take current transposition into account, find the note in array and remove from array IF (ReceivedMidi.msg = 128) AND (arrLength > 0) THEN BEGIN FOR j := 0 TO arrLength-1 // Go through all stored notes DO BEGIN IF notesArray[j] = (ReceivedMidi.data1 + transpoArray[j]) THEN BEGIN ReceivedMidi.data1 := (ReceivedMidi.data1 + transpoArray[j]); SetMidiArrayValue(output, i, ReceivedMidi); // Send note off to midi outlet // FOR DEBUGGING // writeln('REMOVE: ' + intToStr(notesArray[j])); DelArrayIndices; // call proc to remove note from arrays BREAK; // Break for-loop END; END; END; END; END ELSE SetLength(outPut,0); // nothing received, set out length to 0END. // mainStatistics: Posted by antwan — 23 Oct 2008, 13:36
Statistics: Posted by antwan — 22 Oct 2008, 07:33
Statistics: Posted by woodslanding — 22 Oct 2008, 05:52
Statistics: Posted by antwan — 21 Oct 2008, 21:48
Statistics: Posted by woodslanding — 21 Oct 2008, 18:31
Statistics: Posted by nay-seven — 19 Oct 2008, 22:44
Statistics: Posted by bsork — 19 Oct 2008, 22:04