< Back to IRCAM Forum

Macro & Curve

Hi,

I would like and I’m trying to write a macro definition to set a number of banks of formant filters (frequency, amplitude, bandwith) and in the same time tweak the amplitude parameter through the curve function for each bank (my separate attempts are below ) the thing is I have a bank of 8 filters and I would like to send different banks at each different event i.e. :

event1
(1 freq1 amp1 bw1, 2 freq2 amp2 bw2, … , n freqn ampn bwn) and tweak the $amp with curves

event2
(1 freq1 amp1 bw1, 2 freq2 amp2 bw2, … , n freqn ampn bwn) and tweak the $amp with curves

my actual attempt both works but separately:

NOTE Bb3 4 MACRO

@MACRO_DEF Muse_Wah($BANK_RECEIVE, $Num, $FRQ, $AMP, $BW) ;maybe $FREQ_RECEIVE, $AMP_RECEIVE, $BW_RECEIVE
{
group {

	$BANK_RECEIVE $Num $FRQ $AMP $BW       
 }  

}

@Muse_Wah(formantissimo, 1, 311, 40, 10)

Trill (C4-Bb3) 4 beg

noise 1;

  1. loop 6.66

{

curve @action:=amps $x1 $x2 $x3 $x4 $x5 $x6 $x7 $x8 @grain:=0.03s
{
$x1, $x2, $x3, $x4, $x5, $x6, $x7, $x8
{

    {100. 0. 0. 0. 0. 0. 0. 0.}   
0.5 {0. 100. 0. 0. 0. 0. 0. 0.}  
0.5 {0. 0. 100. 0. 0. 0. 0. 0.}  
1.0 {0. 0. 0. 100. 0. 0. 0. 0.}  
0.5 {0. 0. 0. 0. 100. 0. 0. 0.}  
0.5 {0. 0. 0. 0. 0. 100. 0. 0.}  
0.5 {0. 0. 0. 0. 0. 0. 100. 0.}  
1.0 {0. 0. 0. 0. 0. 0. 0. 100.}  
	}  

}  

} /until(expr)/

is it possible or do I have to implement a max module for each bank like in the attached screenshot ?

hope it’s not a mess of a request

thanks

N.

Capture-d’écran-2015-04-15-à-11.18.30.jpg

Hello Nadir.

I am not sure to understand the question. Is it an Antescofo question or a Max question ?

In the first case, yes, the code you have written is a correct Antescofo program :slight_smile: At each iteration of the loop (that is, each 6.6 beats), a new curve is started (that lasts 4.5 beats). If you want to avoid to explicit the number of bank, (for example because you want to write a code that adapts to any number of bank), you can replace all the variable by just one, and instead of specifying a list of breakpoints, you use a TAB (a vector). Something like

curve   
@action:=amps $x  
@grain:=0.03s  
{  
    $x  {  
               $v1  
           0.5 $v2  
           0.5 $v3  
           1.0 $v4  
           0.5 $v5  
           0.5 $v6  
           0.5 $v7  
           0.5 $v8  
           1.0 $v9  
        }  
}

where the $v… have been initialized (or computed), e.g.
$v1 := [100. 0. 0. 0. 0. 0. 0. 0.]
(note the square bracket used to define a tab). When an expression like $x is evaluated in the arguments of a Max message, it is replaced by all the element of the tab.

If you want to avoid the routing in Max, you can change the action of the curve : the action of the curve can be an arbitrary group of actions enclosed in curly brackets :

curve   
@action := {  
   amp1 $x[0]  
   amp2 $x[1]  
   amp3 $x[2]  
   ...  
}  
@grain:=0.03s  
{  
   $x ...  
}

In this example I suppose that the curve is vectorial to adapt to any number of banks, but the action enumerate explicitly the banks.

We can do much better. If we suppose that the banks are named banki then we can use a forall to iterate over the tab elements and to compute the Max receiver. We juste use an auxilliary vector which correspond to the indices used to access both the tab elements (tab indexing starts at 0) and the banks. For the fun, we suppose that the bank numbering starts at 1 :

$N := ...                       ; the number of banks  
$indices := [ $i : $i in ($N) ] ; [0, 1, 2 ..., $N-1] the vector of indices, see the definition of a tab in comprehension in the doc  
...  
Curve  
@action := {  
    forall $i in $indices  
    {  
       @command("bank" + ($i + 1)) $x[$i]  
    }  
}  
@grain:=0.03s  
{  
   $x ...  
}

in the previous code fragment, notice the use of the @command construct to specify that the action is a Max message but that the receiver must be computed. The receiver is computed as the addition + of a string and an integer: this will simply concatenate the string and the string representation of the integer.

Do not hesitate to ask for clarification.

Hi Jean-Louis,

It is actually an Antescofo/Ascograph question. I’m going to practice the code and hints you shared and I’ll be back to you.

Thank you

Bye

N.

Hi,

Back after some practice thanks to Jean-Louis and José Miguel’s advices…

First the forall routine is quite handy !

Here is a dynamic patching and a message forward tweak (all in one) for Max users (quite sure it’s portable to PD and more…)

$x1 := 0
$N := 13 ; the number of instances
$indices := [ $i | $i in ($N) ] ; the vector of indices

forall $i in $indices
{

	this_patcher script newdefault ("var_env" + ($i + 1)) 425 100 "r" (($i + 1) + "_env")   

	;one needs a max patch window  with a <code>thispatcher</code> object connected to a <code>receive</code> object, here "this_patcher"  

	;this script will instantiate sequencially the number of ($i+1)_env receive objects i.e. 1_env, 2_env... $N_env  

            ;the instantiated receive objects will have each a "var_env($i+1)" scripting name i.e. var_env1, var_env2... var_env$N  

            ;the receive objects in the max patch window will have the same position "425 100"    



	this_patcher script connect ("var_env" + ($i + 1)) 0 print_me 0  
	  
	; one needs to give a scripting name to the print object (within its inspector), here "print_me"  
	  
	; this script will connect the instantiated receivers to the print object  

            ; the two "0" in the script are respectively the first outlets of the receivers and print objects.  
    
	@command(($i + 1) + "_env") $x1  
	  
	; this command will send the $N number of $x1 to the print object, here 13 Zeros to init 13 envelops  
           
	; ... whatever, whenever, wherever  

}

just for fun

N.

… the code tag didn’t work well

I forgot about the latency issues… (because of max dsp status and one’s machine’s processing core)
I for one think that a slight delay is needed between the scripts making max objects and the one which forwards the parameters…

like this :

$x1 := 0  

$N := 13   
$indices := [ $i | $i in ($N) ] ;   

forall $i in $indices {  
	  
		this_patcher script newdefault ("var_env" + ($i + 1)) 425 100 "r" (($i + 1) + "_env")   
		this_patcher script connect ("var_env" + ($i + 1)) 0 print_me 0  
		  
		60ms  
        
		@command(($i + 1) + "_env") $x1  
		  
  }

N.

@nadir-b : I just came across this post where you are actually creating a Max patch on-the-fly using the Antescofo language hooked to “thispatcher” scripting in Max! Wonderfull!!!

Do you mind sharing a patch example + sample score in a Zip file here for us to look at and test?

Did you ever considered using Max’ Javascript capabilities for this? I have recently tried creating patches on the fly with max’ JS and am now thinking of moving them to Antescofo libraries… Wondering if you have had any experience.