ArrayArrayArrayArrayArrayArrayArrayArrayArrayArray BrainModular BrainModular Users Forum 2008-11-12T16:35:10+02:00 https://brainmodular.com/forums/app.php/feed/topic/1127 2008-11-12T16:35:10+02:00 2008-11-12T16:35:10+02:00 https://brainmodular.com/forums/viewtopic.php?t=1127&p=6219#p6219 <![CDATA[compile problem with midi script]]> changes:
- almost all algos replaced
- convert CC or PC to Notes
- removed functionality: compress note, convert midi message to notes (polyphonic)
- more demos: noteLegato.mp3 , noteLegato.stepMod.mp3 (LFO->+createMidi->MEP.script->T-Pulse VSTii)

CODE:

&#40;* no compress, no multinoteConvertMEP 0.95 by amiga909// 2008-10-29&#58; first version// 2008-11-12&#58; release version// credits to&#58; bSork, senso &#40;www.sensomusic.com/forums&#41;// <Description> midi tool roughly inspired by Yamaha MEP-4 Midi Event Processor.     MEP was designed for experimental purposes but it can be also used as a midi utility.     download the original MEP-4 manual here&#58;     http&#58;//www2.yamaha.co.jp/manual/pdf/emi/english/synth/MEP4E.PDF // <Features> prevent hanging notes, swap data bytes, convert to notes, ..// <Processing chain>     <input>    ->    select     ->                        // filter input &#40;if midi thru on&#58; pass filtered data&#41;      swapBytes  -> inverse   ->           // modify input bytes    expand     -> transpose ->           // calculate input bytes    wrap       -> step&#40;x%y&#41; -> limit ->  // limit/rescale input bytes     affectByte ->                        // modify output bytes    convert    ->                        // change output type    <output>   <-// <Parameters> // select event &#58; select an event type for processing &#40;if event type is NoteOn+Off and                   convert is not bypassed, NoteOff messages are filtered in some cases&#41;.  // mute         &#58; filter selected event.  // midi thru    &#58; output all other event types. // affect byte  &#58; process first or second data byte or both. if only one                   byte is selected, then the other byte is output unprocessed.// inv. byte1/2 &#58; inverse incoming data byte. high value -> low, low -> high.// swap bytes   &#58; swap first and second byte &#40;eg. convert velocity to noteOn&#41;.// expand       &#58; choose a multiplication factor from 0.0625 to 16.// transpose    &#58; add or subtract value.// wrap around  &#58; if a value as a result of expanding or transposing is not between 1 and 128,                   and if wrap around is off&#58; result is 128 or 1,                   if wrap around is on&#58; &#40;1-1=128;128+1=1;&#41;.// step         &#58; only messages with a data byte that is a multiple of the Step                   will be allowed through.// limit low/hi &#58; specify the output data range.                  use a range fader &#40;interface design&#41; for control.  // limit mode   &#58; limit hard limits the output and filters values out of range,                   scale rescales to desired range.// convert      &#58; transform input event to another midi message.                   &#40;mode 1&#58; convert to notes&#58; even events are noteOns, odd events are noteOffs                  hanging notes; in contrary NoteOff! or NoteOn! create invalid midi notes&#41;.    // <Notes>   - Aftertouch, PC and other messages are not tested as much as Notes and CC   - compress is very beta. maybe it will be removed... &#40;not original MEP anyway&#41;   - the interface will maybe be reworked. there is the idea to have 8 toggle buttons that can each hold     an operation parameter &#40;à la instajungle&#41;.*&#41;VAR  pIn, pOut, pMult, pEvent, pDest, pWrap, pInv1, pInv2, pTransp, pBypass,      pNotesCount, pThru, pConv, pStep, pLimitHi, pLimitLo, pLimit, pSwap    &#58; TParameter;TYPE TMult    = ARRAY OF integer;VAR  mult     &#58; ARRAY OF TMult;VAR  pMultAr  &#58; ARRAY OF double;  VAR  tmp      &#58; TMidi;   VAR  multiply &#58; double;   VAR  len,i,tmpX,tmpY,tmpXX,tmpYY,tmpMsg,dest,transpose,limit,convert,event,step,convCnt,     limitLo,limitHi,tmpLimitLo, notesCount,filterByte,lenCount,lastConvNoteOn&#58; integer; VAR  isSwap, isWrap, isInv1, isInv2, isLimit, isConvNoteOff,       isFirstByte, isSecondByte, isConvert, isConvertToNotes      &#58; boolean;CONST NOTE_ON     = 144;CONST NOTE_OFF    = 128;CONST CONTROL_CHG = 176;CONST PROGRAM_CHG = 192;CONST PITCHBEND   = 224;CONST AFTER_MONO  = 208;CONST AFTER_POLY  = 160;CONST MIDI_CLOCK  = 248;CONST MIDI_START  = 250;CONST MIDI_CONT   = 251;CONST MIDI_STOP   = 252;CONST ACTIVE_SENS = 254;//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^//           //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// PROCEDURE Init;//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// VAR f_c1,f_c2&#58; integer; BEGIN pIn &#58;= createParam&#40;'midi in', ptMidi&#41;;  pOut &#58;= createParam&#40;'midi out', ptMidi&#41;; pEvent &#58;= createParam&#40;'select', ptListBox&#41;;   setListBoxString&#40;pEvent,  '"ALL","Note On+Off", "Control Change", "Program Change", "Pitch Bend", "Aftertouch"'&#41;;         pInv1 &#58;= createParam&#40;'inverse byte1', ptSwitch&#41;;      pInv2 &#58;= createParam&#40;'inverse byte2', ptSwitch&#41;;     pSwap &#58;= createParam&#40;'swap bytes', ptSwitch&#41;; pMult &#58;= createParam&#40;'expand', ptListBox&#41;;   setListBoxString&#40;pMult,  '        "-bypass-", "1/16",  "1/8", "1/4", "1/2","1","2","4","8","16"'&#41;;  pMultAr&#58;=&#91;1,          0.0625, 0.125,  0.25,  0.5,  1,  2,  4,  8,  16&#93;;       pTransp &#58;= createParam&#40;'transpose',ptDataFader&#41;;setMin&#40;pTransp,-128&#41;;setMax&#40;pTransp,127&#41;;  setSymbol&#40;pTransp, ''&#41;;setFormat&#40;pTransp,'-bypass-'&#41;;  pWrap &#58;= createParam&#40;'wrap around', ptSwitch&#41;;  pStep &#58;= createParam&#40;'step modulo', ptDataFader&#41;;setMin&#40;pStep,1&#41;;setMax&#40;pStep, 16&#41;;   setSymbol&#40;pStep,''&#41;;setFormat&#40;pStep,'-bypass-'&#41;; pLimitLo &#58;= createParam&#40;'lo limit', ptMidiNoteFader&#41;; setMax&#40;pLimitLo, 126&#41;; setMin&#40;pLimitLo, 0&#41;;    pLimitHi &#58;= createParam&#40;'hi limit', ptMidiNoteFader&#41;; setMin&#40;pLimitHi, 1&#41;;setMax&#40;pLimitHi, 127&#41;;   pLimit &#58;= createParam&#40;'limit mode', ptListBox&#41;;   setListBoxString&#40;pLimit,'"-bypass-","filter","rescale","compress"'&#41;;// if compress&#58; faders = ratio, threshold  setValue&#40;pLimit,1&#41;; setDefaultValue&#40;pLimit,0&#41;;pDest &#58;= createParam&#40;'affect', ptListBox&#41;;   setListBoxString&#40;pDest,'"1st byte &#40;note,cc.num,..&#41;", "2nd byte &#40;velo,cc.val,..&#41;", "1st and 2nd byte"'&#41;;    pConv &#58;= createParam&#40;'convert', ptListBox&#41;; // take all from 'Create Midi?'  setListBoxString&#40;pConv,  '"-bypass-","Note Legato","Note Poly &#40;mode1&#41;","Note Poly &#40;mode2&#41;","Note Poly &#40;random&#41;",'+  '"Control Change","Program Change", "Pitch Bend","Aftertouch Channel","Aftertouch Poly",'+  '"Timing Clock","Start","Stop","Continue","Active Sensing", "NoteOn !","NoteOff !"'&#41;;pThru &#58;= createParam&#40;'midi thru', ptSwitch&#41;; pBypass &#58;= createParam&#40;'mute', ptSwitch&#41;; pNotesCount &#58;= createParam&#40;'open notes', ptDataField&#41;; setReadOnly&#40;pNotesCount,true&#41;;  setMin&#40;pNotesCount,0&#41;;setMax&#40;pNotesCount,999&#41;;f_c1&#58;= 90099;f_c2&#58;= 60099; setColor&#40;pLimitHi,f_c1&#41;;setColor&#40;pLimitLo,f_c1&#41;;setColor&#40;pTransp,f_c1&#41;;setColor&#40;pThru,f_c2&#41;;setColor&#40;pStep,f_c1&#41;;setColor&#40;pWrap,f_c2&#41;;setColor&#40;pInv1,f_c2&#41;;setColor&#40;pInv2,f_c2&#41;;setColor&#40;pSwap,f_c2&#41;;setIsInput&#40;pOut,false&#41;;setIsInput&#40;pNotesCount,false&#41;;setIsOutput&#40;pIn,false&#41;;setIsOutput&#40;pEvent,false&#41;;setIsOutput&#40;pThru,false&#41;;setIsOutput&#40;pDest,false&#41;;setIsOutput&#40;pInv1,false&#41;;setIsOutput&#40;pInv2,false&#41;;setIsOutput&#40;pSwap,false&#41;;setIsOutput&#40;pMult,false&#41;; setIsOutput&#40;pTransp,false&#41;; setIsOutput&#40;pStep,false&#41;; setIsOutput&#40;pWrap,false&#41;;setIsOutput&#40;pLimit,false&#41;;setIsOutput&#40;pLimitLo,false&#41;;setIsOutput&#40;pLimitHi,false&#41;;setIsOutput&#40;pConv,false&#41;; setIsOutput&#40;pBypass,false&#41;; setValue&#40;pEvent,1&#41;;  setValue&#40;pDest,0&#41;; setValue&#40;pInv1,0&#41;;setValue&#40;pInv2,0&#41;;setValue&#40;pMult,GetLength&#40;pMult&#41;-1&#41;;setDefaultValue&#40;pMult,0&#41;;setValue&#40;pTransp,-128&#41;;setValue&#40;pStep,1&#41;;   setValue&#40;pWrap,0&#41;;setValue&#40;pLimitLo,0&#41;;setValue&#40;pLimitHi,127&#41;; setValue&#40;pLimit,0&#41;;setValue&#40;pConv,0&#41;;// array initsetArrayLength&#40;mult, 16&#41;;       FOR i &#58;= 0 TO 15 DO BEGIN         setArrayLength&#40;mult&#91;i&#93;, 128&#41;; // init &#91;16 channels&#93;&#91;128 multiply values&#93;   END;notesCount&#58;=0;convCnt&#58;=0;END; //^^^^^^^^^^^^^^^^^^^^^^^<F>^^^^^^^^^^^^^^^^^^^^^//// <F> isMidiMsg&#58; 'event' is a list of pEvent &#40;0=ALL&#41;//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// FUNCTION isMidiMsg&#40;msg&#58; integer; e&#58; integer&#41;&#58; boolean;BEGIN    IF      &#40;&#40;e=1&#41;OR&#40;e=0&#41;&#41; AND &#40;&#40;msg=NOTE_ON&#41;OR&#40;msg=NOTE_OFF&#41;&#41; THEN BEGIN      result &#58;= true; END  // Notes ELSE IF &#40;&#40;e=2&#41;OR&#40;e=0&#41;&#41; AND &#40;msg=CONTROL_CHG&#41; THEN BEGIN      result &#58;= true; END  //CtrlChg ELSE IF &#40;&#40;e=3&#41;OR&#40;e=0&#41;&#41; AND &#40;msg=PROGRAM_CHG&#41; THEN BEGIN     result &#58;= true; END  //PrgrChg ELSE IF &#40;&#40;e=4&#41;OR&#40;e=0&#41;&#41; AND &#40;msg=PITCHBEND&#41; THEN BEGIN      result &#58;= true; END  //PitchBend ELSE IF &#40;&#40;e=5&#41;OR&#40;e=0&#41;&#41; AND &#40;&#40;msg=AFTER_MONO&#41; OR &#40;msg=AFTER_POLY&#41;&#41; THEN BEGIN      result &#58;= true; END  //Aftertouch &#40;Channel, Poly&#41; ELSE BEGIN     result&#58;=false; END; END;// <F> isStep&#58; step limit data&#58; filter out &#40;? or compress->max, or compress->min&#41;//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// FUNCTION isStep&#40;val&#58; integer; stp&#58; integer&#41;&#58; boolean;BEGIN    IF NOT&#40;&#40;val+1&#41; MOD stp=0&#41; THEN BEGIN        result&#58;=true;    END    ELSE BEGIN        result&#58;=false;    END;END;// <F> isNoteOn&#58;  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// FUNCTION isNoteOn&#40;message&#58; byte;velocity&#58; byte&#41;&#58; boolean;BEGIN     IF &#40;message=NOTE_ON&#41;AND&#40;velocity>0&#41; THEN BEGIN         result&#58;=true;    END    ELSE BEGIN         result&#58;=false;     END;END;// <F> isNoteOff&#58;  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// FUNCTION isNoteOff&#40;message&#58; byte;velocity&#58; byte&#41;&#58; boolean;BEGIN      IF &#40;message=NOTE_OFF&#41;OR&#40;&#40;message=NOTE_ON&#41;AND&#40;velocity=0&#41;&#41; THEN BEGIN         result&#58;=true;    END    ELSE BEGIN         result&#58;=false;    END;END;// <F> setWrap&#58; wrap or limit byte range  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// FUNCTION setWrap &#40;t&#58; integer; wrap&#58; boolean&#41;&#58; integer;   // 777777 rename 'setWrap' BEGIN  IF isWrap THEN BEGIN     IF t<0 THEN BEGIN         result&#58;= 128 - &#40;&#40;t*-1&#41; MOD 128&#41;;             END     ELSE IF t>127 THEN BEGIN         result &#58;= t MOD 128;      END    ELSE BEGIN         result&#58;=t;    END; END ELSE BEGIN     IF t<0 THEN BEGIN         result&#58;=0;    END     ELSE IF t>127 THEN BEGIN         result&#58;=127;    END    ELSE BEGIN         result&#58;=t;    END; END;END;// &#58; setTransp&#58; //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// FUNCTION setTransp&#40;val&#58; integer; trsp&#58; integer; wrap&#58; boolean&#41;&#58;integer;BEGIN    val&#58;=val+trsp;    IF &#40;&#40;val>127&#41;OR&#40;val<0&#41;&#41; THEN BEGIN         IF isWrap THEN BEGIN            IF val>127 THEN BEGIN                 result&#58;=val-127;             END            ELSE BEGIN                 result&#58;=val+127;            END;        END        ELSE BEGIN             IF val>127 THEN BEGIN                result&#58;=127;             END            ELSE BEGIN // val<0                result&#58;=0;            END;        END;    END    ELSE BEGIN         result&#58;=0;     END;END;// <F> convert&#58;//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// // setConvert&#58; &#40;why not convert to&#58; clock , start, stop, cont?&#41;FUNCTION setConvert&#40;srcMsg&#58; byte;typeId&#58; integer&#41;&#58; byte;BEGINCASE typeId OF      0&#58; result&#58;=srcMsg; // bypass      1&#58; result&#58;=NOTE_ON; // NotesLegato      2&#58; result&#58;=NOTE_ON; // NotesPoly1      3&#58; result&#58;=NOTE_ON; // NotesPoly2      4&#58; result&#58;=NOTE_ON; // NotesPoly rnd      5&#58; result&#58;=CONTROL_CHG;        6&#58; result&#58;=PROGRAM_CHG;       7&#58; result&#58;=PITCHBEND; //&#40;Modwheel&#41;      8&#58; result&#58;=AFTER_MONO; // Aftert Channel      9&#58; result&#58;=AFTER_POLY; // Aftert Poly     10&#58; result&#58;=MIDI_CLOCK;       11&#58; result&#58;=MIDI_START;       12&#58; result&#58;=MIDI_STOP;      13&#58; result&#58;=MIDI_CONT;       14&#58; result&#58;=ACTIVE_SENS;      15&#58; result&#58;=NOTE_ON; // NoteON ONLY!     16&#58; result&#58;=NOTE_OFF; // NoteOFF ONLY!   ELSE BEGIN      result&#58;=srcMsg;   END;END;END;// <F> calcLimited&#58; returns multiplication value for limiting, or return 1 &#40;x*1=x; x>0&#41;//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// FUNCTION calcLimited &#40;val&#58; integer;lo&#58; integer;hi&#58; integer;mode&#58; integer&#41;&#58; integer; VAR r  &#58; double;  BEGIN  //writeln&#40;'val&#58;'+inttostr&#40;val&#41;&#41;    IF mode<=1 THEN BEGIN  // filter, bypass, not used here        result&#58;=val;     END      ELSE IF mode=2 THEN BEGIN // scale        r &#58;= 128/&#40;hi-lo&#41;;        val&#58;= trunc&#40;&#40;val+1&#41;/r&#41;;        result&#58;= val+lo;            END     ELSE BEGIN         result&#58;=val;     END;END;    //^^^^^^^^^^^^^^^^^^^^^^^<P>^^^^^^^^^^^^^^^^^^^^^//// <P> countNotes&#58;  PROCEDURE countNotes&#40;isANoteAndON&#58;boolean&#41;;//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^//BEGIN       IF isANoteAndON THEN BEGIN         notesCount&#58;=notesCount+1             END    ELSE BEGIN        notesCount&#58;=notesCount-1;       END;       END;// <P> convertToLegatoNotes&#58; isConvert AND isNoteOff=false &#40;dont process noteOff for eg. note->cc&#41;//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// PROCEDURE convertToLegatoNotes;BEGIN     IF  convCnt MOD 2 = 1  THEN BEGIN          tmp.data1&#58;=byte&#40;lastConvNoteOn&#41;;        tmp.msg&#58;=byte&#40;NOTE_OFF&#41;;     END    ELSE BEGIN         lastConvNoteOn&#58;=tmp.data1;        tmp.msg&#58;=byte&#40;NOTE_ON&#41;;      END;    convCnt&#58;=convCnt+1;     IF convCnt=1028 THEN BEGIN convCnt&#58;=0; END;END;// <P> initLimitRange&#58; expect&#58; limitHi and limitLo are getValue&#40;p&#41; //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// PROCEDURE initLimitRange;BEGIN  IF NOT&#40;limit=3&#41; THEN BEGIN  // if limit is compress&#58; thres/ratio fader functions      IF limitHi-limitLo< 0 THEN BEGIN            tmpLimitLo&#58;=limitLo;          limitLo&#58;=limitHi;          limitHi&#58;=tmpLimitLo       END      ELSE IF limitHi-limitLo=0 THEN BEGIN          IF limitHi=128 THEN BEGIN               limitLo&#58;=127;           END          ELSE BEGIN              limitHi&#58;=limitHi+1;          END;      END; END; END;                            // <P> setDataSymbols&#58; //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// PROCEDURE setDataSymbols;VAR tr&#58; integer;BEGIN                  IF &#40;trunc&#40;getValue&#40;pStep&#41;&#41;<= 1&#41; THEN BEGIN         setSymbol&#40;pStep,''&#41;;setFormat&#40;pStep,'-bypass-'&#41;;     END     ELSE BEGIN          setSymbol&#40;pStep,'%'&#41;; setFormat&#40;pStep,'%.0f'&#41;    END;         tr&#58;=trunc&#40;getValue&#40;pTransp&#41;&#41;;    IF tr>0 THEN BEGIN         setSymbol&#40;pTransp,'+'&#41;; setFormat&#40;pTransp,'%.0f'&#41;;      END    ELSE IF &#40;tr=&#40;-128&#41;&#41;OR&#40;tr=0&#41; THEN BEGIN         setSymbol&#40;pTransp,''&#41;; setFormat&#40;pTransp,'-bypass-'&#41;;     END    ELSE BEGIN          setSymbol&#40;pTransp,''&#41;;setFormat&#40;pTransp,'%.0f'&#41;;      END;    END;//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^|   //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^|    // main  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|     //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^|       //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^|BEGIN         len &#58;= getLength&#40;pIn&#41;;   lenCount&#58;= len;         IF len > 0 THEN BEGIN            multiply&#58;=pMultAr&#91;trunc&#40;getValue&#40;pMult&#41;&#41;&#93;;      transpose&#58;= trunc&#40;getValue&#40;pTransp&#41;&#41;;       IF &#40;transpose=&#40;-128&#41;&#41; THEN BEGIN // control&#58; bypass at the left end for convenience          transpose&#58;=0;       END;      event&#58;=trunc&#40;getValue&#40;pEvent&#41;&#41;;      dest&#58;=trunc&#40;getValue&#40;pDest&#41;&#41;;      isFirstByte&#58;=&#40;dest=2&#41;OR&#40;dest=0&#41;;       isSecondByte&#58;=&#40;dest=2&#41;OR&#40;dest=1&#41;;      limit&#58;=trunc&#40;getValue&#40;pLimit&#41;&#41;;      limitLo&#58;=trunc&#40;getValue&#40;pLimitLo&#41;&#41;;      limitHi&#58;=trunc&#40;getValue&#40;pLimitHi&#41;&#41;;            isLimit&#58;=&#40;limit>0&#41; AND &#40;&#40;limitLo>=1&#41;OR&#40;limitHi<=126&#41;&#41;;       initLimitRange&#40;&#41;;      convert&#58;=trunc&#40;getValue&#40;pConv&#41;&#41;;       isConvert&#58;=convert>0;      isConvertToNotes&#58;=convert=1;      isConvNoteOff&#58;=false;       step&#58;=trunc&#40;getValue&#40;pStep&#41;&#41;;       isInv1&#58;=getValue&#40;pInv1&#41;>0;       isInv2&#58;=getValue&#40;pInv2&#41;>0;         isSwap&#58;=getValue&#40;pSwap&#41;>0;          isWrap&#58;=getValue&#40;pWrap&#41;>0;      FOR i &#58;= 0 TO &#40;len - 1&#41; DO BEGIN          getMidiArrayValue&#40;pIn, i, tmp&#41;;          IF  &#40;getValue&#40;pBypass&#41;=0&#41; AND &#40;isMidiMsg&#40;tmp.msg,event&#41;&#41; THEN BEGIN                tmpMsg&#58;= tmp.msg;             tmpX  &#58;= tmp.data1;             tmpY  &#58;= tmp.data2;               tmpXX &#58;= tmpX; // store orig. val for noteList             tmpYY &#58;= tmpY;             IF isInv1 THEN BEGIN                 tmpX&#58;= 127 - tmpX;             END;             IF isInv2 THEN BEGIN                   tmpY&#58;= 127 - tmpY;             END;                           IF isSwap THEN BEGIN                    tmpX &#58;= tmpY;                     tmpY &#58;= tmpXX;                END;                      // affect byte 1              IF isFirstByte THEN BEGIN    // 1st byte&#58; process 1st+2nd byte if dest=2                  tmpX &#58;= trunc&#40;multiply*tmpX&#41;;                 tmpX &#58;= tmpX + &#40;transpose&#41;;                 tmpX &#58;= setWrap&#40;tmpX, isWrap&#41;; // wrap or hard limit                  IF isLimit THEN BEGIN                     tmpX &#58;= calcLimited&#40;tmpX,limitLo,limitHi,limit&#41;;                 END;                  tmp.data1 &#58;= byte&#40;tmpX&#41;;                END;              // affect byte 2              IF isSecondByte THEN BEGIN                    tmpY &#58;= trunc&#40;multiply*tmpY&#41;;                 tmpY &#58;= tmpY + &#40;transpose&#41;;                 tmpY &#58;= setWrap&#40;tmpY, isWrap&#41;; // wrap or hard limit                  IF isLimit THEN BEGIN                     tmpY &#58;= calcLimited&#40;tmpY,limitLo,limitHi,limit&#41;;                 END;                  tmp.data2 &#58;= byte&#40;tmpY&#41;;                       END;               // prevent hanging notes &#40;tmpXX for swapped note values&#41;             IF isNoteOn&#40;tmpMsg,tmpYY&#41; THEN BEGIN                     mult&#91;tmp.channel - 1&#93;&#91;tmpXX&#93; &#58;= tmp.data1;  // tmpXX&#40;old 1st byte&#41; needed for noteOff value                           END             ELSE IF &#40;&#40;isConvertToNotes=false&#41; AND &#40;isNoteOff&#40;tmpMsg,tmpYY&#41;=true&#41;&#41; THEN BEGIN //! if convert=>Notes&#58;                   tmp.data1 &#58;= mult&#91;tmp.channel - 1&#93;&#91;tmpXX&#93;; // set NoteOff value from original NoteOn value             END;             // affect msg&#58; convert event             IF isConvert THEN BEGIN                       IF isConvertToNotes THEN BEGIN                          convertToLegatoNotes&#40;&#41;;                      END                       ELSE BEGIN // isConvertToNotes=false                          IF isNoteOff&#40;tmpMsg,tmpYY&#41;=true THEN BEGIN                              isConvNoteOff&#58;=true;  // filter flag for output                         END                          ELSE BEGIN                              tmp.msg&#58;=setConvert&#40;tmpMsg, convert&#41;;                         END;                     END;                   END;             IF  isFirstByte OR &#40;isFirstByte AND isSecondByte&#41; THEN BEGIN                  filterByte&#58;= tmpX;             END               ELSE BEGIN                  filterByte&#58;= tmpY;             END;             IF  &#40;isConvNoteOff&#41; OR    // if convert to notes dont convert noteOff                 &#40;&#40;limit=1&#41;AND&#40;limitLo>filterByte&#41;&#41; OR &#40;limitHi<filterByte&#41;  OR                  &#40;step>1&#41;AND&#40;isStep&#40;filterByte,step&#41;&#41;   THEN BEGIN  // filter message                  lenCount&#58;=lenCount-1;             END              ELSE BEGIN                 IF isNoteOn&#40;tmp.msg,tmp.data2&#41; THEN BEGIN                    countNotes&#40;true&#41;;               END               ELSE IF isNoteOff&#40;tmp.msg,tmp.data2&#41; THEN BEGIN                    countNotes&#40;false&#41;;               END;                      setLength&#40;pOut,lenCount&#41;;                 setMidiArrayValue&#40;pOut, i, tmp&#41;;  // write modified message             END;              END                // ! isMidiMsg&#40;&#41;            ELSE BEGIN                  IF &#40;getValue&#40;pThru&#41;>0&#41; THEN BEGIN                       setMidiArrayValue&#40;pOut, i, tmp&#41;;                   END                 ELSE BEGIN                      setLength&#40;pOut, 0&#41;;                  END;            END;        END;  // &#40;FOR i &#58;= 0 ..           END    ELSE BEGIN       setLength&#40;pOut, 0&#41;;    END; // len = 0 setValue&#40;pNotesCount, notesCount&#41;;setDataSymbols&#40;&#41;;END.

Statistics: Posted by amiga909 — 12 Nov 2008, 15:35


]]>
2008-11-07T21:25:09+02:00 2008-11-07T21:25:09+02:00 https://brainmodular.com/forums/viewtopic.php?t=1127&p=6150#p6150 <![CDATA[compile problem with midi script]]> the idea is to have a midi effect patch for live use. using midi effects live isnt exactly popular though.

trying it with vsti's bSorks noteoff solution works great, here from a first try.
http://thaumat.org/_permShare/mp3/mep.draft.t1.mp3
used: a piano roll with a drum pattern, ephonic drumatic , tpmusic t-pulse, and 2x mep script for each plugin.

Statistics: Posted by amiga909 — 07 Nov 2008, 20:25


]]>
2008-11-04T23:52:33+02:00 2008-11-04T23:52:33+02:00 https://brainmodular.com/forums/viewtopic.php?t=1127&p=6109#p6109 <![CDATA[compile problem with midi script]]>

its not a MEP-4 emulation, btw. its an experimental midi tool to learn the script language,
the only thing it has in common are most parameters and some of their ranges.
i try to avoid the hanging notes problem which the MEP-4 does not. on the other hand the MEP features channel filter/routing, mid delay, data presetting or stuff regarding its 4 ins and outs. personally I like to deal with channel filtering before or after a midi effect, midi delay already exists as a script and if you'd need 4in/outs you can use 4 instances of the script.
do you think if something essential from the MEP-4 is missing in the script?

guess i'll post a running beta with all features implemented here. to finish this script it will take some more time..

Statistics: Posted by amiga909 — 04 Nov 2008, 22:52


]]>
2008-11-04T22:43:59+02:00 2008-11-04T22:43:59+02:00 https://brainmodular.com/forums/viewtopic.php?t=1127&p=6108#p6108 <![CDATA[compile problem with midi script]]> Statistics: Posted by bsork — 04 Nov 2008, 21:43


]]>
2008-11-04T22:29:57+02:00 2008-11-04T22:29:57+02:00 https://brainmodular.com/forums/viewtopic.php?t=1127&p=6107#p6107 <![CDATA[compile problem with midi script]]> will you post it as add-on?

Statistics: Posted by senso — 04 Nov 2008, 21:29


]]>
2008-11-04T21:10:27+02:00 2008-11-04T21:10:27+02:00 https://brainmodular.com/forums/viewtopic.php?t=1127&p=6106#p6106 <![CDATA[compile problem with midi script]]>
I used to have one of those yamaha boxes, it was awesome!

cheers!
-e

Statistics: Posted by woodslanding — 04 Nov 2008, 20:10


]]>
2008-11-04T16:55:48+02:00 2008-11-04T16:55:48+02:00 https://brainmodular.com/forums/viewtopic.php?t=1127&p=6097#p6097 <![CDATA[compile problem with midi script]]> great explanation too.


(* blabla *) multiline comment compiles here without any problems.

btw: tkx bsork, based on another post of you I have corrected the setLength(pOut, len) thing (output array will now get smaller when select input data is filtered)

Statistics: Posted by amiga909 — 04 Nov 2008, 15:55


]]>
2008-11-04T15:17:46+02:00 2008-11-04T15:17:46+02:00 https://brainmodular.com/forums/viewtopic.php?t=1127&p=6093#p6093 <![CDATA[compile problem with midi script]]>
replace

CODE:

setIsInput&#40;NotesCount,false&#41;;bysetIsInput&#40;pNotesCount,false&#41;;
it works
the parameter are in fact numbers which represent their ID
pIn = 0
pOut = 1
...
in the order of creation

for example

CODE:

setIsInput&#40;pIn,false&#41;;is totally equivalent to setIsInput&#40;0,false&#41;;

Statistics: Posted by senso — 04 Nov 2008, 14:17


]]>
2008-11-04T11:44:24+02:00 2008-11-04T11:44:24+02:00 https://brainmodular.com/forums/viewtopic.php?t=1127&p=6085#p6085 <![CDATA[compile problem with midi script]]> Statistics: Posted by bsork — 04 Nov 2008, 10:44


]]>
2008-11-04T09:47:07+02:00 2008-11-04T09:47:07+02:00 https://brainmodular.com/forums/viewtopic.php?t=1127&p=6081#p6081 <![CDATA[compile problem with midi script]]>
got a problem with this (unfinished) script here.

when I compile it the midi in input pin is not generated. (using v.4.01)

further I get some cpu lags and freezes but this could be caused by my shitty office computer.
and yes, I hope this script will have some practical use :)

thaumat.org/tmp/_transfer/MEP.0.037.script

CODE:

&#40;* MEP 0.037// 2008-11-29&#58; @amiga909// credits to&#58; bSork, senso &#40;www.sensomusic.com/forums&#41;// <Description>// MEP&#58; midi tool roughly inspired by Yamaha MEP-4 Midi Event Processor.      download the original MEP-4 manual here&#58;      http&#58;//www2.yamaha.co.jp/manual/pdf/emi/english/synth/MEP4E.PDF // Features&#58; prevent hanging notes, swap data bytes, convert to notes or system messages, ..// Processing chain&#58;     <input>    ->    select     ->                        // filter input &#40;if midi thru on&#58; pass filtered data&#41;      inverse    -> swapBytes ->           // modify input bytes    expand     -> transpose ->           // calculate input bytes    wrap       -> step&#40;x%y&#41; -> limit ->  // limit/rescale input bytes     affectByte ->                        // modify output bytes    convert    ->                        // change output type    <output>   <-// <Parameters> // select event &#58; select an event type for processing // midi thru    &#58; output all other event types.                    !&#123;sysex, clock and activesensing are always filtered&#125;// affect byte  &#58; process first or second data byte or both. if only one                   byte is selected, then the other byte is output unprocessed.// inv. byte1/2 &#58; inverse incoming data byte. high value -> low, low -> high.// swap bytes   &#58; swap first and second byte &#40;eg. convert velocity to noteOn&#41;.// expand       &#58; choose a multiplication factor between 0.0625 to 16// transpose    &#58; add or subtract value// wrap around  &#58; if a value as a result of expanding or transposing is not between 1 and 128,                   and if wrap around is off&#58; result is 128 or 1,                   if wrap around is on&#58; &#40;1-1=128;128+1=1;&#41;.// step         &#58; only messages with a data byte that is a multiple of the Step                   will be allowed through.// limit low/hi &#58; specify the output data range.                  use a range fader &#40;interface design&#41; for control.  // limit mode   &#58; limit hard limits the output and filters values out of range                   scale rescales to desired range&#58; value/128 => value/newRange // convert      &#58; transform input event to CC, PC, PitchBend or Aftertouch// <Notes>   Aftertouch, PC and other messages are not tested. *&#41;VAR pIn, pOut, pMult,  pEvent, pDest, pWrap,pThru, pSwap,  pInv1, pInv2, pTransp,  pNotesCount,    pStep,  pLimitHi, pLimitLo, pLimit, pConv &#58; TParameter;TYPE TMult = ARRAY OF integer;VAR mult &#58; ARRAY OF TMult;VAR pMultAr&#58; ARRAY OF double; TYPE TBool = ARRAY OF boolean; // convert -> notesVAR notesList&#58; ARRAY OF TBool;VAR tmp&#58; TMidi;   VAR multiply&#58; double;   VAR len, i, tmpX ,tmpY, tmpXX, tmpDest,tmpMsg, transpose, limit, convert, tmpEvent,limitLo, limitHi, tmpLimitLo, step, notesCount,filterByte,lenCount&#58; integer; VAR isNoteOff, isNoteOn, isSwap, isThru,isWrap, isStepActive, isInv1,isInv2,isConvert,isLimit,isFirstByte,isSecondByte&#58; boolean;//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^//           //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// PROCEDURE Init;//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// VAR f_c1,f_c2,f_c3&#58; integer;BEGINpIn &#58;= createParam&#40;'midi in', ptMidi&#41;;  pOut &#58;= createParam&#40;'midi out', ptMidi&#41;; pEvent &#58;= createParam&#40;'select', ptListBox&#41;;   setListBoxString&#40;pEvent,  '"ALL","Note On+Off", "Control Change", "Program Change", "Pitch Bend", "Aftertouch"'&#41;;         pInv1 &#58;= createParam&#40;'inverse byte1', ptSwitch&#41;;      pInv2 &#58;= createParam&#40;'inverse byte2', ptSwitch&#41;;     pSwap &#58;= createParam&#40;'swap bytes', ptSwitch&#41;; pMult &#58;= createParam&#40;'expand', ptListBox&#41;;   setListBoxString&#40;pMult,  '        "-bypass-", "1/16",  "1/8", "1/4", "1/2","1","2","4","8","16"'&#41;;  pMultAr&#58;=&#91;1,          0.0625, 0.125,  0.25,  0.5,  1,  2,  4,  8,  16&#93;;       pTransp &#58;= createParam&#40;'transpose',ptDataFader&#41;;setMin&#40;pTransp,-128&#41;;setMax&#40;pTransp,127&#41;;  setSymbol&#40;pTransp, ''&#41;;setFormat&#40;pTransp,'-bypass-'&#41;; pStep &#58;= createParam&#40;'step', ptDataFader&#41;;setMin&#40;pStep,1&#41;;setMax&#40;pStep, 16&#41;;   setSymbol&#40;pStep,''&#41;;setFormat&#40;pStep,'-bypass-'&#41;;  pWrap &#58;= createParam&#40;'wrap around', ptSwitch&#41;;  pLimitLo &#58;= createParam&#40;'lo limit', ptMidiNoteFader&#41;; setMax&#40;pLimitLo, 126&#41;; setMin&#40;pLimitLo, 0&#41;;    pLimitHi &#58;= createParam&#40;'hi limit', ptMidiNoteFader&#41;; setMin&#40;pLimitHi, 1&#41;;setMax&#40;pLimitHi, 127&#41;;   pLimit &#58;= createParam&#40;'limit mode', ptListBox&#41;;   setListBoxString&#40;pLimit,'"-bypass-","filter","rescale","compress"'&#41;;// if compress&#58; faders = ratio, threshold  setValue&#40;pLimit,1&#41;; setDefaultValue&#40;pLimit,0&#41;;pDest &#58;= createParam&#40;'affect byte', ptListBox&#41;;   setListBoxString&#40;pDest,'"1&#40;note,cc.num,..&#41;", "2&#40;velo,cc.val,..&#41;", "1 + 2"'&#41;;    pConv &#58;= createParam&#40;'convert', ptListBox&#41;; // take all from 'Create Midi?'  setListBoxString&#40;pConv,  '"-bypass-","Note Legato","Note Poly &#40;mode1&#41;","Note Poly &#40;mode2&#41;","Control Change","Program Change", "Pitch Bend","Aftertouch Channel","Aftertouch Poly", "Timing Clock","Start","Stop","Continue","Active Sensing", "NoteOn !","NoteOff !"'&#41;;pThru &#58;= createParam&#40;'midi thru', ptSwitch&#41;; pNotesCount &#58;= createParam&#40;'open notes', ptDataField&#41;; setReadOnly&#40;pNotesCount,true&#41;;  setMin&#40;pNotesCount,0&#41;;setMax&#40;pNotesCount,999&#41;;f_c1&#58;= 90099;f_c2&#58;= 60099;f_c3&#58;= 6666666; setColor&#40;pLimitHi,f_c1&#41;; setColor&#40;pLimitLo,f_c1&#41;;setColor&#40;pTransp,f_c1&#41;;setColor&#40;pStep,f_c1&#41;; setColor&#40;pWrap,f_c2&#41;;setColor&#40;pThru,f_c2&#41;;setColor&#40;pInv1,f_c2&#41;;setColor&#40;pInv2,f_c2&#41;;setColor&#40;pSwap,f_c2&#41;; //setColor&#40;pNotesCount,f_c3&#41;;setIsInput&#40;pOut,false&#41;;setIsInput&#40;NotesCount,false&#41;;setIsOutput&#40;pIn,false&#41;;setIsOutput&#40;pEvent,false&#41;;setIsOutput&#40;pThru,false&#41;;setIsOutput&#40;pDest,false&#41;;setIsOutput&#40;pInv1,false&#41;;setIsOutput&#40;pInv2,false&#41;;setIsOutput&#40;pSwap,false&#41;;setIsOutput&#40;pMult,false&#41;;//setIsOutput&#40;pMultSw,false&#41;;setIsOutput&#40;pTransp,false&#41;;//setIsOutput&#40;pTranspSw,false&#41;;setIsOutput&#40;pStep,false&#41;;//setIsOutput&#40;pStepSw,false&#41;;setIsOutput&#40;pWrap,false&#41;;setIsOutput&#40;pLimit,false&#41;;setIsOutput&#40;pLimitLo,false&#41;;setIsOutput&#40;pLimitHi,false&#41;;setIsOutput&#40;pConv,false&#41;; setValue&#40;pEvent,1&#41;;  setValue&#40;pDest,0&#41;; setValue&#40;pInv1,0&#41;;setValue&#40;pInv2,0&#41;;setValue&#40;pMult,GetLength&#40;pMult&#41;-1&#41;;setDefaultValue&#40;pMult,0&#41;;setValue&#40;pTransp,-128&#41;;setValue&#40;pStep,1&#41;;   setValue&#40;pWrap,0&#41;;setValue&#40;pLimitLo,0&#41;;setValue&#40;pLimitHi,127&#41;; setValue&#40;pLimit,0&#41;;setValue&#40;pConv,0&#41;;setArrayLength&#40;mult, 16&#41;;     setArrayLength&#40;notesList, 16&#41;;    FOR i &#58;= 0 TO 15 DO BEGIN         setArrayLength&#40;mult&#91;i&#93;, 128&#41;; // init &#91;16 channels&#93;&#91;128 multiply values&#93;      SetArrayLength&#40;notesList&#91;i&#93;, 128&#41;;    END;notesCount&#58;=0;END; // <F> isMidiMsg&#58; 'event' is a list of pEvent &#40;0=ALL&#41;. filters sysex, clock and system messages//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// FUNCTION isMidiMsg&#40;msg&#58; integer; e&#58; integer&#41;&#58; boolean;BEGIN     IF      &#40;&#40;e=1&#41;OR&#40;e=0&#41;&#41; AND &#40;&#40;msg=144&#41;OR&#40;msg=128&#41;&#41; THEN BEGIN      result &#58;= true; END  // Notes ELSE IF &#40;&#40;e=2&#41;OR&#40;e=0&#41;&#41; AND &#40;msg=176&#41; THEN BEGIN      result &#58;= true; END  //CtrlChg ELSE IF &#40;&#40;e=3&#41;OR&#40;e=0&#41;&#41; AND &#40;msg=192&#41; THEN BEGIN      result &#58;= true; END  //PrgrChg ELSE IF &#40;&#40;e=4&#41;OR&#40;e=0&#41;&#41; AND &#40;msg=224&#41; THEN BEGIN      result &#58;= true; END  //PitchBend ELSE IF &#40;&#40;e=5&#41;OR&#40;e=0&#41;&#41; AND &#40;&#40;msg=208&#41; OR &#40;msg=160&#41;&#41; THEN BEGIN      result &#58;= true; END  //Aftertouch &#40;Channel, Poly&#41; ELSE BEGIN     result&#58;=false; END;END;// <F> setWrap&#58; wrap or limit byte range  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// FUNCTION setWrap &#40;t&#58; integer; wrap&#58; boolean&#41;&#58; integer;   // 777777 rename 'setWrap' BEGIN  IF t < 0 THEN BEGIN t&#58;=t*&#40;-1&#41;; END; IF t > 127 THEN BEGIN        IF isWrap THEN BEGIN          result &#58;= round&#40;&#40;t+1&#41; MOD 128&#41;; // TEST      END      ELSE BEGIN          result&#58;= 127;      END;   END ELSE IF t < 0 THEN BEGIN  /// ADD for transpose! END  ELSE BEGIN      result&#58;=t;  END;  END;// &#58; setTransp&#58; //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// FUNCTION setTransp&#40;val&#58; integer; trsp&#58; integer; wrap&#58; boolean&#41;&#58;integer;BEGIN    val&#58;=val+trsp;    IF &#40;&#40;val>127&#41;OR&#40;val<0&#41;&#41; THEN BEGIN         IF isWrap THEN BEGIN            IF val>127 THEN BEGIN                 result&#58;=val-127;             END            ELSE BEGIN                 result&#58;=val+127;            END;        END        ELSE BEGIN             IF val>127 THEN BEGIN                result&#58;=127;             END            ELSE BEGIN // val<0                result&#58;=0;            END;        END;    END    ELSE BEGIN         result&#58;=0;     END;END;// <F> calcLimited&#58; returns multiplication value for limiting, or return 1 &#40;x*1=x; x>0&#41;//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// FUNCTION calcLimited &#40;val&#58;integer; lo&#58;integer; hi&#58;integer; mode&#58;integer&#41;&#58;double; BEGIN    IF mode=0 THEN BEGIN result&#58;=1 END        //IF &#40;val<=hi&#41;AND&#40;val>=lo&#41;     ELSE IF mode=1 THEN BEGIN         result&#58;= &#40;hi-lo&#41;/128;          //result&#58;= &#40;lo + round&#40;val*r&#41; - 1&#41;;           END    ELSE IF mode = 2 THEN BEGIN          // compress    END    ELSE BEGIN         result&#58;=1     END;END; // <F> isStep&#58; step limit data&#58; filter out &#40;? or compress->max, or compress->min&#41;//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// FUNCTION isStep&#40;val&#58; integer; stp&#58; integer&#41;&#58;boolean;BEGIN    IF &#40;&#40;val+1&#41; MOD stp=0&#41; THEN BEGIN        result&#58;=true;    END    ELSE BEGIN        result&#58;=false;    END;END;// <F> convert//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// // setConvert&#58; &#40;why not convert to&#58; clock , start, stop, cont?&#41;FUNCTION setConvert&#40;srcMsg&#58;byte;typeId&#58;integer&#41;&#58;byte;BEGIN&#40;*IF = notes&#58; Note Legato","Note Poly &#40;mode1&#41;","Note Poly &#40;mode2&#41; 1-3; CC = 4generate events! if replace with current, loose data...Legato&#58;         if new event arrives, last event is closed&#58;         if not first event generate noteOff for the previous event        structures&#58; noteConvertTmpMidi&#58;= tmp // just before FOR loop ends.Mode1&#58;  if new event arrives, add_output noteOFF for oldest even noteOn,         or if it is the only note present. remove closed note from array        structures&#58; event array&#58; boolean&#91;chn&#93;&#91;note&#93; for currently open notes  //        ..already got this?Mode2&#58;  if new event arrives, add_output noteOFF for oldest odd noteOn,         or if it there are only even notes. remove closed note from array        -> even notes will endure until all odd notes are finished*&#41;    IF typeId=4 THEN BEGIN        result&#58;=176; // CC    END    ELSE IF typeId=14 THEN BEGIN        result&#58;=144; // leg play&#58; send noteOff Value if next noteOn value arrives tmp.Msg var holding last value    END         ELSE IF typeId=5 THEN BEGIN        result&#58;=192; // PC &#40;no 2nd byte&#41;    END    ELSE IF typeId=6 THEN BEGIN         result&#58;=224; // PitchBend &#40;Modwheel&#41;    END    ELSE IF typeId=7 THEN BEGIN        result&#58;=208; // Aftert Channel    END    ELSE IF typeId=8 THEN BEGIN        result&#58;=160; // Aftert Poly    END    ELSE BEGIN        result&#58;=srcMsg;    END; END;&#40;*// <F>getOpenNotes//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^//FUNCTION getOpenNotes&#40;&#41;&#58;integer;// global variables!!BEGIN           //boolNotesArray&#91;&#93;&#91;&#93;    END; //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^//// <P> writeNoteOff&#58; for convert to Notes//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^//PROCEDURE writeNoteOff;// global variables!!VAR extra&#58; TMidi;BEGIN      extra.msg&#58;=byte&#40;128&#41;;     extra.data1&#58;=tmp.data1;     extra.data2&#58;=0;     extra.channel&#58;=tmp.channel;     // write out     //setLength&#40;pOut&#41;&#58;= getLength&#40;pOut&#41;+1;     // ?? TEST!! ?? setMidiArrayData&#40;pOut,trunc&#40;getLength&#40;pOut&#41;&#41;-1&#41;,extraMidi&#41;     // remove from array     //NotesArray&#91;aVal&#93;&#58;= false;     //countNotes&#40;false&#41;; END; *&#41;// <P> countNotes&#58;  PROCEDURE countNotes&#40;isANoteAndON&#58;boolean&#41;;//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^//BEGIN       IF isANoteAndON THEN BEGIN         notesCount&#58;=notesCount+1             END    ELSE BEGIN        notesCount&#58;=notesCount-1;       END;       END;// <P> initLimitRange&#58; expect&#58; limitHi and limitLo are getValue&#40;p&#41; //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// PROCEDURE initLimitRange;BEGIN       IF limitHi-limitLo< 0 THEN BEGIN            tmpLimitLo&#58;=limitLo;          limitLo&#58;=limitHi;          limitHi&#58;=tmpLimitLo       END      ELSE IF limitHi-limitLo=0 THEN BEGIN          IF limitHi=128 THEN BEGIN               limitLo&#58;=127;           END          ELSE BEGIN              limitHi&#58;=limitHi+1;          END;      END; END; // <P> setDataSymbols&#58; //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// PROCEDURE setDataSymbols;VAR tr&#58; integer;BEGIN                    IF &#40;trunc&#40;getValue&#40;pStep&#41;&#41;<= 1&#41; THEN BEGIN         setSymbol&#40;pStep,''&#41;;setFormat&#40;pStep,'-bypass-'&#41;;     END     ELSE BEGIN          setSymbol&#40;pStep,'%'&#41;; setFormat&#40;pStep,'%.0f'&#41;    END;         tr&#58;=trunc&#40;getValue&#40;pTransp&#41;&#41;;    IF tr>0 THEN BEGIN         setSymbol&#40;pTransp,'+'&#41;; setFormat&#40;pTransp,'%.0f'&#41;;      END    ELSE IF  &#40;tr=&#40;-128&#41;&#41;OR&#40;tr=0&#41; THEN BEGIN         setSymbol&#40;pTransp,''&#41;; setFormat&#40;pTransp,'-bypass-'&#41;;     END    ELSE BEGIN          setSymbol&#40;pTransp,''&#41;;setFormat&#40;pTransp,'%.0f'&#41;;      END; &#40;*       IF trunc&#40;getValue&#40;pLimitHi&#41;&#41; = 127 THEN BEGIN         setColor&#40;pLimitHi,81099&#41;;    END     ELSE BEGIN         setColor&#40;pLimitHi,90099&#41;;    END;     IF trunc&#40;getValue&#40;pLimitLo&#41;&#41; = 0 THEN BEGIN              setOffColor&#40;pLimitLo,90099&#41;;    END     ELSE BEGIN        // setColor&#40;pLimitLo,90099&#41;;    END;    *&#41;    END;//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^|   //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^|    // main  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|     //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^|       //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^|BEGIN         len &#58;= getLength&#40;pIn&#41;;   lenCount&#58;= len;       IF len > 0 THEN BEGIN              multiply&#58;=pMultAr&#91;trunc&#40;getValue&#40;pMult&#41;&#41;&#93;;      transpose&#58;= trunc&#40;getValue&#40;pTransp&#41;&#41;;       IF &#40;transpose=&#40;-128&#41;&#41; THEN BEGIN // control&#58; bypass at the left end for convenience          transpose&#58;=0;       END;      tmpEvent&#58;=trunc&#40;getValue&#40;pEvent&#41;&#41;;      tmpDest&#58;=trunc&#40;getValue&#40;pDest&#41;&#41;;      isFirstByte&#58;=&#40;tmpDest=2&#41;OR&#40;tmpDest=0&#41;;      isSecondByte&#58;=&#40;tmpDest=2&#41;OR&#40;tmpDest=1&#41;;      limitLo&#58;=trunc&#40;getValue&#40;pLimitLo&#41;&#41;;      limitHi&#58;=trunc&#40;getValue&#40;pLimitHi&#41;&#41;;      limit&#58;=trunc&#40;getValue&#40;pLimit&#41;&#41;;      isLimit&#58;=&#40;limit>0&#41; AND &#40;&#40;limitLo>=1&#41;AND&#40;limitHi<=126&#41;&#41;;      initLimitRange&#40;&#41;;      convert&#58;=trunc&#40;getValue&#40;pConv&#41;&#41;;      step&#58;=trunc&#40;getValue&#40;pStep&#41;&#41;;      isStepActive&#58;=step>1;        isInv1&#58;=getValue&#40;pInv1&#41;>0;       isInv2&#58;=getValue&#40;pInv2&#41;>0;         isSwap&#58;=getValue&#40;pSwap&#41;>0;         isWrap&#58;=trunc&#40;getValue&#40;pWrap&#41;&#41;>0;      isThru&#58;=trunc&#40;getValue&#40;pThru&#41;&#41;>0;      FOR i &#58;= 0 TO &#40;len - 1&#41; DO BEGIN          getMidiArrayValue&#40;pIn, i, tmp&#41;;           IF isMidiMsg&#40;tmp.msg, tmpEvent&#41; THEN BEGIN  // process on IF. if pThru is 1, process on ELSE             tmpMsg &#58;=tmp.msg;             tmpX &#58;= tmp.data1;             tmpY &#58;= tmp.data2;               tmpXX &#58;= tmpX; // store global for note off array                IF isInv1 THEN BEGIN tmpX&#58;= 127 - tmpX;END;             IF isInv2 THEN BEGIN tmpY&#58;= 127 - tmpY;END;                           IF isSwap THEN BEGIN                    tmpX &#58;= tmpY;                     tmpY &#58;= tmpXX;              END;                            // affect byte 1              IF isFirstByte THEN BEGIN   // 1st byte&#58; process 1st+2nd byte if tmpDest=2                          tmpX &#58;= trunc&#40;multiply*tmpX&#41; + &#40;transpose&#41;;                 tmpX &#58;= setWrap&#40;tmpX, isWrap&#41;;                 IF isLimit THEN BEGIN                     tmpX &#58;= trunc&#40;tmpX * calcLimited&#40;tmpX,limitLo,limitHi,limit&#41;&#41;;                 END;                 tmp.data1 &#58;= byte&#40;tmpX&#41;;                             END;              // affect byte 2              IF isSecondByte THEN BEGIN    // 2nd byte&#58; process 1st+2nd byte if tmpDest=2                   tmpY &#58;= trunc&#40;multiply*tmpY&#41; + &#40;transpose&#41;;                 tmpY &#58;= setWrap&#40;tmpY, isWrap&#41;;                 IF isLimit THEN BEGIN                      tmpY &#58;= trunc&#40;tmpY * calcLimited&#40;tmpY,limitLo,limitHi,limit&#41;&#41;;                 END;                 tmp.data2 &#58;= byte&#40;tmpY&#41;;                       END;                 // affect msg&#58; convert event             IF isConvert THEN BEGIN                   tmp.msg &#58;= setConvert&#40;tmp.msg,convert&#41;;             END;             isNoteOff&#58;= &#40;tmpMsg=128&#41; OR &#40;&#40;tmpMsg=144&#41;AND&#40;tmpY=0&#41;&#41;;             isNoteOn &#58;= &#40;isNoteOff=false&#41;AND&#40;&#40;tmpMsg=144&#41;AND&#40;tmpY>0&#41;&#41;;                    // only when Notes are output                 // prevent hanging notes &#40;tmpXX for swapped note values&#41;; ! if convert=>Notes&#58;              IF isNoteOn THEN BEGIN                  mult&#91;tmp.channel - 1&#93;&#91;tmpXX&#93; &#58;= tmp.data1;  // tmpXX&#40;old 1st byte&#41; needed for noteOff value                   IF notesList&#91;tmp.channel - 1&#93;&#91;tmpXX&#93;=false THEN BEGIN                     notesList&#91;tmp.channel - 1&#93;&#91;tmpXX&#93;&#58;= true;                                      END;                  //IF &#40;&#40;convert<=3&#41;AND&#40;convert>0&#41;&#41; THEN BEGIN                  //addToBoolNotes&#40;tmp.data1, tmp.channel, tmpXX&#41;;                 // END                 //ELSE BEGIN                                       //END;                               END             ELSE IF isNoteOff THEN BEGIN //  ! if convert=>Notes&#58;                 tmp.data1 &#58;= mult&#91;tmp.channel - 1&#93;&#91;tmpXX&#93;; // set NoteOff value from original NoteOn value                 IF notesList&#91;tmp.channel - 1&#93;&#91;tmpXX&#93;=true THEN BEGIN                     notesList&#91;tmp.channel - 1&#93;&#91;tmpXX&#93;&#58;=false;                                      END;              END;                      IF  isFirstByte OR &#40;isFirstByte AND isSecondByte&#41; THEN BEGIN                filterByte&#58;= tmpX;           END //&#40;tempDest=1&#41;           ELSE BEGIN                filterByte&#58;= tmpY;           END;           IF &#40;&#40;limit=1&#41; AND &#40;&#40;limitLo>filterByte&#41; OR &#40;limitHi<filterByte&#41;&#41;&#41; OR              &#40;isStepActive AND&#40;isStep&#40;filterByte,step&#41;=true&#41;&#41;           THEN BEGIN  // filter message                lenCount&#58;=lenCount-1;           END            ELSE BEGIN                IF isNoteOn THEN BEGIN                    countNotes&#40;true&#41;;                END               ELSE IF isNoteOff THEN BEGIN                    countNotes&#40;false&#41;;               END;                      setLength&#40;pOut,lenCount&#41;;                setMidiArrayValue&#40;pOut, i, tmp&#41;;  // write modified message           END;           END              // ! isMidiMsg&#40;&#41;           ELSE BEGIN                  IF isThru THEN BEGIN                       setMidiArrayValue&#40;pOut, i, tmp&#41;;                   END                 ELSE BEGIN                      setLength&#40;pOut, 0&#41;;                  END;            END;         END;  // &#40;FOR i &#58;= 0 ..           END    ELSE BEGIN       setLength&#40;pOut, 0&#41;;    END; // len = 0 setValue&#40;pNotesCount, notesCount&#41;;setDataSymbols&#40;&#41;;END.

Statistics: Posted by amiga909 — 04 Nov 2008, 08:47


]]>
BrainModular BrainModular Users Forum 2008-11-12T16:35:10+02:00 https://brainmodular.com/forums/app.php/feed/topic/1127 2008-11-12T16:35:10+02:00 2008-11-12T16:35:10+02:00 https://brainmodular.com/forums/viewtopic.php?t=1127&p=6219#p6219 <![CDATA[compile problem with midi script]]> changes:
- almost all algos replaced
- convert CC or PC to Notes
- removed functionality: compress note, convert midi message to notes (polyphonic)
- more demos: noteLegato.mp3 , noteLegato.stepMod.mp3 (LFO->+createMidi->MEP.script->T-Pulse VSTii)

CODE:

&#40;* no compress, no multinoteConvertMEP 0.95 by amiga909// 2008-10-29&#58; first version// 2008-11-12&#58; release version// credits to&#58; bSork, senso &#40;www.sensomusic.com/forums&#41;// <Description> midi tool roughly inspired by Yamaha MEP-4 Midi Event Processor.     MEP was designed for experimental purposes but it can be also used as a midi utility.     download the original MEP-4 manual here&#58;     http&#58;//www2.yamaha.co.jp/manual/pdf/emi/english/synth/MEP4E.PDF // <Features> prevent hanging notes, swap data bytes, convert to notes, ..// <Processing chain>     <input>    ->    select     ->                        // filter input &#40;if midi thru on&#58; pass filtered data&#41;      swapBytes  -> inverse   ->           // modify input bytes    expand     -> transpose ->           // calculate input bytes    wrap       -> step&#40;x%y&#41; -> limit ->  // limit/rescale input bytes     affectByte ->                        // modify output bytes    convert    ->                        // change output type    <output>   <-// <Parameters> // select event &#58; select an event type for processing &#40;if event type is NoteOn+Off and                   convert is not bypassed, NoteOff messages are filtered in some cases&#41;.  // mute         &#58; filter selected event.  // midi thru    &#58; output all other event types. // affect byte  &#58; process first or second data byte or both. if only one                   byte is selected, then the other byte is output unprocessed.// inv. byte1/2 &#58; inverse incoming data byte. high value -> low, low -> high.// swap bytes   &#58; swap first and second byte &#40;eg. convert velocity to noteOn&#41;.// expand       &#58; choose a multiplication factor from 0.0625 to 16.// transpose    &#58; add or subtract value.// wrap around  &#58; if a value as a result of expanding or transposing is not between 1 and 128,                   and if wrap around is off&#58; result is 128 or 1,                   if wrap around is on&#58; &#40;1-1=128;128+1=1;&#41;.// step         &#58; only messages with a data byte that is a multiple of the Step                   will be allowed through.// limit low/hi &#58; specify the output data range.                  use a range fader &#40;interface design&#41; for control.  // limit mode   &#58; limit hard limits the output and filters values out of range,                   scale rescales to desired range.// convert      &#58; transform input event to another midi message.                   &#40;mode 1&#58; convert to notes&#58; even events are noteOns, odd events are noteOffs                  hanging notes; in contrary NoteOff! or NoteOn! create invalid midi notes&#41;.    // <Notes>   - Aftertouch, PC and other messages are not tested as much as Notes and CC   - compress is very beta. maybe it will be removed... &#40;not original MEP anyway&#41;   - the interface will maybe be reworked. there is the idea to have 8 toggle buttons that can each hold     an operation parameter &#40;à la instajungle&#41;.*&#41;VAR  pIn, pOut, pMult, pEvent, pDest, pWrap, pInv1, pInv2, pTransp, pBypass,      pNotesCount, pThru, pConv, pStep, pLimitHi, pLimitLo, pLimit, pSwap    &#58; TParameter;TYPE TMult    = ARRAY OF integer;VAR  mult     &#58; ARRAY OF TMult;VAR  pMultAr  &#58; ARRAY OF double;  VAR  tmp      &#58; TMidi;   VAR  multiply &#58; double;   VAR  len,i,tmpX,tmpY,tmpXX,tmpYY,tmpMsg,dest,transpose,limit,convert,event,step,convCnt,     limitLo,limitHi,tmpLimitLo, notesCount,filterByte,lenCount,lastConvNoteOn&#58; integer; VAR  isSwap, isWrap, isInv1, isInv2, isLimit, isConvNoteOff,       isFirstByte, isSecondByte, isConvert, isConvertToNotes      &#58; boolean;CONST NOTE_ON     = 144;CONST NOTE_OFF    = 128;CONST CONTROL_CHG = 176;CONST PROGRAM_CHG = 192;CONST PITCHBEND   = 224;CONST AFTER_MONO  = 208;CONST AFTER_POLY  = 160;CONST MIDI_CLOCK  = 248;CONST MIDI_START  = 250;CONST MIDI_CONT   = 251;CONST MIDI_STOP   = 252;CONST ACTIVE_SENS = 254;//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^//           //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// PROCEDURE Init;//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// VAR f_c1,f_c2&#58; integer; BEGIN pIn &#58;= createParam&#40;'midi in', ptMidi&#41;;  pOut &#58;= createParam&#40;'midi out', ptMidi&#41;; pEvent &#58;= createParam&#40;'select', ptListBox&#41;;   setListBoxString&#40;pEvent,  '"ALL","Note On+Off", "Control Change", "Program Change", "Pitch Bend", "Aftertouch"'&#41;;         pInv1 &#58;= createParam&#40;'inverse byte1', ptSwitch&#41;;      pInv2 &#58;= createParam&#40;'inverse byte2', ptSwitch&#41;;     pSwap &#58;= createParam&#40;'swap bytes', ptSwitch&#41;; pMult &#58;= createParam&#40;'expand', ptListBox&#41;;   setListBoxString&#40;pMult,  '        "-bypass-", "1/16",  "1/8", "1/4", "1/2","1","2","4","8","16"'&#41;;  pMultAr&#58;=&#91;1,          0.0625, 0.125,  0.25,  0.5,  1,  2,  4,  8,  16&#93;;       pTransp &#58;= createParam&#40;'transpose',ptDataFader&#41;;setMin&#40;pTransp,-128&#41;;setMax&#40;pTransp,127&#41;;  setSymbol&#40;pTransp, ''&#41;;setFormat&#40;pTransp,'-bypass-'&#41;;  pWrap &#58;= createParam&#40;'wrap around', ptSwitch&#41;;  pStep &#58;= createParam&#40;'step modulo', ptDataFader&#41;;setMin&#40;pStep,1&#41;;setMax&#40;pStep, 16&#41;;   setSymbol&#40;pStep,''&#41;;setFormat&#40;pStep,'-bypass-'&#41;; pLimitLo &#58;= createParam&#40;'lo limit', ptMidiNoteFader&#41;; setMax&#40;pLimitLo, 126&#41;; setMin&#40;pLimitLo, 0&#41;;    pLimitHi &#58;= createParam&#40;'hi limit', ptMidiNoteFader&#41;; setMin&#40;pLimitHi, 1&#41;;setMax&#40;pLimitHi, 127&#41;;   pLimit &#58;= createParam&#40;'limit mode', ptListBox&#41;;   setListBoxString&#40;pLimit,'"-bypass-","filter","rescale","compress"'&#41;;// if compress&#58; faders = ratio, threshold  setValue&#40;pLimit,1&#41;; setDefaultValue&#40;pLimit,0&#41;;pDest &#58;= createParam&#40;'affect', ptListBox&#41;;   setListBoxString&#40;pDest,'"1st byte &#40;note,cc.num,..&#41;", "2nd byte &#40;velo,cc.val,..&#41;", "1st and 2nd byte"'&#41;;    pConv &#58;= createParam&#40;'convert', ptListBox&#41;; // take all from 'Create Midi?'  setListBoxString&#40;pConv,  '"-bypass-","Note Legato","Note Poly &#40;mode1&#41;","Note Poly &#40;mode2&#41;","Note Poly &#40;random&#41;",'+  '"Control Change","Program Change", "Pitch Bend","Aftertouch Channel","Aftertouch Poly",'+  '"Timing Clock","Start","Stop","Continue","Active Sensing", "NoteOn !","NoteOff !"'&#41;;pThru &#58;= createParam&#40;'midi thru', ptSwitch&#41;; pBypass &#58;= createParam&#40;'mute', ptSwitch&#41;; pNotesCount &#58;= createParam&#40;'open notes', ptDataField&#41;; setReadOnly&#40;pNotesCount,true&#41;;  setMin&#40;pNotesCount,0&#41;;setMax&#40;pNotesCount,999&#41;;f_c1&#58;= 90099;f_c2&#58;= 60099; setColor&#40;pLimitHi,f_c1&#41;;setColor&#40;pLimitLo,f_c1&#41;;setColor&#40;pTransp,f_c1&#41;;setColor&#40;pThru,f_c2&#41;;setColor&#40;pStep,f_c1&#41;;setColor&#40;pWrap,f_c2&#41;;setColor&#40;pInv1,f_c2&#41;;setColor&#40;pInv2,f_c2&#41;;setColor&#40;pSwap,f_c2&#41;;setIsInput&#40;pOut,false&#41;;setIsInput&#40;pNotesCount,false&#41;;setIsOutput&#40;pIn,false&#41;;setIsOutput&#40;pEvent,false&#41;;setIsOutput&#40;pThru,false&#41;;setIsOutput&#40;pDest,false&#41;;setIsOutput&#40;pInv1,false&#41;;setIsOutput&#40;pInv2,false&#41;;setIsOutput&#40;pSwap,false&#41;;setIsOutput&#40;pMult,false&#41;; setIsOutput&#40;pTransp,false&#41;; setIsOutput&#40;pStep,false&#41;; setIsOutput&#40;pWrap,false&#41;;setIsOutput&#40;pLimit,false&#41;;setIsOutput&#40;pLimitLo,false&#41;;setIsOutput&#40;pLimitHi,false&#41;;setIsOutput&#40;pConv,false&#41;; setIsOutput&#40;pBypass,false&#41;; setValue&#40;pEvent,1&#41;;  setValue&#40;pDest,0&#41;; setValue&#40;pInv1,0&#41;;setValue&#40;pInv2,0&#41;;setValue&#40;pMult,GetLength&#40;pMult&#41;-1&#41;;setDefaultValue&#40;pMult,0&#41;;setValue&#40;pTransp,-128&#41;;setValue&#40;pStep,1&#41;;   setValue&#40;pWrap,0&#41;;setValue&#40;pLimitLo,0&#41;;setValue&#40;pLimitHi,127&#41;; setValue&#40;pLimit,0&#41;;setValue&#40;pConv,0&#41;;// array initsetArrayLength&#40;mult, 16&#41;;       FOR i &#58;= 0 TO 15 DO BEGIN         setArrayLength&#40;mult&#91;i&#93;, 128&#41;; // init &#91;16 channels&#93;&#91;128 multiply values&#93;   END;notesCount&#58;=0;convCnt&#58;=0;END; //^^^^^^^^^^^^^^^^^^^^^^^<F>^^^^^^^^^^^^^^^^^^^^^//// <F> isMidiMsg&#58; 'event' is a list of pEvent &#40;0=ALL&#41;//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// FUNCTION isMidiMsg&#40;msg&#58; integer; e&#58; integer&#41;&#58; boolean;BEGIN    IF      &#40;&#40;e=1&#41;OR&#40;e=0&#41;&#41; AND &#40;&#40;msg=NOTE_ON&#41;OR&#40;msg=NOTE_OFF&#41;&#41; THEN BEGIN      result &#58;= true; END  // Notes ELSE IF &#40;&#40;e=2&#41;OR&#40;e=0&#41;&#41; AND &#40;msg=CONTROL_CHG&#41; THEN BEGIN      result &#58;= true; END  //CtrlChg ELSE IF &#40;&#40;e=3&#41;OR&#40;e=0&#41;&#41; AND &#40;msg=PROGRAM_CHG&#41; THEN BEGIN     result &#58;= true; END  //PrgrChg ELSE IF &#40;&#40;e=4&#41;OR&#40;e=0&#41;&#41; AND &#40;msg=PITCHBEND&#41; THEN BEGIN      result &#58;= true; END  //PitchBend ELSE IF &#40;&#40;e=5&#41;OR&#40;e=0&#41;&#41; AND &#40;&#40;msg=AFTER_MONO&#41; OR &#40;msg=AFTER_POLY&#41;&#41; THEN BEGIN      result &#58;= true; END  //Aftertouch &#40;Channel, Poly&#41; ELSE BEGIN     result&#58;=false; END; END;// <F> isStep&#58; step limit data&#58; filter out &#40;? or compress->max, or compress->min&#41;//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// FUNCTION isStep&#40;val&#58; integer; stp&#58; integer&#41;&#58; boolean;BEGIN    IF NOT&#40;&#40;val+1&#41; MOD stp=0&#41; THEN BEGIN        result&#58;=true;    END    ELSE BEGIN        result&#58;=false;    END;END;// <F> isNoteOn&#58;  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// FUNCTION isNoteOn&#40;message&#58; byte;velocity&#58; byte&#41;&#58; boolean;BEGIN     IF &#40;message=NOTE_ON&#41;AND&#40;velocity>0&#41; THEN BEGIN         result&#58;=true;    END    ELSE BEGIN         result&#58;=false;     END;END;// <F> isNoteOff&#58;  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// FUNCTION isNoteOff&#40;message&#58; byte;velocity&#58; byte&#41;&#58; boolean;BEGIN      IF &#40;message=NOTE_OFF&#41;OR&#40;&#40;message=NOTE_ON&#41;AND&#40;velocity=0&#41;&#41; THEN BEGIN         result&#58;=true;    END    ELSE BEGIN         result&#58;=false;    END;END;// <F> setWrap&#58; wrap or limit byte range  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// FUNCTION setWrap &#40;t&#58; integer; wrap&#58; boolean&#41;&#58; integer;   // 777777 rename 'setWrap' BEGIN  IF isWrap THEN BEGIN     IF t<0 THEN BEGIN         result&#58;= 128 - &#40;&#40;t*-1&#41; MOD 128&#41;;             END     ELSE IF t>127 THEN BEGIN         result &#58;= t MOD 128;      END    ELSE BEGIN         result&#58;=t;    END; END ELSE BEGIN     IF t<0 THEN BEGIN         result&#58;=0;    END     ELSE IF t>127 THEN BEGIN         result&#58;=127;    END    ELSE BEGIN         result&#58;=t;    END; END;END;// &#58; setTransp&#58; //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// FUNCTION setTransp&#40;val&#58; integer; trsp&#58; integer; wrap&#58; boolean&#41;&#58;integer;BEGIN    val&#58;=val+trsp;    IF &#40;&#40;val>127&#41;OR&#40;val<0&#41;&#41; THEN BEGIN         IF isWrap THEN BEGIN            IF val>127 THEN BEGIN                 result&#58;=val-127;             END            ELSE BEGIN                 result&#58;=val+127;            END;        END        ELSE BEGIN             IF val>127 THEN BEGIN                result&#58;=127;             END            ELSE BEGIN // val<0                result&#58;=0;            END;        END;    END    ELSE BEGIN         result&#58;=0;     END;END;// <F> convert&#58;//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// // setConvert&#58; &#40;why not convert to&#58; clock , start, stop, cont?&#41;FUNCTION setConvert&#40;srcMsg&#58; byte;typeId&#58; integer&#41;&#58; byte;BEGINCASE typeId OF      0&#58; result&#58;=srcMsg; // bypass      1&#58; result&#58;=NOTE_ON; // NotesLegato      2&#58; result&#58;=NOTE_ON; // NotesPoly1      3&#58; result&#58;=NOTE_ON; // NotesPoly2      4&#58; result&#58;=NOTE_ON; // NotesPoly rnd      5&#58; result&#58;=CONTROL_CHG;        6&#58; result&#58;=PROGRAM_CHG;       7&#58; result&#58;=PITCHBEND; //&#40;Modwheel&#41;      8&#58; result&#58;=AFTER_MONO; // Aftert Channel      9&#58; result&#58;=AFTER_POLY; // Aftert Poly     10&#58; result&#58;=MIDI_CLOCK;       11&#58; result&#58;=MIDI_START;       12&#58; result&#58;=MIDI_STOP;      13&#58; result&#58;=MIDI_CONT;       14&#58; result&#58;=ACTIVE_SENS;      15&#58; result&#58;=NOTE_ON; // NoteON ONLY!     16&#58; result&#58;=NOTE_OFF; // NoteOFF ONLY!   ELSE BEGIN      result&#58;=srcMsg;   END;END;END;// <F> calcLimited&#58; returns multiplication value for limiting, or return 1 &#40;x*1=x; x>0&#41;//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// FUNCTION calcLimited &#40;val&#58; integer;lo&#58; integer;hi&#58; integer;mode&#58; integer&#41;&#58; integer; VAR r  &#58; double;  BEGIN  //writeln&#40;'val&#58;'+inttostr&#40;val&#41;&#41;    IF mode<=1 THEN BEGIN  // filter, bypass, not used here        result&#58;=val;     END      ELSE IF mode=2 THEN BEGIN // scale        r &#58;= 128/&#40;hi-lo&#41;;        val&#58;= trunc&#40;&#40;val+1&#41;/r&#41;;        result&#58;= val+lo;            END     ELSE BEGIN         result&#58;=val;     END;END;    //^^^^^^^^^^^^^^^^^^^^^^^<P>^^^^^^^^^^^^^^^^^^^^^//// <P> countNotes&#58;  PROCEDURE countNotes&#40;isANoteAndON&#58;boolean&#41;;//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^//BEGIN       IF isANoteAndON THEN BEGIN         notesCount&#58;=notesCount+1             END    ELSE BEGIN        notesCount&#58;=notesCount-1;       END;       END;// <P> convertToLegatoNotes&#58; isConvert AND isNoteOff=false &#40;dont process noteOff for eg. note->cc&#41;//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// PROCEDURE convertToLegatoNotes;BEGIN     IF  convCnt MOD 2 = 1  THEN BEGIN          tmp.data1&#58;=byte&#40;lastConvNoteOn&#41;;        tmp.msg&#58;=byte&#40;NOTE_OFF&#41;;     END    ELSE BEGIN         lastConvNoteOn&#58;=tmp.data1;        tmp.msg&#58;=byte&#40;NOTE_ON&#41;;      END;    convCnt&#58;=convCnt+1;     IF convCnt=1028 THEN BEGIN convCnt&#58;=0; END;END;// <P> initLimitRange&#58; expect&#58; limitHi and limitLo are getValue&#40;p&#41; //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// PROCEDURE initLimitRange;BEGIN  IF NOT&#40;limit=3&#41; THEN BEGIN  // if limit is compress&#58; thres/ratio fader functions      IF limitHi-limitLo< 0 THEN BEGIN            tmpLimitLo&#58;=limitLo;          limitLo&#58;=limitHi;          limitHi&#58;=tmpLimitLo       END      ELSE IF limitHi-limitLo=0 THEN BEGIN          IF limitHi=128 THEN BEGIN               limitLo&#58;=127;           END          ELSE BEGIN              limitHi&#58;=limitHi+1;          END;      END; END; END;                            // <P> setDataSymbols&#58; //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// PROCEDURE setDataSymbols;VAR tr&#58; integer;BEGIN                  IF &#40;trunc&#40;getValue&#40;pStep&#41;&#41;<= 1&#41; THEN BEGIN         setSymbol&#40;pStep,''&#41;;setFormat&#40;pStep,'-bypass-'&#41;;     END     ELSE BEGIN          setSymbol&#40;pStep,'%'&#41;; setFormat&#40;pStep,'%.0f'&#41;    END;         tr&#58;=trunc&#40;getValue&#40;pTransp&#41;&#41;;    IF tr>0 THEN BEGIN         setSymbol&#40;pTransp,'+'&#41;; setFormat&#40;pTransp,'%.0f'&#41;;      END    ELSE IF &#40;tr=&#40;-128&#41;&#41;OR&#40;tr=0&#41; THEN BEGIN         setSymbol&#40;pTransp,''&#41;; setFormat&#40;pTransp,'-bypass-'&#41;;     END    ELSE BEGIN          setSymbol&#40;pTransp,''&#41;;setFormat&#40;pTransp,'%.0f'&#41;;      END;    END;//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^|   //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^|    // main  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|     //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^|       //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^|BEGIN         len &#58;= getLength&#40;pIn&#41;;   lenCount&#58;= len;         IF len > 0 THEN BEGIN            multiply&#58;=pMultAr&#91;trunc&#40;getValue&#40;pMult&#41;&#41;&#93;;      transpose&#58;= trunc&#40;getValue&#40;pTransp&#41;&#41;;       IF &#40;transpose=&#40;-128&#41;&#41; THEN BEGIN // control&#58; bypass at the left end for convenience          transpose&#58;=0;       END;      event&#58;=trunc&#40;getValue&#40;pEvent&#41;&#41;;      dest&#58;=trunc&#40;getValue&#40;pDest&#41;&#41;;      isFirstByte&#58;=&#40;dest=2&#41;OR&#40;dest=0&#41;;       isSecondByte&#58;=&#40;dest=2&#41;OR&#40;dest=1&#41;;      limit&#58;=trunc&#40;getValue&#40;pLimit&#41;&#41;;      limitLo&#58;=trunc&#40;getValue&#40;pLimitLo&#41;&#41;;      limitHi&#58;=trunc&#40;getValue&#40;pLimitHi&#41;&#41;;            isLimit&#58;=&#40;limit>0&#41; AND &#40;&#40;limitLo>=1&#41;OR&#40;limitHi<=126&#41;&#41;;       initLimitRange&#40;&#41;;      convert&#58;=trunc&#40;getValue&#40;pConv&#41;&#41;;       isConvert&#58;=convert>0;      isConvertToNotes&#58;=convert=1;      isConvNoteOff&#58;=false;       step&#58;=trunc&#40;getValue&#40;pStep&#41;&#41;;       isInv1&#58;=getValue&#40;pInv1&#41;>0;       isInv2&#58;=getValue&#40;pInv2&#41;>0;         isSwap&#58;=getValue&#40;pSwap&#41;>0;          isWrap&#58;=getValue&#40;pWrap&#41;>0;      FOR i &#58;= 0 TO &#40;len - 1&#41; DO BEGIN          getMidiArrayValue&#40;pIn, i, tmp&#41;;          IF  &#40;getValue&#40;pBypass&#41;=0&#41; AND &#40;isMidiMsg&#40;tmp.msg,event&#41;&#41; THEN BEGIN                tmpMsg&#58;= tmp.msg;             tmpX  &#58;= tmp.data1;             tmpY  &#58;= tmp.data2;               tmpXX &#58;= tmpX; // store orig. val for noteList             tmpYY &#58;= tmpY;             IF isInv1 THEN BEGIN                 tmpX&#58;= 127 - tmpX;             END;             IF isInv2 THEN BEGIN                   tmpY&#58;= 127 - tmpY;             END;                           IF isSwap THEN BEGIN                    tmpX &#58;= tmpY;                     tmpY &#58;= tmpXX;                END;                      // affect byte 1              IF isFirstByte THEN BEGIN    // 1st byte&#58; process 1st+2nd byte if dest=2                  tmpX &#58;= trunc&#40;multiply*tmpX&#41;;                 tmpX &#58;= tmpX + &#40;transpose&#41;;                 tmpX &#58;= setWrap&#40;tmpX, isWrap&#41;; // wrap or hard limit                  IF isLimit THEN BEGIN                     tmpX &#58;= calcLimited&#40;tmpX,limitLo,limitHi,limit&#41;;                 END;                  tmp.data1 &#58;= byte&#40;tmpX&#41;;                END;              // affect byte 2              IF isSecondByte THEN BEGIN                    tmpY &#58;= trunc&#40;multiply*tmpY&#41;;                 tmpY &#58;= tmpY + &#40;transpose&#41;;                 tmpY &#58;= setWrap&#40;tmpY, isWrap&#41;; // wrap or hard limit                  IF isLimit THEN BEGIN                     tmpY &#58;= calcLimited&#40;tmpY,limitLo,limitHi,limit&#41;;                 END;                  tmp.data2 &#58;= byte&#40;tmpY&#41;;                       END;               // prevent hanging notes &#40;tmpXX for swapped note values&#41;             IF isNoteOn&#40;tmpMsg,tmpYY&#41; THEN BEGIN                     mult&#91;tmp.channel - 1&#93;&#91;tmpXX&#93; &#58;= tmp.data1;  // tmpXX&#40;old 1st byte&#41; needed for noteOff value                           END             ELSE IF &#40;&#40;isConvertToNotes=false&#41; AND &#40;isNoteOff&#40;tmpMsg,tmpYY&#41;=true&#41;&#41; THEN BEGIN //! if convert=>Notes&#58;                   tmp.data1 &#58;= mult&#91;tmp.channel - 1&#93;&#91;tmpXX&#93;; // set NoteOff value from original NoteOn value             END;             // affect msg&#58; convert event             IF isConvert THEN BEGIN                       IF isConvertToNotes THEN BEGIN                          convertToLegatoNotes&#40;&#41;;                      END                       ELSE BEGIN // isConvertToNotes=false                          IF isNoteOff&#40;tmpMsg,tmpYY&#41;=true THEN BEGIN                              isConvNoteOff&#58;=true;  // filter flag for output                         END                          ELSE BEGIN                              tmp.msg&#58;=setConvert&#40;tmpMsg, convert&#41;;                         END;                     END;                   END;             IF  isFirstByte OR &#40;isFirstByte AND isSecondByte&#41; THEN BEGIN                  filterByte&#58;= tmpX;             END               ELSE BEGIN                  filterByte&#58;= tmpY;             END;             IF  &#40;isConvNoteOff&#41; OR    // if convert to notes dont convert noteOff                 &#40;&#40;limit=1&#41;AND&#40;limitLo>filterByte&#41;&#41; OR &#40;limitHi<filterByte&#41;  OR                  &#40;step>1&#41;AND&#40;isStep&#40;filterByte,step&#41;&#41;   THEN BEGIN  // filter message                  lenCount&#58;=lenCount-1;             END              ELSE BEGIN                 IF isNoteOn&#40;tmp.msg,tmp.data2&#41; THEN BEGIN                    countNotes&#40;true&#41;;               END               ELSE IF isNoteOff&#40;tmp.msg,tmp.data2&#41; THEN BEGIN                    countNotes&#40;false&#41;;               END;                      setLength&#40;pOut,lenCount&#41;;                 setMidiArrayValue&#40;pOut, i, tmp&#41;;  // write modified message             END;              END                // ! isMidiMsg&#40;&#41;            ELSE BEGIN                  IF &#40;getValue&#40;pThru&#41;>0&#41; THEN BEGIN                       setMidiArrayValue&#40;pOut, i, tmp&#41;;                   END                 ELSE BEGIN                      setLength&#40;pOut, 0&#41;;                  END;            END;        END;  // &#40;FOR i &#58;= 0 ..           END    ELSE BEGIN       setLength&#40;pOut, 0&#41;;    END; // len = 0 setValue&#40;pNotesCount, notesCount&#41;;setDataSymbols&#40;&#41;;END.

Statistics: Posted by amiga909 — 12 Nov 2008, 15:35


]]>
2008-11-07T21:25:09+02:00 2008-11-07T21:25:09+02:00 https://brainmodular.com/forums/viewtopic.php?t=1127&p=6150#p6150 <![CDATA[compile problem with midi script]]> the idea is to have a midi effect patch for live use. using midi effects live isnt exactly popular though.

trying it with vsti's bSorks noteoff solution works great, here from a first try.
http://thaumat.org/_permShare/mp3/mep.draft.t1.mp3
used: a piano roll with a drum pattern, ephonic drumatic , tpmusic t-pulse, and 2x mep script for each plugin.

Statistics: Posted by amiga909 — 07 Nov 2008, 20:25


]]>
2008-11-04T23:52:33+02:00 2008-11-04T23:52:33+02:00 https://brainmodular.com/forums/viewtopic.php?t=1127&p=6109#p6109 <![CDATA[compile problem with midi script]]>

its not a MEP-4 emulation, btw. its an experimental midi tool to learn the script language,
the only thing it has in common are most parameters and some of their ranges.
i try to avoid the hanging notes problem which the MEP-4 does not. on the other hand the MEP features channel filter/routing, mid delay, data presetting or stuff regarding its 4 ins and outs. personally I like to deal with channel filtering before or after a midi effect, midi delay already exists as a script and if you'd need 4in/outs you can use 4 instances of the script.
do you think if something essential from the MEP-4 is missing in the script?

guess i'll post a running beta with all features implemented here. to finish this script it will take some more time..

Statistics: Posted by amiga909 — 04 Nov 2008, 22:52


]]>
2008-11-04T22:43:59+02:00 2008-11-04T22:43:59+02:00 https://brainmodular.com/forums/viewtopic.php?t=1127&p=6108#p6108 <![CDATA[compile problem with midi script]]> Statistics: Posted by bsork — 04 Nov 2008, 21:43


]]>
2008-11-04T22:29:57+02:00 2008-11-04T22:29:57+02:00 https://brainmodular.com/forums/viewtopic.php?t=1127&p=6107#p6107 <![CDATA[compile problem with midi script]]> will you post it as add-on?

Statistics: Posted by senso — 04 Nov 2008, 21:29


]]>
2008-11-04T21:10:27+02:00 2008-11-04T21:10:27+02:00 https://brainmodular.com/forums/viewtopic.php?t=1127&p=6106#p6106 <![CDATA[compile problem with midi script]]>
I used to have one of those yamaha boxes, it was awesome!

cheers!
-e

Statistics: Posted by woodslanding — 04 Nov 2008, 20:10


]]>
2008-11-04T16:55:48+02:00 2008-11-04T16:55:48+02:00 https://brainmodular.com/forums/viewtopic.php?t=1127&p=6097#p6097 <![CDATA[compile problem with midi script]]> great explanation too.


(* blabla *) multiline comment compiles here without any problems.

btw: tkx bsork, based on another post of you I have corrected the setLength(pOut, len) thing (output array will now get smaller when select input data is filtered)

Statistics: Posted by amiga909 — 04 Nov 2008, 15:55


]]>
2008-11-04T15:17:46+02:00 2008-11-04T15:17:46+02:00 https://brainmodular.com/forums/viewtopic.php?t=1127&p=6093#p6093 <![CDATA[compile problem with midi script]]>
replace

CODE:

setIsInput&#40;NotesCount,false&#41;;bysetIsInput&#40;pNotesCount,false&#41;;
it works
the parameter are in fact numbers which represent their ID
pIn = 0
pOut = 1
...
in the order of creation

for example

CODE:

setIsInput&#40;pIn,false&#41;;is totally equivalent to setIsInput&#40;0,false&#41;;

Statistics: Posted by senso — 04 Nov 2008, 14:17


]]>
2008-11-04T11:44:24+02:00 2008-11-04T11:44:24+02:00 https://brainmodular.com/forums/viewtopic.php?t=1127&p=6085#p6085 <![CDATA[compile problem with midi script]]> Statistics: Posted by bsork — 04 Nov 2008, 10:44


]]>
2008-11-04T09:47:07+02:00 2008-11-04T09:47:07+02:00 https://brainmodular.com/forums/viewtopic.php?t=1127&p=6081#p6081 <![CDATA[compile problem with midi script]]>
got a problem with this (unfinished) script here.

when I compile it the midi in input pin is not generated. (using v.4.01)

further I get some cpu lags and freezes but this could be caused by my shitty office computer.
and yes, I hope this script will have some practical use :)

thaumat.org/tmp/_transfer/MEP.0.037.script

CODE:

&#40;* MEP 0.037// 2008-11-29&#58; @amiga909// credits to&#58; bSork, senso &#40;www.sensomusic.com/forums&#41;// <Description>// MEP&#58; midi tool roughly inspired by Yamaha MEP-4 Midi Event Processor.      download the original MEP-4 manual here&#58;      http&#58;//www2.yamaha.co.jp/manual/pdf/emi/english/synth/MEP4E.PDF // Features&#58; prevent hanging notes, swap data bytes, convert to notes or system messages, ..// Processing chain&#58;     <input>    ->    select     ->                        // filter input &#40;if midi thru on&#58; pass filtered data&#41;      inverse    -> swapBytes ->           // modify input bytes    expand     -> transpose ->           // calculate input bytes    wrap       -> step&#40;x%y&#41; -> limit ->  // limit/rescale input bytes     affectByte ->                        // modify output bytes    convert    ->                        // change output type    <output>   <-// <Parameters> // select event &#58; select an event type for processing // midi thru    &#58; output all other event types.                    !&#123;sysex, clock and activesensing are always filtered&#125;// affect byte  &#58; process first or second data byte or both. if only one                   byte is selected, then the other byte is output unprocessed.// inv. byte1/2 &#58; inverse incoming data byte. high value -> low, low -> high.// swap bytes   &#58; swap first and second byte &#40;eg. convert velocity to noteOn&#41;.// expand       &#58; choose a multiplication factor between 0.0625 to 16// transpose    &#58; add or subtract value// wrap around  &#58; if a value as a result of expanding or transposing is not between 1 and 128,                   and if wrap around is off&#58; result is 128 or 1,                   if wrap around is on&#58; &#40;1-1=128;128+1=1;&#41;.// step         &#58; only messages with a data byte that is a multiple of the Step                   will be allowed through.// limit low/hi &#58; specify the output data range.                  use a range fader &#40;interface design&#41; for control.  // limit mode   &#58; limit hard limits the output and filters values out of range                   scale rescales to desired range&#58; value/128 => value/newRange // convert      &#58; transform input event to CC, PC, PitchBend or Aftertouch// <Notes>   Aftertouch, PC and other messages are not tested. *&#41;VAR pIn, pOut, pMult,  pEvent, pDest, pWrap,pThru, pSwap,  pInv1, pInv2, pTransp,  pNotesCount,    pStep,  pLimitHi, pLimitLo, pLimit, pConv &#58; TParameter;TYPE TMult = ARRAY OF integer;VAR mult &#58; ARRAY OF TMult;VAR pMultAr&#58; ARRAY OF double; TYPE TBool = ARRAY OF boolean; // convert -> notesVAR notesList&#58; ARRAY OF TBool;VAR tmp&#58; TMidi;   VAR multiply&#58; double;   VAR len, i, tmpX ,tmpY, tmpXX, tmpDest,tmpMsg, transpose, limit, convert, tmpEvent,limitLo, limitHi, tmpLimitLo, step, notesCount,filterByte,lenCount&#58; integer; VAR isNoteOff, isNoteOn, isSwap, isThru,isWrap, isStepActive, isInv1,isInv2,isConvert,isLimit,isFirstByte,isSecondByte&#58; boolean;//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^//           //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// PROCEDURE Init;//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// VAR f_c1,f_c2,f_c3&#58; integer;BEGINpIn &#58;= createParam&#40;'midi in', ptMidi&#41;;  pOut &#58;= createParam&#40;'midi out', ptMidi&#41;; pEvent &#58;= createParam&#40;'select', ptListBox&#41;;   setListBoxString&#40;pEvent,  '"ALL","Note On+Off", "Control Change", "Program Change", "Pitch Bend", "Aftertouch"'&#41;;         pInv1 &#58;= createParam&#40;'inverse byte1', ptSwitch&#41;;      pInv2 &#58;= createParam&#40;'inverse byte2', ptSwitch&#41;;     pSwap &#58;= createParam&#40;'swap bytes', ptSwitch&#41;; pMult &#58;= createParam&#40;'expand', ptListBox&#41;;   setListBoxString&#40;pMult,  '        "-bypass-", "1/16",  "1/8", "1/4", "1/2","1","2","4","8","16"'&#41;;  pMultAr&#58;=&#91;1,          0.0625, 0.125,  0.25,  0.5,  1,  2,  4,  8,  16&#93;;       pTransp &#58;= createParam&#40;'transpose',ptDataFader&#41;;setMin&#40;pTransp,-128&#41;;setMax&#40;pTransp,127&#41;;  setSymbol&#40;pTransp, ''&#41;;setFormat&#40;pTransp,'-bypass-'&#41;; pStep &#58;= createParam&#40;'step', ptDataFader&#41;;setMin&#40;pStep,1&#41;;setMax&#40;pStep, 16&#41;;   setSymbol&#40;pStep,''&#41;;setFormat&#40;pStep,'-bypass-'&#41;;  pWrap &#58;= createParam&#40;'wrap around', ptSwitch&#41;;  pLimitLo &#58;= createParam&#40;'lo limit', ptMidiNoteFader&#41;; setMax&#40;pLimitLo, 126&#41;; setMin&#40;pLimitLo, 0&#41;;    pLimitHi &#58;= createParam&#40;'hi limit', ptMidiNoteFader&#41;; setMin&#40;pLimitHi, 1&#41;;setMax&#40;pLimitHi, 127&#41;;   pLimit &#58;= createParam&#40;'limit mode', ptListBox&#41;;   setListBoxString&#40;pLimit,'"-bypass-","filter","rescale","compress"'&#41;;// if compress&#58; faders = ratio, threshold  setValue&#40;pLimit,1&#41;; setDefaultValue&#40;pLimit,0&#41;;pDest &#58;= createParam&#40;'affect byte', ptListBox&#41;;   setListBoxString&#40;pDest,'"1&#40;note,cc.num,..&#41;", "2&#40;velo,cc.val,..&#41;", "1 + 2"'&#41;;    pConv &#58;= createParam&#40;'convert', ptListBox&#41;; // take all from 'Create Midi?'  setListBoxString&#40;pConv,  '"-bypass-","Note Legato","Note Poly &#40;mode1&#41;","Note Poly &#40;mode2&#41;","Control Change","Program Change", "Pitch Bend","Aftertouch Channel","Aftertouch Poly", "Timing Clock","Start","Stop","Continue","Active Sensing", "NoteOn !","NoteOff !"'&#41;;pThru &#58;= createParam&#40;'midi thru', ptSwitch&#41;; pNotesCount &#58;= createParam&#40;'open notes', ptDataField&#41;; setReadOnly&#40;pNotesCount,true&#41;;  setMin&#40;pNotesCount,0&#41;;setMax&#40;pNotesCount,999&#41;;f_c1&#58;= 90099;f_c2&#58;= 60099;f_c3&#58;= 6666666; setColor&#40;pLimitHi,f_c1&#41;; setColor&#40;pLimitLo,f_c1&#41;;setColor&#40;pTransp,f_c1&#41;;setColor&#40;pStep,f_c1&#41;; setColor&#40;pWrap,f_c2&#41;;setColor&#40;pThru,f_c2&#41;;setColor&#40;pInv1,f_c2&#41;;setColor&#40;pInv2,f_c2&#41;;setColor&#40;pSwap,f_c2&#41;; //setColor&#40;pNotesCount,f_c3&#41;;setIsInput&#40;pOut,false&#41;;setIsInput&#40;NotesCount,false&#41;;setIsOutput&#40;pIn,false&#41;;setIsOutput&#40;pEvent,false&#41;;setIsOutput&#40;pThru,false&#41;;setIsOutput&#40;pDest,false&#41;;setIsOutput&#40;pInv1,false&#41;;setIsOutput&#40;pInv2,false&#41;;setIsOutput&#40;pSwap,false&#41;;setIsOutput&#40;pMult,false&#41;;//setIsOutput&#40;pMultSw,false&#41;;setIsOutput&#40;pTransp,false&#41;;//setIsOutput&#40;pTranspSw,false&#41;;setIsOutput&#40;pStep,false&#41;;//setIsOutput&#40;pStepSw,false&#41;;setIsOutput&#40;pWrap,false&#41;;setIsOutput&#40;pLimit,false&#41;;setIsOutput&#40;pLimitLo,false&#41;;setIsOutput&#40;pLimitHi,false&#41;;setIsOutput&#40;pConv,false&#41;; setValue&#40;pEvent,1&#41;;  setValue&#40;pDest,0&#41;; setValue&#40;pInv1,0&#41;;setValue&#40;pInv2,0&#41;;setValue&#40;pMult,GetLength&#40;pMult&#41;-1&#41;;setDefaultValue&#40;pMult,0&#41;;setValue&#40;pTransp,-128&#41;;setValue&#40;pStep,1&#41;;   setValue&#40;pWrap,0&#41;;setValue&#40;pLimitLo,0&#41;;setValue&#40;pLimitHi,127&#41;; setValue&#40;pLimit,0&#41;;setValue&#40;pConv,0&#41;;setArrayLength&#40;mult, 16&#41;;     setArrayLength&#40;notesList, 16&#41;;    FOR i &#58;= 0 TO 15 DO BEGIN         setArrayLength&#40;mult&#91;i&#93;, 128&#41;; // init &#91;16 channels&#93;&#91;128 multiply values&#93;      SetArrayLength&#40;notesList&#91;i&#93;, 128&#41;;    END;notesCount&#58;=0;END; // <F> isMidiMsg&#58; 'event' is a list of pEvent &#40;0=ALL&#41;. filters sysex, clock and system messages//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// FUNCTION isMidiMsg&#40;msg&#58; integer; e&#58; integer&#41;&#58; boolean;BEGIN     IF      &#40;&#40;e=1&#41;OR&#40;e=0&#41;&#41; AND &#40;&#40;msg=144&#41;OR&#40;msg=128&#41;&#41; THEN BEGIN      result &#58;= true; END  // Notes ELSE IF &#40;&#40;e=2&#41;OR&#40;e=0&#41;&#41; AND &#40;msg=176&#41; THEN BEGIN      result &#58;= true; END  //CtrlChg ELSE IF &#40;&#40;e=3&#41;OR&#40;e=0&#41;&#41; AND &#40;msg=192&#41; THEN BEGIN      result &#58;= true; END  //PrgrChg ELSE IF &#40;&#40;e=4&#41;OR&#40;e=0&#41;&#41; AND &#40;msg=224&#41; THEN BEGIN      result &#58;= true; END  //PitchBend ELSE IF &#40;&#40;e=5&#41;OR&#40;e=0&#41;&#41; AND &#40;&#40;msg=208&#41; OR &#40;msg=160&#41;&#41; THEN BEGIN      result &#58;= true; END  //Aftertouch &#40;Channel, Poly&#41; ELSE BEGIN     result&#58;=false; END;END;// <F> setWrap&#58; wrap or limit byte range  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// FUNCTION setWrap &#40;t&#58; integer; wrap&#58; boolean&#41;&#58; integer;   // 777777 rename 'setWrap' BEGIN  IF t < 0 THEN BEGIN t&#58;=t*&#40;-1&#41;; END; IF t > 127 THEN BEGIN        IF isWrap THEN BEGIN          result &#58;= round&#40;&#40;t+1&#41; MOD 128&#41;; // TEST      END      ELSE BEGIN          result&#58;= 127;      END;   END ELSE IF t < 0 THEN BEGIN  /// ADD for transpose! END  ELSE BEGIN      result&#58;=t;  END;  END;// &#58; setTransp&#58; //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// FUNCTION setTransp&#40;val&#58; integer; trsp&#58; integer; wrap&#58; boolean&#41;&#58;integer;BEGIN    val&#58;=val+trsp;    IF &#40;&#40;val>127&#41;OR&#40;val<0&#41;&#41; THEN BEGIN         IF isWrap THEN BEGIN            IF val>127 THEN BEGIN                 result&#58;=val-127;             END            ELSE BEGIN                 result&#58;=val+127;            END;        END        ELSE BEGIN             IF val>127 THEN BEGIN                result&#58;=127;             END            ELSE BEGIN // val<0                result&#58;=0;            END;        END;    END    ELSE BEGIN         result&#58;=0;     END;END;// <F> calcLimited&#58; returns multiplication value for limiting, or return 1 &#40;x*1=x; x>0&#41;//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// FUNCTION calcLimited &#40;val&#58;integer; lo&#58;integer; hi&#58;integer; mode&#58;integer&#41;&#58;double; BEGIN    IF mode=0 THEN BEGIN result&#58;=1 END        //IF &#40;val<=hi&#41;AND&#40;val>=lo&#41;     ELSE IF mode=1 THEN BEGIN         result&#58;= &#40;hi-lo&#41;/128;          //result&#58;= &#40;lo + round&#40;val*r&#41; - 1&#41;;           END    ELSE IF mode = 2 THEN BEGIN          // compress    END    ELSE BEGIN         result&#58;=1     END;END; // <F> isStep&#58; step limit data&#58; filter out &#40;? or compress->max, or compress->min&#41;//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// FUNCTION isStep&#40;val&#58; integer; stp&#58; integer&#41;&#58;boolean;BEGIN    IF &#40;&#40;val+1&#41; MOD stp=0&#41; THEN BEGIN        result&#58;=true;    END    ELSE BEGIN        result&#58;=false;    END;END;// <F> convert//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// // setConvert&#58; &#40;why not convert to&#58; clock , start, stop, cont?&#41;FUNCTION setConvert&#40;srcMsg&#58;byte;typeId&#58;integer&#41;&#58;byte;BEGIN&#40;*IF = notes&#58; Note Legato","Note Poly &#40;mode1&#41;","Note Poly &#40;mode2&#41; 1-3; CC = 4generate events! if replace with current, loose data...Legato&#58;         if new event arrives, last event is closed&#58;         if not first event generate noteOff for the previous event        structures&#58; noteConvertTmpMidi&#58;= tmp // just before FOR loop ends.Mode1&#58;  if new event arrives, add_output noteOFF for oldest even noteOn,         or if it is the only note present. remove closed note from array        structures&#58; event array&#58; boolean&#91;chn&#93;&#91;note&#93; for currently open notes  //        ..already got this?Mode2&#58;  if new event arrives, add_output noteOFF for oldest odd noteOn,         or if it there are only even notes. remove closed note from array        -> even notes will endure until all odd notes are finished*&#41;    IF typeId=4 THEN BEGIN        result&#58;=176; // CC    END    ELSE IF typeId=14 THEN BEGIN        result&#58;=144; // leg play&#58; send noteOff Value if next noteOn value arrives tmp.Msg var holding last value    END         ELSE IF typeId=5 THEN BEGIN        result&#58;=192; // PC &#40;no 2nd byte&#41;    END    ELSE IF typeId=6 THEN BEGIN         result&#58;=224; // PitchBend &#40;Modwheel&#41;    END    ELSE IF typeId=7 THEN BEGIN        result&#58;=208; // Aftert Channel    END    ELSE IF typeId=8 THEN BEGIN        result&#58;=160; // Aftert Poly    END    ELSE BEGIN        result&#58;=srcMsg;    END; END;&#40;*// <F>getOpenNotes//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^//FUNCTION getOpenNotes&#40;&#41;&#58;integer;// global variables!!BEGIN           //boolNotesArray&#91;&#93;&#91;&#93;    END; //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^//// <P> writeNoteOff&#58; for convert to Notes//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^//PROCEDURE writeNoteOff;// global variables!!VAR extra&#58; TMidi;BEGIN      extra.msg&#58;=byte&#40;128&#41;;     extra.data1&#58;=tmp.data1;     extra.data2&#58;=0;     extra.channel&#58;=tmp.channel;     // write out     //setLength&#40;pOut&#41;&#58;= getLength&#40;pOut&#41;+1;     // ?? TEST!! ?? setMidiArrayData&#40;pOut,trunc&#40;getLength&#40;pOut&#41;&#41;-1&#41;,extraMidi&#41;     // remove from array     //NotesArray&#91;aVal&#93;&#58;= false;     //countNotes&#40;false&#41;; END; *&#41;// <P> countNotes&#58;  PROCEDURE countNotes&#40;isANoteAndON&#58;boolean&#41;;//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^//BEGIN       IF isANoteAndON THEN BEGIN         notesCount&#58;=notesCount+1             END    ELSE BEGIN        notesCount&#58;=notesCount-1;       END;       END;// <P> initLimitRange&#58; expect&#58; limitHi and limitLo are getValue&#40;p&#41; //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// PROCEDURE initLimitRange;BEGIN       IF limitHi-limitLo< 0 THEN BEGIN            tmpLimitLo&#58;=limitLo;          limitLo&#58;=limitHi;          limitHi&#58;=tmpLimitLo       END      ELSE IF limitHi-limitLo=0 THEN BEGIN          IF limitHi=128 THEN BEGIN               limitLo&#58;=127;           END          ELSE BEGIN              limitHi&#58;=limitHi+1;          END;      END; END; // <P> setDataSymbols&#58; //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// PROCEDURE setDataSymbols;VAR tr&#58; integer;BEGIN                    IF &#40;trunc&#40;getValue&#40;pStep&#41;&#41;<= 1&#41; THEN BEGIN         setSymbol&#40;pStep,''&#41;;setFormat&#40;pStep,'-bypass-'&#41;;     END     ELSE BEGIN          setSymbol&#40;pStep,'%'&#41;; setFormat&#40;pStep,'%.0f'&#41;    END;         tr&#58;=trunc&#40;getValue&#40;pTransp&#41;&#41;;    IF tr>0 THEN BEGIN         setSymbol&#40;pTransp,'+'&#41;; setFormat&#40;pTransp,'%.0f'&#41;;      END    ELSE IF  &#40;tr=&#40;-128&#41;&#41;OR&#40;tr=0&#41; THEN BEGIN         setSymbol&#40;pTransp,''&#41;; setFormat&#40;pTransp,'-bypass-'&#41;;     END    ELSE BEGIN          setSymbol&#40;pTransp,''&#41;;setFormat&#40;pTransp,'%.0f'&#41;;      END; &#40;*       IF trunc&#40;getValue&#40;pLimitHi&#41;&#41; = 127 THEN BEGIN         setColor&#40;pLimitHi,81099&#41;;    END     ELSE BEGIN         setColor&#40;pLimitHi,90099&#41;;    END;     IF trunc&#40;getValue&#40;pLimitLo&#41;&#41; = 0 THEN BEGIN              setOffColor&#40;pLimitLo,90099&#41;;    END     ELSE BEGIN        // setColor&#40;pLimitLo,90099&#41;;    END;    *&#41;    END;//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^|   //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^|    // main  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|     //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^|       //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^|BEGIN         len &#58;= getLength&#40;pIn&#41;;   lenCount&#58;= len;       IF len > 0 THEN BEGIN              multiply&#58;=pMultAr&#91;trunc&#40;getValue&#40;pMult&#41;&#41;&#93;;      transpose&#58;= trunc&#40;getValue&#40;pTransp&#41;&#41;;       IF &#40;transpose=&#40;-128&#41;&#41; THEN BEGIN // control&#58; bypass at the left end for convenience          transpose&#58;=0;       END;      tmpEvent&#58;=trunc&#40;getValue&#40;pEvent&#41;&#41;;      tmpDest&#58;=trunc&#40;getValue&#40;pDest&#41;&#41;;      isFirstByte&#58;=&#40;tmpDest=2&#41;OR&#40;tmpDest=0&#41;;      isSecondByte&#58;=&#40;tmpDest=2&#41;OR&#40;tmpDest=1&#41;;      limitLo&#58;=trunc&#40;getValue&#40;pLimitLo&#41;&#41;;      limitHi&#58;=trunc&#40;getValue&#40;pLimitHi&#41;&#41;;      limit&#58;=trunc&#40;getValue&#40;pLimit&#41;&#41;;      isLimit&#58;=&#40;limit>0&#41; AND &#40;&#40;limitLo>=1&#41;AND&#40;limitHi<=126&#41;&#41;;      initLimitRange&#40;&#41;;      convert&#58;=trunc&#40;getValue&#40;pConv&#41;&#41;;      step&#58;=trunc&#40;getValue&#40;pStep&#41;&#41;;      isStepActive&#58;=step>1;        isInv1&#58;=getValue&#40;pInv1&#41;>0;       isInv2&#58;=getValue&#40;pInv2&#41;>0;         isSwap&#58;=getValue&#40;pSwap&#41;>0;         isWrap&#58;=trunc&#40;getValue&#40;pWrap&#41;&#41;>0;      isThru&#58;=trunc&#40;getValue&#40;pThru&#41;&#41;>0;      FOR i &#58;= 0 TO &#40;len - 1&#41; DO BEGIN          getMidiArrayValue&#40;pIn, i, tmp&#41;;           IF isMidiMsg&#40;tmp.msg, tmpEvent&#41; THEN BEGIN  // process on IF. if pThru is 1, process on ELSE             tmpMsg &#58;=tmp.msg;             tmpX &#58;= tmp.data1;             tmpY &#58;= tmp.data2;               tmpXX &#58;= tmpX; // store global for note off array                IF isInv1 THEN BEGIN tmpX&#58;= 127 - tmpX;END;             IF isInv2 THEN BEGIN tmpY&#58;= 127 - tmpY;END;                           IF isSwap THEN BEGIN                    tmpX &#58;= tmpY;                     tmpY &#58;= tmpXX;              END;                            // affect byte 1              IF isFirstByte THEN BEGIN   // 1st byte&#58; process 1st+2nd byte if tmpDest=2                          tmpX &#58;= trunc&#40;multiply*tmpX&#41; + &#40;transpose&#41;;                 tmpX &#58;= setWrap&#40;tmpX, isWrap&#41;;                 IF isLimit THEN BEGIN                     tmpX &#58;= trunc&#40;tmpX * calcLimited&#40;tmpX,limitLo,limitHi,limit&#41;&#41;;                 END;                 tmp.data1 &#58;= byte&#40;tmpX&#41;;                             END;              // affect byte 2              IF isSecondByte THEN BEGIN    // 2nd byte&#58; process 1st+2nd byte if tmpDest=2                   tmpY &#58;= trunc&#40;multiply*tmpY&#41; + &#40;transpose&#41;;                 tmpY &#58;= setWrap&#40;tmpY, isWrap&#41;;                 IF isLimit THEN BEGIN                      tmpY &#58;= trunc&#40;tmpY * calcLimited&#40;tmpY,limitLo,limitHi,limit&#41;&#41;;                 END;                 tmp.data2 &#58;= byte&#40;tmpY&#41;;                       END;                 // affect msg&#58; convert event             IF isConvert THEN BEGIN                   tmp.msg &#58;= setConvert&#40;tmp.msg,convert&#41;;             END;             isNoteOff&#58;= &#40;tmpMsg=128&#41; OR &#40;&#40;tmpMsg=144&#41;AND&#40;tmpY=0&#41;&#41;;             isNoteOn &#58;= &#40;isNoteOff=false&#41;AND&#40;&#40;tmpMsg=144&#41;AND&#40;tmpY>0&#41;&#41;;                    // only when Notes are output                 // prevent hanging notes &#40;tmpXX for swapped note values&#41;; ! if convert=>Notes&#58;              IF isNoteOn THEN BEGIN                  mult&#91;tmp.channel - 1&#93;&#91;tmpXX&#93; &#58;= tmp.data1;  // tmpXX&#40;old 1st byte&#41; needed for noteOff value                   IF notesList&#91;tmp.channel - 1&#93;&#91;tmpXX&#93;=false THEN BEGIN                     notesList&#91;tmp.channel - 1&#93;&#91;tmpXX&#93;&#58;= true;                                      END;                  //IF &#40;&#40;convert<=3&#41;AND&#40;convert>0&#41;&#41; THEN BEGIN                  //addToBoolNotes&#40;tmp.data1, tmp.channel, tmpXX&#41;;                 // END                 //ELSE BEGIN                                       //END;                               END             ELSE IF isNoteOff THEN BEGIN //  ! if convert=>Notes&#58;                 tmp.data1 &#58;= mult&#91;tmp.channel - 1&#93;&#91;tmpXX&#93;; // set NoteOff value from original NoteOn value                 IF notesList&#91;tmp.channel - 1&#93;&#91;tmpXX&#93;=true THEN BEGIN                     notesList&#91;tmp.channel - 1&#93;&#91;tmpXX&#93;&#58;=false;                                      END;              END;                      IF  isFirstByte OR &#40;isFirstByte AND isSecondByte&#41; THEN BEGIN                filterByte&#58;= tmpX;           END //&#40;tempDest=1&#41;           ELSE BEGIN                filterByte&#58;= tmpY;           END;           IF &#40;&#40;limit=1&#41; AND &#40;&#40;limitLo>filterByte&#41; OR &#40;limitHi<filterByte&#41;&#41;&#41; OR              &#40;isStepActive AND&#40;isStep&#40;filterByte,step&#41;=true&#41;&#41;           THEN BEGIN  // filter message                lenCount&#58;=lenCount-1;           END            ELSE BEGIN                IF isNoteOn THEN BEGIN                    countNotes&#40;true&#41;;                END               ELSE IF isNoteOff THEN BEGIN                    countNotes&#40;false&#41;;               END;                      setLength&#40;pOut,lenCount&#41;;                setMidiArrayValue&#40;pOut, i, tmp&#41;;  // write modified message           END;           END              // ! isMidiMsg&#40;&#41;           ELSE BEGIN                  IF isThru THEN BEGIN                       setMidiArrayValue&#40;pOut, i, tmp&#41;;                   END                 ELSE BEGIN                      setLength&#40;pOut, 0&#41;;                  END;            END;         END;  // &#40;FOR i &#58;= 0 ..           END    ELSE BEGIN       setLength&#40;pOut, 0&#41;;    END; // len = 0 setValue&#40;pNotesCount, notesCount&#41;;setDataSymbols&#40;&#41;;END.

Statistics: Posted by amiga909 — 04 Nov 2008, 08:47


]]>