BangAround

From YoungMusic

Jump to: navigation, search

My first external. Full explanation and demo patch will follow.

#include "m_pd.h"

/* This object can alternate bangs over 4 outputs. The counter has 16 steps,
   and using an incoming integer from 0 to 5 (handy for radio buttons in pd)
   you can make it bang on:
	 		 0: never
	 		 1: every 16 steps
	 		 2: every 8 steps
	 		 3: every 4 steps
	 		 4: every 2 steps
	 		 5: every step
   I made this to trigger samples in a very steady rhythm. More specificly I try 
   to make an electronic version of Riley's in C with this.
   The alternation between 4 outputs exists because a sample can be longer than a
   period. This way it can keep playing 4 times longer.
   
   A metro object can best be used as an input to get a steady pulse. You can 
   send a "reset" message to get the counter back to zero, which is handy to syncronise 
   several objects.
   The output frequency can be changed with the message "setstep x" in which x is a 
   number between 0 and 5.
   
   There is one creation argument, which is the initial output frequency ( = setstep).
*/

static t_class *cBangAround;

typedef struct _BangAround {
  t_object x_obj;
  t_int counter; // this counter is incremented with each bang
  t_int output; // circulate between four outputs
  t_int steps; // how often a bang i sent to the output
  t_int incSteps; // temporary save incoming step format until we ended the current cycle
  t_outlet *out1, *out2, *out3, *out4; // four outlets for bangs 
} typeBangAround;

void incoming(typeBangAround *x) {
  if (x->counter == 16) { 
 	  x->counter = 0;
 	  x->steps = x->incSteps; // only change the steps after a whole cycle
	}
	if (x->steps > 0) { // 0 means don't output anything
	  if ((x->counter % x->steps) == 0) {
		 
      // generate output
      if(x->output == 1) outlet_bang(x->out1);
      if(x->output == 2) outlet_bang(x->out2);
      if(x->output == 3) outlet_bang(x->out3);
      if(x->output == 4) outlet_bang(x->out4);
	    //	next time take the next output
	    if (x->output == 4) {
	   		x->output = 1;
	    } else {
	 	    x->output++;
	    }
	  }						
  }
  x->counter++;
} 

void setStep(typeBangAround *x, t_floatarg f) {
	t_int i = f;
	switch (i) {
		case 0: x->incSteps = 0;
				    break;
    case 1: x->incSteps = 16;
            break;
    case 2: x->incSteps = 8;
            break;
    case 3: x->incSteps = 4;
            break;
    case 4: x->incSteps = 2;
            break;
    case 5: x->incSteps = 1;
  }
}     

void reset(typeBangAround *x) {
	x->counter = 0;
}	 
	 
void *New(t_floatarg f) {
  typeBangAround *x = (typeBangAround *)pd_new(cBangAround);
  x->counter = 0; // variables get an initial value in this function
  x->output = 1;
  x->steps = f;
  x->incSteps = f;
  x->out1 = outlet_new(&x->x_obj, gensym("bang"));
  x->out2 = outlet_new(&x->x_obj, gensym("bang"));
  x->out3 = outlet_new(&x->x_obj, gensym("bang"));
  x->out4 = outlet_new(&x->x_obj, gensym("bang"));
  return (void *)x;
} 

__declspec(dllexport) void BangAround_setup(void) {
  cBangAround = class_new(gensym("BangAround"),
                           (t_newmethod)New,
                            0, sizeof(typeBangAround),
                            CLASS_DEFAULT,
 		             A_DEFFLOAT, 0); // one  creation argument to set how many step 
        		                     // go in each roun d
												
  // a function is setup to intercept incoming bangs		
  class_addbang(cBangAround, incoming);
   
  // another function for the incoming message setstep, which changes the interval
  class_addmethod(cBangAround, 
                 (t_method)setStep, 
	          gensym("setstep"),
	          A_DEFFLOAT, 0);

  class_addmethod(cBangAround,
                 (t_method)reset,
                 gensym("reset"),
                 0);
}
Personal tools