From 63305a132cf1a72e8d53d283471f0258d0f52bc7 Mon Sep 17 00:00:00 2001 From: Gerard van Dongen Date: Sat, 18 Oct 2003 13:20:49 +0000 Subject: This commit was generated by cvs2svn to compensate for changes in r1104, which included commits to RCS files with non-trunk default branches. svn path=/trunk/externals/beatpipe/; revision=1105 --- beatpipe.c | 277 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 277 insertions(+) create mode 100644 beatpipe.c (limited to 'beatpipe.c') diff --git a/beatpipe.c b/beatpipe.c new file mode 100644 index 0000000..05970cd --- /dev/null +++ b/beatpipe.c @@ -0,0 +1,277 @@ +/* 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 +static t_class *beatpipe_class; + + +typedef struct queue_node{ + float time; + int argc; + t_atom *argv; + struct queue_node * next; + struct queue_node * previous; +}t_queue; + +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); + class_sethelpsymbol(beatpipe_class,gensym("help-beatpipe")); + + +} -- cgit v1.2.1