Welcome to %s forums

BrainModular Users Forum

Login Register

a patch that counts notes to filter a midi phrase

I need help on a Patch
Post Reply
claygues
Member
Posts: 27
Contact:

Unread post by claygues » 06 Apr 2009, 17:46

Bonjour/hi,



i need a patch that counts notes to filter a midi phrase

I don't know where to begin. It seems to be possible with a script?

That i would like to do:

1-

for example

a phrase loop with 9 notes: 1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9 : midi in

a way to pickup a note on 2: 1 3 5 7 9 2 4 6 8 : midi out

a note on 3: 1 4 7 1 4 7 : midi out

a note on n...



2-

a way to scroll n step forward (pass n notes before count begins)

a note on 3 0 step forward: 1 4 7 1 4 7 : midi out

1 step forward: 2 5 8 2 5 8 : id

2 step forward: 3 6 9 3 6 9 : id





If someone can give me information.

Syntax info source for script (not sure that i'll be able to deal with it)?



Salutations, cyrille.

amiga909
Member
Posts: 324
Contact:

Unread post by amiga909 » 06 Apr 2009, 23:37

hi
if u want to try for yourself:
I'd use the MOD operator (modulo). and you need to filter and count note on's of course. like:
IF ((count >= trunc(getValue(offset))) AND (NOT(count MOD trunc(getValue(step))) = 0)) THEN BEGIN // process message
END
ELSE BEGIN // filter message, go to next message

I can put it together for you (maybe tomorrow). its not hard.

claygues
Member
Posts: 27
Contact:

Unread post by claygues » 07 Apr 2009, 11:21

Thanks Amiga909,
I afraid i have not the background to understand yet.
But yes i prefer try myself !
Is this script syntax specific to usine?
If not where can i find things to begin.
I have no programmer's abilities but script seem to be powerful to midi manipulation, then it worth than i take a look.
Your help is welcome.

amiga909
Member
Posts: 324
Contact:

Unread post by amiga909 » 08 Apr 2009, 10:49

hi cyrille

ok, here is a running version.
its a bit more complicated now - but u should be able to change params in realtime without getting hanging notes (I can explain..). also i stole your idea and i'll do it a bit more generic (eg. want to try to limitCount midiclock messages, etc.).

this version is a mere draft, have to leave now... hope it should get u started with experimenting :)

Code: Select all

(*/////////////////////////////////////////////////////
// MEP_limitCount -  midi script module for sensomusic usine 
// version: 2009-04-08 0.1; author: amiga909
//
//  TO DO: select message type for counting

// <Description> 
// 	filters Note message based on a counter

// <Parameters> 
//  offset
//  step
			
		
//////////////////////////////////////////////////////
*&#41;

//////////////////////////////////////////////////////
// globals
//////////////////////////////////////////////////////
VAR  pIn, pOut, pOut2, pStep, pOffset,pResetCount &#58; TParameter;  

TYPE MidiNotes   	= ARRAY OF BOOLEAN;
VAR  midiMem     	&#58; ARRAY OF MidiNotes;  
VAR  midiMem2     	&#58; ARRAY OF MidiNotes;  
VAR  tmp      		&#58; TMidi;   
VAR  len,len1,len2, i,j, step,tmpChan, offset, count   &#58; INTEGER;  
VAR  isLimit,isNoteOffMsg_out1,isNoteOffMsg_out2 &#58; BOOLEAN;
 
CONST NOTE_ON     = 144;	
CONST NOTE_OFF    = 128;	
CONST PROGRAM_CHG = 192;
CONST AFTER_MONO  = 208;	 
CONST PITCHBEND   = 224;
 
//////////////////////////////////////////////////////
// initialize
//////////////////////////////////////////////////////
PROCEDURE init;    
BEGIN  
	pIn &#58;= createParam&#40;'in', ptMidi&#41;;  
	pOut &#58;= createParam&#40;'out', ptMidi&#41;; 
	pOut2 &#58;= createParam&#40;'filtered', ptMidi&#41;; 

	pOffset &#58;= createParam&#40;'offset', ptDataFader&#41;; setMin&#40;pOffset, 0&#41;;setMax&#40;pOffset, 16&#41;;
	pStep &#58;= createParam&#40;'step', ptDataFader&#41;; setMin&#40;pStep, 1&#41;;setMax&#40;pStep, 16&#41;;
	setFormat&#40;step, '%.0f'&#41;; setFormat&#40;offset, '%.0f'&#41;;
	pResetCount &#58;= createParam&#40;'reset count', ptSwitch&#41;;

	setFormat&#40;pStep, '%.0f'&#41;; setFormat&#40;pOffset, '%.0f'&#41;;	

	setValue&#40;pStep,1&#41;;
	setValue&#40;pResetCount,0&#41;;
	setValue&#40;pOffset,0&#41;;
	setValue&#40;pStep,1&#41;; 

	setIsInput&#40;pOut,FALSE&#41;;
	setIsInput&#40;pOut2,FALSE&#41;;
	setIsOutput&#40;pIn,FALSE&#41;;
	setIsOutput&#40;pStep,FALSE&#41;;
	setIsOutput&#40;pResetCount,FALSE&#41;;
	setIsOutput&#40;pOffset,FALSE&#41;;

	len&#58;=0; len1 &#58;= 0; len2 &#58;= 0;
	isNoteOffMsg_out1 &#58;= FALSE;		
	isNoteOffMsg_out2 &#58;= FALSE;			 

	setArrayLength&#40;midiMem, 16&#41;;    
	setArrayLength&#40;midiMem2, 16&#41;;  
	FOR i &#58;= 0 TO 15 DO BEGIN   
	      setArrayLength&#40;midiMem&#91;i&#93;, 128&#41;; 
		  setArrayLength&#40;midiMem2&#91;i&#93;, 128&#41;;
	      FOR j&#58;=0 TO 127 DO BEGIN 
	          midiMem&#91;i&#93;&#91;j&#93;&#58;=FALSE;
			  midiMem2&#91;i&#93;&#91;j&#93;&#58;=FALSE;
	      END;
	END;
	
END;

// <F> filterMidi&#58; filter MIDI_CLOCK, START, CONT, STOP, ACTIVE_SENS  
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// 
FUNCTION filterMidi&#40;msg&#58; INTEGER&#41;&#58; BOOLEAN;  
BEGIN   
 IF &#40;msg <= PITCHBEND&#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> checkStep&#58; TRUE = is modulo dividend 
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// 
FUNCTION checkStep&#40;offs&#58; INTEGER; stp&#58; INTEGER&#41;&#58; BOOLEAN;
BEGIN
    IF &#40;&#40;count >= offs&#41;  AND &#40;NOT&#40;count MOD &#40;stp&#41;&#41; = 0&#41;&#41; THEN BEGIN
        RESULT&#58;=FALSE; // send to filter output
    END
    ELSE BEGIN
        RESULT&#58;=TRUE;  // pass to normal output
    END;
END;

// <P> setHangingNoteOff1&#58;  
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// 		 
PROCEDURE setHangingNoteOff1&#40;&#41;; 
BEGIN 
	IF isNoteOn&#40;tmp.msg,tmp.data2&#41; THEN BEGIN 
		midiMem&#91;tmpChan&#93;&#91;tmp.data1&#93; &#58;= TRUE;		
	END
	ELSE IF &#40;isNoteOff&#40;tmp.msg,tmp.data2&#41;&#41; THEN BEGIN 
		midiMem&#91;tmpChan&#93;&#91;tmp.data1&#93; &#58;= FALSE;	 
	END;		
END;		 
	
// <P> setHangingNoteOff2&#58;  
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// 		
PROCEDURE setHangingNoteOff2&#40;&#41;; 
BEGIN 
  
	IF isNoteOn&#40;tmp.msg,tmp.data2&#41; THEN BEGIN 
		midiMem2&#91;tmpChan&#93;&#91;tmp.data1&#93; &#58;= TRUE;		
	END
	ELSE IF &#40;isNoteOff&#40;tmp.msg,tmp.data2&#41;&#41; THEN BEGIN 
		midiMem2&#91;tmpChan&#93;&#91;tmp.data1&#93; &#58;= FALSE;		 
	END;		
END;	

 ////////////////////////////////////////
// main
//////////////////////////////////////////////////////
BEGIN 
   len &#58;= getLength&#40;pIn&#41;;
   	step &#58;= trunc&#40;getValue&#40;pStep&#41;&#41;;
    offset &#58;= trunc&#40;getValue&#40;pOffset&#41;&#41;;
   IF len > 0 THEN BEGIN 
   len1 &#58;= 0;
   len2 &#58;= 0;
   FOR i &#58;= 0 TO &#40;len - 1&#41; DO BEGIN 
    getMidiArrayValue&#40;pIn, i, tmp&#41;; 
	IF  &#40;filterMidi&#40;tmp.msg&#41;&#41; THEN BEGIN 
		tmpChan &#58;= tmp.channel - 1;  

		
		IF &#40;tmp.msg = NOTE_ON&#41; THEN BEGIN
			count &#58;= count + 1;
		END;
		
		IF &#40;checkStep&#40;offset, step&#41;&#41; THEN BEGIN 
			isLimit &#58;= TRUE;
		END
		ELSE BEGIN 
			isLimit &#58;= FALSE;
		END; 

   
			
		IF &#40;isLimit&#41; THEN BEGIN  // => out1
			IF &#40;&#40;isNoteOff&#40;tmp.msg,tmp.data2&#41;&#41; AND &#40;midiMem2&#91;tmpChan&#93;&#91;tmp.data1&#93;&#41;&#41; THEN BEGIN 
				setMidiArrayValue&#40;pOut2, len2, tmp&#41;; 
				len2 &#58;= len2 + 1;
				setHangingNoteOff2&#40;&#41;;				
			END
			ELSE BEGIN 
				setMidiArrayValue&#40;pOut, len1, tmp&#41;; 
				len1 &#58;= len1 + 1;				
				setHangingNoteOff1&#40;&#41;;
			END;
 
		END 
		ELSE BEGIN // // => out2; isLimit = FALSE  OR isNoteOffMsg_out2=TRUE  
			IF &#40;&#40;isNoteOff&#40;tmp.msg,tmp.data2&#41;&#41; AND &#40;midiMem&#91;tmpChan&#93;&#91;tmp.data1&#93;&#41;&#41; THEN BEGIN 
				setMidiArrayValue&#40;pOut, len1, tmp&#41;; 
				len1 &#58;= len1 + 1;	 
				setHangingNoteOff1&#40;&#41;;
			END
			ELSE BEGIN 
				setMidiArrayValue&#40;pOut2, len2, tmp&#41;; 
				len2 &#58;= len2 + 1;
				setHangingNoteOff2&#40;&#41;;
			END;
		END;
		setLength&#40;pOut,len1&#41;;  	
		setLength&#40;pOut2,len2&#41;;
	END 
	ELSE BEGIN 
	END;
   END;
   
   END
   ELSE BEGIN
		setLength&#40;pOut, 0&#41;;   
		setLength&#40;pOut2,0&#41;;		
   END;
   
   
  // writeln&#40;'count&#58;'+ inttostr&#40;count&#41;&#41;;
    IF &#40;trunc&#40;getValue&#40;pResetCount&#41;&#41; = 1 &#41; OR &#40;count = 16384&#41; THEN BEGIN 
		//count &#58;= offset + &#40;count MOD step&#41;;
		setValue&#40;pResetCount,0&#41;;
		count &#58;= 0;
		//setValue&#40;pOffset,0&#41;; NOT CORRECT!!
	END;  
   
END.
btw: @bsork and others: chords should be processed correctly (isnt the case in my scripts that use more than one output, will correct and upload them)


..to use the script, you need to copy&paste into a .script file and insert it in usine (browser or drag&drop).

claygues
Member
Posts: 27
Contact:

Unread post by claygues » 08 Apr 2009, 11:25

Bonjour/hi,

"i stole your idea and i'll do it a bit more generic (eg. want to try to limitCount midiclock messages, etc.). "
Your welcome!

"a bit more complicated now "
Ok, in fact it's very simple, i read the script language like the newspaper (just kidding, of course not !).

Salutations, Cyrille.

"..to use the script, you need to copy&paste into a .script file and insert it in usine (browser or drag&drop)."
I'll try it today, and try to understand it.

User avatar
nay-seven
Site Admin
Posts: 5684
Location: rennes France
Contact:

Unread post by nay-seven » 08 Apr 2009, 12:47

no midi in/out....?

amiga909
Member
Posts: 324
Contact:

Unread post by amiga909 » 08 Apr 2009, 12:56

np, mate :)

learning scripting: well.. it took me a long time to get into a bit. now it seems much easier but at the beginning i understood nothing. for me the best way was to start with the 1in/1out script and trying different Tparameters (midi, data, notes, switch, button, etc.), and then trying to do something with these parameters.
the getMidiArrayValue(), setMidiArrayValue(), setLength(), getLength() methods are vital. also the Midi data type.

this script: it should do what you want (at least it compiles). its a ripoff of another script and there a few redundant things it does.
i'l let you know when a final (tested) version is done.
in terms of elegance and CPU/RAM efficiency i won't be able to do a perfect script. if bsork wants to do a better version, look for his stuff!

amiga909
Member
Posts: 324
Contact:

Unread post by amiga909 » 08 Apr 2009, 17:09

nay-seven wrote:no midi in/out....?
?
pIn := createParam('in', ptMidi);
pOut := createParam('out', ptMidi);

claygues
Member
Posts: 27
Contact:

Unread post by claygues » 09 Apr 2009, 11:22

Bonjour/hi,

Just give up to understand, but it works fine and do that i want.
Well done Amiga 909 !

The idea is to make rythmical accents or arrange (in a very simple and automatic way) a patern or realtime while keyboard playing. Accent by playing the same instrument with diffrents eq, volume or send to a reverb parameter. Arrange by choosing differents sounds.
I'll post a patch that use 3 of it.

Salutations, cyrille.

Post Reply

Who is online

Users browsing this forum: No registered users and 36 guests