Logo Search packages:      
Sourcecode: pd-beatpipe version File versions  Download package

beatpipe.c

/* beatpipe externals for pd
 * copyright 2003 Gerard van Dongen gml@xs4all.nl

* This program is free software; you can redistribute it and/or               
* modify it under the terms of the GNU General Public License                 
* as published by the Free Software Foundation; either version 2              
* of the License, or (at your option) any later version.                      
* This program is distributed in the hope that it will be useful,             
* but WITHOUT ANY WARRANTY; without even the implied warranty of              
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               
* GNU General Public License for more details.                                
* You should have received a copy of the GNU General Public License           
* along with this program; if not, write to the Free Software                 
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. 



* objects:  
* beatpipe
* schedules and quantizes lists. A realtime qlist, sort of.

 */



#include "m_pd.h"
#include <stdio.h>
#include <math.h>
static t_class *beatpipe_class;


00032 typedef struct queue_node{
      float time;
      int argc;
      t_atom *argv;
      struct queue_node * next;
      struct queue_node * previous;
}t_queue;

00040 typedef struct {
      t_object x_obj;
      t_queue *queue;
      t_clock *x_clock;
      double current_beat;
      t_float tempo;
      t_float tpq;
      double delay;
      int frozen;
      t_outlet *queue_out,*done_out;
}t_beatpipe;




void beatpipe_tick(t_beatpipe *x)
{


      x->current_beat = x->current_beat + 1/x->tpq;
      x->delay = 60000/(x->tempo*x->tpq);//to _milisecs_!!
      if (x->frozen) return;

      while (x->queue) {
            //pop of events of the top of the list

            if (x->current_beat >= x->queue->time) {
            
                  t_queue *temp;
                  temp = x->queue;
                  outlet_anything(x->queue_out,&s_list,x->queue->argc,x->queue->argv);
                  x->queue = x->queue->next;
                  freebytes(temp->argv,temp->argc*sizeof(t_atom));
                  freebytes(temp,sizeof(t_queue));

                  //if empty put out a bang on the right outlet:
                  if (!x->queue) outlet_bang(x->done_out);


            } else {
                  break;
            }
      }
      clock_delay(x->x_clock,x->delay);


}

void beatpipe_bang(t_beatpipe *x)
{
      x->frozen = 0;
      beatpipe_tick(x);
}

void beatpipe_freeze(t_beatpipe *x)
{
      x->frozen =1;
}
void beatpipe_sync(t_beatpipe *x)
{
      x->frozen = 0;
      clock_unset(x->x_clock);
      beatpipe_tick(x);
}
void beatpipe_syncbeat(t_beatpipe *x)
{
      x->frozen = 0;
      clock_unset(x->x_clock);
      x->current_beat =floor(x->current_beat+1.0);
      beatpipe_tick(x);

}

void beatpipe_set_tpq(t_beatpipe *x,t_floatarg tpq)
{
      x->tpq = tpq;
      if (x->tpq == 0) x->tpq = 96;
}


void beatpipe_clear(t_beatpipe *x)
{
      while (x->queue) {
            t_queue *temp;
            temp = x->queue;
            freebytes(x->queue,sizeof(t_queue));
            x->queue = temp->next;
      }
}




void beatpipe_list(t_beatpipe *x,t_symbol *s,int argc, t_atom* argv)
{
      t_float beat;
      t_queue *new;
      t_queue * temp;
      t_queue * previous;

      beat = atom_getfloatarg(0,argc,argv);
      // if time<=0 (or first element of list is not a number)output immediatly
      if (beat<=0.0)    { 
            outlet_anything(x->queue_out,s,argc-1,argv+1);
            return;
      }

      beat=beat+x->current_beat;

      //now insert in the queue

      new = getbytes(sizeof(t_queue));
      new->time = beat;
      new->argc = argc-1;
      new->argv = copybytes(argv+1,new->argc * sizeof(t_atom));


      //is queue empty?
      if (!x->queue) {

      
            x->queue = new;
            new->next = NULL;
            new->previous = NULL;
            return;
      }

      //now walk the queue

      temp = x->queue;
      
      while (temp) {

            if (!temp->next) {
                  temp->next =   new;
                  new->previous =  temp;
                  return;
            }
                  
            if (beat > temp->time) {
                  temp=  temp->next;
            
            } else {
                  if(!temp->previous) {
                        x->queue = new;
                        new->next = temp;
                        new->previous = NULL;
                        return;
                  }
                  new->previous = temp->previous;
                  temp->previous =  new;
                  new->next = temp;
                  temp= new->previous;
                  temp->next= new;
                  return;
            }
      }





}

void *beatpipe_new(t_floatarg tempo,t_floatarg tpq)
{


      t_beatpipe *x =(t_beatpipe *)pd_new(beatpipe_class);

      x->x_clock = clock_new(x, (t_method)beatpipe_tick);


      x->queue = NULL;

      if (tempo != 0.0)
            x->tempo = tempo;
      else
            x->tempo = 60.0;

      if (tpq !=0.0)
            x->tpq = tpq;
      else
            x->tpq = 96.0;


      x->current_beat = 0;
      x->delay = (double) 60000/(x->tempo*x->tpq);//to _milisecs_!!
      floatinlet_new(&x->x_obj,&x->tempo);

      clock_delay(x->x_clock,x->delay);

      x->queue_out=outlet_new(&x->x_obj,0);

      x->done_out=outlet_new(&x->x_obj, &s_bang);
      x->frozen = 0;
      return (x);

}

void beatpipe_free(t_beatpipe *x)
{
      clock_free(x->x_clock);

      while (x->queue) {
            t_queue *temp;
            temp = x->queue;
            freebytes(x->queue,sizeof(t_queue));
            x->queue = temp->next;
      }

}


void beatpipe_setup(void)
{


      beatpipe_class = class_new(gensym("beatpipe"), 
                         (t_newmethod)beatpipe_new,
                         (t_method)beatpipe_free,
                         sizeof(t_beatpipe),
                         CLASS_DEFAULT,
                         A_DEFFLOAT,
                         A_DEFFLOAT,0);

      class_addbang(beatpipe_class,(t_method) beatpipe_bang);

      class_addmethod(beatpipe_class, (t_method)beatpipe_clear,gensym("clear"),0);
      class_addmethod(beatpipe_class, (t_method)beatpipe_sync,gensym("sync"),0);
      class_addmethod(beatpipe_class, (t_method)beatpipe_syncbeat,gensym("sync-beat"),0);
      class_addmethod(beatpipe_class, (t_method)beatpipe_set_tpq,gensym("set-tpq"),A_DEFFLOAT,0);
      class_addmethod(beatpipe_class, (t_method)beatpipe_freeze,gensym("freeze"),0);
      class_addmethod(beatpipe_class, (t_method)beatpipe_bang,gensym("continue"),0);
      class_addlist(beatpipe_class,(t_method) beatpipe_list);
}

Generated by  Doxygen 1.6.0   Back to index