Add the identifying header
[kugel-rb.git] / apps / plugins / pdbox / PDa / src / d_array.c
blob7139e4dc3d92bccb9be0772dc742d3eb9a1a5eaf
1 /* Copyright (c) 1997-1999 Miller Puckette and others.
2 * For information on usage and redistribution, and for a DISCLAIMER OF ALL
3 * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
5 /* sampling */
7 /* LATER make tabread4 and tabread~ */
9 #include "m_pd.h"
12 /* ------------------------- tabwrite~ -------------------------- */
14 static t_class *tabwrite_tilde_class;
16 typedef struct _tabwrite_tilde
18 t_object x_obj;
19 int x_phase;
20 int x_nsampsintab;
21 float *x_vec;
22 t_symbol *x_arrayname;
23 t_clock *x_clock;
24 float x_f;
25 } t_tabwrite_tilde;
27 static void tabwrite_tilde_tick(t_tabwrite_tilde *x);
29 static void *tabwrite_tilde_new(t_symbol *s)
31 t_tabwrite_tilde *x = (t_tabwrite_tilde *)pd_new(tabwrite_tilde_class);
32 x->x_clock = clock_new(x, (t_method)tabwrite_tilde_tick);
33 x->x_phase = 0x7fffffff;
34 x->x_arrayname = s;
35 x->x_f = 0;
36 return (x);
39 static t_int *tabwrite_tilde_perform(t_int *w)
41 t_tabwrite_tilde *x = (t_tabwrite_tilde *)(w[1]);
42 t_float *in = (t_float *)(w[2]);
43 int n = (int)(w[3]), phase = x->x_phase, endphase = x->x_nsampsintab;
44 if (!x->x_vec) goto bad;
46 if (endphase > phase)
48 int nxfer = endphase - phase;
49 float *fp = x->x_vec + phase;
50 if (nxfer > n) nxfer = n;
51 phase += nxfer;
52 while (nxfer--)
54 float f = *in++;
55 if (PD_BIGORSMALL(f))
56 f = 0;
57 *fp++ = f;
59 if (phase >= endphase)
61 clock_delay(x->x_clock, 0);
62 phase = 0x7fffffff;
64 x->x_phase = phase;
66 bad:
67 return (w+4);
70 void tabwrite_tilde_set(t_tabwrite_tilde *x, t_symbol *s)
72 t_garray *a;
74 x->x_arrayname = s;
75 if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class)))
77 if (*s->s_name) pd_error(x, "tabwrite~: %s: no such array",
78 x->x_arrayname->s_name);
79 x->x_vec = 0;
81 else if (!garray_getfloatarray(a, &x->x_nsampsintab, &x->x_vec))
83 pd_error(x, "%s: bad template for tabwrite~", x->x_arrayname->s_name);
84 x->x_vec = 0;
86 else garray_usedindsp(a);
89 static void tabwrite_tilde_dsp(t_tabwrite_tilde *x, t_signal **sp)
91 tabwrite_tilde_set(x, x->x_arrayname);
92 dsp_add(tabwrite_tilde_perform, 3, x, sp[0]->s_vec, sp[0]->s_n);
95 static void tabwrite_tilde_bang(t_tabwrite_tilde *x)
97 x->x_phase = 0;
100 static void tabwrite_tilde_stop(t_tabwrite_tilde *x)
102 if (x->x_phase != 0x7fffffff)
104 tabwrite_tilde_tick(x);
105 x->x_phase = 0x7fffffff;
109 static void tabwrite_tilde_tick(t_tabwrite_tilde *x)
111 t_garray *a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class);
112 if (!a) bug("tabwrite_tilde_tick");
113 else garray_redraw(a);
116 static void tabwrite_tilde_free(t_tabwrite_tilde *x)
118 clock_free(x->x_clock);
121 static void tabwrite_tilde_setup(void)
123 tabwrite_tilde_class = class_new(gensym("tabwrite~"),
124 (t_newmethod)tabwrite_tilde_new, (t_method)tabwrite_tilde_free,
125 sizeof(t_tabwrite_tilde), 0, A_DEFSYM, 0);
126 CLASS_MAINSIGNALIN(tabwrite_tilde_class, t_tabwrite_tilde, x_f);
127 class_addmethod(tabwrite_tilde_class, (t_method)tabwrite_tilde_dsp,
128 gensym("dsp"), 0);
129 class_addmethod(tabwrite_tilde_class, (t_method)tabwrite_tilde_set,
130 gensym("set"), A_SYMBOL, 0);
131 class_addmethod(tabwrite_tilde_class, (t_method)tabwrite_tilde_stop,
132 gensym("stop"), 0);
133 class_addbang(tabwrite_tilde_class, tabwrite_tilde_bang);
136 /* ------------ tabplay~ - non-transposing sample playback --------------- */
138 static t_class *tabplay_tilde_class;
140 typedef struct _tabplay_tilde
142 t_object x_obj;
143 t_outlet *x_bangout;
144 int x_phase;
145 int x_nsampsintab;
146 int x_limit;
147 float *x_vec;
148 t_symbol *x_arrayname;
149 t_clock *x_clock;
150 } t_tabplay_tilde;
152 static void tabplay_tilde_tick(t_tabplay_tilde *x);
154 static void *tabplay_tilde_new(t_symbol *s)
156 t_tabplay_tilde *x = (t_tabplay_tilde *)pd_new(tabplay_tilde_class);
157 x->x_clock = clock_new(x, (t_method)tabplay_tilde_tick);
158 x->x_phase = 0x7fffffff;
159 x->x_limit = 0;
160 x->x_arrayname = s;
161 outlet_new(&x->x_obj, &s_signal);
162 x->x_bangout = outlet_new(&x->x_obj, &s_bang);
163 return (x);
166 static t_int *tabplay_tilde_perform(t_int *w)
168 t_tabplay_tilde *x = (t_tabplay_tilde *)(w[1]);
169 t_float *out = (t_float *)(w[2]), *fp;
170 int n = (int)(w[3]), phase = x->x_phase,
171 endphase = (x->x_nsampsintab < x->x_limit ?
172 x->x_nsampsintab : x->x_limit), nxfer, n3;
173 if (!x->x_vec || phase >= endphase)
174 goto zero;
176 nxfer = endphase - phase;
177 fp = x->x_vec + phase;
178 if (nxfer > n)
179 nxfer = n;
180 n3 = n - nxfer;
181 phase += nxfer;
182 while (nxfer--)
183 *out++ = *fp++;
184 if (phase >= endphase)
186 clock_delay(x->x_clock, 0);
187 x->x_phase = 0x7fffffff;
188 while (n3--)
189 *out++ = 0;
191 else x->x_phase = phase;
193 return (w+4);
194 zero:
195 while (n--) *out++ = 0;
196 return (w+4);
199 void tabplay_tilde_set(t_tabplay_tilde *x, t_symbol *s)
201 t_garray *a;
203 x->x_arrayname = s;
204 if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class)))
206 if (*s->s_name) pd_error(x, "tabplay~: %s: no such array",
207 x->x_arrayname->s_name);
208 x->x_vec = 0;
210 else if (!garray_getfloatarray(a, &x->x_nsampsintab, &x->x_vec))
212 pd_error(x, "%s: bad template for tabplay~", x->x_arrayname->s_name);
213 x->x_vec = 0;
215 else garray_usedindsp(a);
218 static void tabplay_tilde_dsp(t_tabplay_tilde *x, t_signal **sp)
220 tabplay_tilde_set(x, x->x_arrayname);
221 dsp_add(tabplay_tilde_perform, 3, x, sp[0]->s_vec, sp[0]->s_n);
224 static void tabplay_tilde_list(t_tabplay_tilde *x, t_symbol *s,
225 int argc, t_atom *argv)
227 long start = atom_getfloatarg(0, argc, argv);
228 long length = atom_getfloatarg(1, argc, argv);
229 if (start < 0) start = 0;
230 if (length <= 0)
231 x->x_limit = 0x7fffffff;
232 else
233 x->x_limit = start + length;
234 x->x_phase = start;
237 static void tabplay_tilde_stop(t_tabplay_tilde *x)
239 x->x_phase = 0x7fffffff;
242 static void tabplay_tilde_tick(t_tabplay_tilde *x)
244 outlet_bang(x->x_bangout);
247 static void tabplay_tilde_free(t_tabplay_tilde *x)
249 clock_free(x->x_clock);
252 static void tabplay_tilde_setup(void)
254 tabplay_tilde_class = class_new(gensym("tabplay~"),
255 (t_newmethod)tabplay_tilde_new, (t_method)tabplay_tilde_free,
256 sizeof(t_tabplay_tilde), 0, A_DEFSYM, 0);
257 class_addmethod(tabplay_tilde_class, (t_method)tabplay_tilde_dsp,
258 gensym("dsp"), 0);
259 class_addmethod(tabplay_tilde_class, (t_method)tabplay_tilde_stop,
260 gensym("stop"), 0);
261 class_addmethod(tabplay_tilde_class, (t_method)tabplay_tilde_set,
262 gensym("set"), A_DEFSYM, 0);
263 class_addlist(tabplay_tilde_class, tabplay_tilde_list);
266 /******************** tabread~ ***********************/
268 static t_class *tabread_tilde_class;
270 typedef struct _tabread_tilde
272 t_object x_obj;
273 int x_npoints;
274 float *x_vec;
275 t_symbol *x_arrayname;
276 float x_f;
277 } t_tabread_tilde;
279 static void *tabread_tilde_new(t_symbol *s)
281 t_tabread_tilde *x = (t_tabread_tilde *)pd_new(tabread_tilde_class);
282 x->x_arrayname = s;
283 x->x_vec = 0;
284 outlet_new(&x->x_obj, gensym("signal"));
285 x->x_f = 0;
286 return (x);
289 static t_int *tabread_tilde_perform(t_int *w)
291 t_tabread_tilde *x = (t_tabread_tilde *)(w[1]);
292 t_float *in = (t_float *)(w[2]);
293 t_float *out = (t_float *)(w[3]);
294 int n = (int)(w[4]);
295 int maxindex;
296 float *buf = x->x_vec, *fp;
297 int i;
299 maxindex = x->x_npoints - 1;
300 if (!buf) goto zero;
302 for (i = 0; i < n; i++)
304 int index = *in++;
305 if (index < 0)
306 index = 0;
307 else if (index > maxindex)
308 index = maxindex;
309 *out++ = buf[index];
311 return (w+5);
312 zero:
313 while (n--) *out++ = 0;
315 return (w+5);
318 void tabread_tilde_set(t_tabread_tilde *x, t_symbol *s)
320 t_garray *a;
322 x->x_arrayname = s;
323 if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class)))
325 if (*s->s_name)
326 pd_error(x, "tabread~: %s: no such array", x->x_arrayname->s_name);
327 x->x_vec = 0;
329 else if (!garray_getfloatarray(a, &x->x_npoints, &x->x_vec))
331 pd_error(x, "%s: bad template for tabread~", x->x_arrayname->s_name);
332 x->x_vec = 0;
334 else garray_usedindsp(a);
337 static void tabread_tilde_dsp(t_tabread_tilde *x, t_signal **sp)
339 tabread_tilde_set(x, x->x_arrayname);
341 dsp_add(tabread_tilde_perform, 4, x,
342 sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
346 static void tabread_tilde_free(t_tabread_tilde *x)
350 static void tabread_tilde_setup(void)
352 tabread_tilde_class = class_new(gensym("tabread~"),
353 (t_newmethod)tabread_tilde_new, (t_method)tabread_tilde_free,
354 sizeof(t_tabread_tilde), 0, A_DEFSYM, 0);
355 CLASS_MAINSIGNALIN(tabread_tilde_class, t_tabread_tilde, x_f);
356 class_addmethod(tabread_tilde_class, (t_method)tabread_tilde_dsp,
357 gensym("dsp"), 0);
358 class_addmethod(tabread_tilde_class, (t_method)tabread_tilde_set,
359 gensym("set"), A_SYMBOL, 0);
362 /******************** tabread4~ ***********************/
364 static t_class *tabread4_tilde_class;
366 typedef struct _tabread4_tilde
368 t_object x_obj;
369 int x_npoints;
370 float *x_vec;
371 t_symbol *x_arrayname;
372 float x_f;
373 } t_tabread4_tilde;
375 static void *tabread4_tilde_new(t_symbol *s)
377 t_tabread4_tilde *x = (t_tabread4_tilde *)pd_new(tabread4_tilde_class);
378 x->x_arrayname = s;
379 x->x_vec = 0;
380 outlet_new(&x->x_obj, gensym("signal"));
381 x->x_f = 0;
382 return (x);
385 static t_int *tabread4_tilde_perform(t_int *w)
387 t_tabread4_tilde *x = (t_tabread4_tilde *)(w[1]);
388 t_float *in = (t_float *)(w[2]);
389 t_float *out = (t_float *)(w[3]);
390 int n = (int)(w[4]);
391 int maxindex;
392 float *buf = x->x_vec, *fp;
393 int i;
395 maxindex = x->x_npoints - 3;
397 if (!buf) goto zero;
399 #if 0 /* test for spam -- I'm not ready to deal with this */
400 for (i = 0, xmax = 0, xmin = maxindex, fp = in1; i < n; i++, fp++)
402 float f = *in1;
403 if (f < xmin) xmin = f;
404 else if (f > xmax) xmax = f;
406 if (xmax < xmin + x->c_maxextent) xmax = xmin + x->c_maxextent;
407 for (i = 0, splitlo = xmin+ x->c_maxextent, splithi = xmax - x->c_maxextent,
408 fp = in1; i < n; i++, fp++)
410 float f = *in1;
411 if (f > splitlo && f < splithi) goto zero;
413 #endif
415 for (i = 0; i < n; i++)
417 float findex = *in++;
418 int index = findex;
419 float frac, a, b, c, d, cminusb;
420 static int count;
421 if (index < 1)
422 index = 1, frac = 0;
423 else if (index > maxindex)
424 index = maxindex, frac = 1;
425 else frac = findex - index;
426 fp = buf + index;
427 a = fp[-1];
428 b = fp[0];
429 c = fp[1];
430 d = fp[2];
431 /* if (!i && !(count++ & 1023))
432 post("fp = %lx, shit = %lx, b = %f", fp, buf->b_shit, b); */
433 cminusb = c-b;
434 *out++ = b + frac * (
435 cminusb - 0.1666667f * (1.-frac) * (
436 (d - a - 3.0f * cminusb) * frac + (d + 2.0f*a - 3.0f*b)
440 return (w+5);
441 zero:
442 while (n--) *out++ = 0;
444 return (w+5);
447 void tabread4_tilde_set(t_tabread4_tilde *x, t_symbol *s)
449 t_garray *a;
451 x->x_arrayname = s;
452 if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class)))
454 if (*s->s_name)
455 pd_error(x, "tabread4~: %s: no such array", x->x_arrayname->s_name);
456 x->x_vec = 0;
458 else if (!garray_getfloatarray(a, &x->x_npoints, &x->x_vec))
460 pd_error(x, "%s: bad template for tabread4~", x->x_arrayname->s_name);
461 x->x_vec = 0;
463 else garray_usedindsp(a);
466 static void tabread4_tilde_dsp(t_tabread4_tilde *x, t_signal **sp)
468 tabread4_tilde_set(x, x->x_arrayname);
470 dsp_add(tabread4_tilde_perform, 4, x,
471 sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
475 static void tabread4_tilde_free(t_tabread4_tilde *x)
479 static void tabread4_tilde_setup(void)
481 tabread4_tilde_class = class_new(gensym("tabread4~"),
482 (t_newmethod)tabread4_tilde_new, (t_method)tabread4_tilde_free,
483 sizeof(t_tabread4_tilde), 0, A_DEFSYM, 0);
484 CLASS_MAINSIGNALIN(tabread4_tilde_class, t_tabread4_tilde, x_f);
485 class_addmethod(tabread4_tilde_class, (t_method)tabread4_tilde_dsp,
486 gensym("dsp"), 0);
487 class_addmethod(tabread4_tilde_class, (t_method)tabread4_tilde_set,
488 gensym("set"), A_SYMBOL, 0);
491 /******************** tabosc4~ ***********************/
493 /* this is all copied from d_osc.c... what include file could this go in? */
494 #define UNITBIT32 1572864. /* 3*2^19; bit 32 has place value 1 */
496 /* machine-dependent definitions. These ifdefs really
497 should have been by CPU type and not by operating system! */
498 #ifdef IRIX
499 /* big-endian. Most significant byte is at low address in memory */
500 #define HIOFFSET 0 /* word offset to find MSB */
501 #define LOWOFFSET 1 /* word offset to find LSB */
502 #define int32 long /* a data type that has 32 bits */
503 #else
504 #ifdef MSW
505 /* little-endian; most significant byte is at highest address */
506 #define HIOFFSET 1
507 #define LOWOFFSET 0
508 #define int32 long
509 #else
510 #ifdef __FreeBSD__
511 #include <machine/endian.h>
512 #if BYTE_ORDER == LITTLE_ENDIAN
513 #define HIOFFSET 1
514 #define LOWOFFSET 0
515 #else
516 #define HIOFFSET 0 /* word offset to find MSB */
517 #define LOWOFFSET 1 /* word offset to find LSB */
518 #endif /* BYTE_ORDER */
519 #include <sys/types.h>
520 #define int32 int32_t
521 #endif
523 #ifdef __linux__
524 #include <endian.h>
525 #if !defined(__BYTE_ORDER) || !defined(__LITTLE_ENDIAN)
526 #error No byte order defined
527 #endif
529 #if __BYTE_ORDER == __LITTLE_ENDIAN
530 #define HIOFFSET 1
531 #define LOWOFFSET 0
532 #else
533 #define HIOFFSET 0 /* word offset to find MSB */
534 #define LOWOFFSET 1 /* word offset to find LSB */
535 #endif /* __BYTE_ORDER */
537 #include <sys/types.h>
538 #define int32 int32_t
540 #else
541 #ifdef MACOSX
542 #define HIOFFSET 0 /* word offset to find MSB */
543 #define LOWOFFSET 1 /* word offset to find LSB */
544 #define int32 int /* a data type that has 32 bits */
546 #endif /* MACOSX */
547 #endif /* __linux__ */
548 #endif /* MSW */
549 #endif /* SGI */
551 union tabfudge
553 double tf_d;
554 int32 tf_i[2];
557 static t_class *tabosc4_tilde_class;
559 typedef struct _tabosc4_tilde
561 t_object x_obj;
562 float x_fnpoints;
563 float x_finvnpoints;
564 float *x_vec;
565 t_symbol *x_arrayname;
566 float x_f;
567 double x_phase;
568 float x_conv;
569 } t_tabosc4_tilde;
571 static void *tabosc4_tilde_new(t_symbol *s)
573 t_tabosc4_tilde *x = (t_tabosc4_tilde *)pd_new(tabosc4_tilde_class);
574 x->x_arrayname = s;
575 x->x_vec = 0;
576 x->x_fnpoints = 512.;
577 x->x_finvnpoints = (1./512.);
578 outlet_new(&x->x_obj, gensym("signal"));
579 inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("ft1"));
580 x->x_f = 0;
581 return (x);
584 static t_int *tabosc4_tilde_perform(t_int *w)
586 t_tabosc4_tilde *x = (t_tabosc4_tilde *)(w[1]);
587 t_float *in = (t_float *)(w[2]);
588 t_float *out = (t_float *)(w[3]);
589 int n = (int)(w[4]);
590 int normhipart;
591 union tabfudge tf;
592 float fnpoints = x->x_fnpoints;
593 int mask = fnpoints - 1;
594 float conv = fnpoints * x->x_conv;
595 int maxindex;
596 float *tab = x->x_vec, *addr;
597 int i;
598 double dphase = fnpoints * x->x_phase + UNITBIT32;
600 if (!tab) goto zero;
601 tf.tf_d = UNITBIT32;
602 normhipart = tf.tf_i[HIOFFSET];
604 #if 1
605 while (n--)
607 float frac, a, b, c, d, cminusb;
608 tf.tf_d = dphase;
609 dphase += *in++ * conv;
610 addr = tab + (tf.tf_i[HIOFFSET] & mask);
611 tf.tf_i[HIOFFSET] = normhipart;
612 frac = tf.tf_d - UNITBIT32;
613 a = addr[0];
614 b = addr[1];
615 c = addr[2];
616 d = addr[3];
617 cminusb = c-b;
618 *out++ = b + frac * (
619 cminusb - 0.1666667f * (1.-frac) * (
620 (d - a - 3.0f * cminusb) * frac + (d + 2.0f*a - 3.0f*b)
624 #endif
626 tf.tf_d = UNITBIT32 * fnpoints;
627 normhipart = tf.tf_i[HIOFFSET];
628 tf.tf_d = dphase + (UNITBIT32 * fnpoints - UNITBIT32);
629 tf.tf_i[HIOFFSET] = normhipart;
630 x->x_phase = (tf.tf_d - UNITBIT32 * fnpoints) * x->x_finvnpoints;
631 return (w+5);
632 zero:
633 while (n--) *out++ = 0;
635 return (w+5);
638 void tabosc4_tilde_set(t_tabosc4_tilde *x, t_symbol *s)
640 t_garray *a;
641 int npoints, pointsinarray;
643 x->x_arrayname = s;
644 if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class)))
646 if (*s->s_name)
647 pd_error(x, "tabosc4~: %s: no such array", x->x_arrayname->s_name);
648 x->x_vec = 0;
650 else if (!garray_getfloatarray(a, &pointsinarray, &x->x_vec))
652 pd_error(x, "%s: bad template for tabosc4~", x->x_arrayname->s_name);
653 x->x_vec = 0;
655 else if ((npoints = pointsinarray - 3) != (1 << ilog2(pointsinarray - 3)))
657 pd_error(x, "%s: number of points (%d) not a power of 2 plus three",
658 x->x_arrayname->s_name, pointsinarray);
659 x->x_vec = 0;
660 garray_usedindsp(a);
662 else
664 x->x_fnpoints = npoints;
665 x->x_finvnpoints = 1./npoints;
666 garray_usedindsp(a);
670 static void tabosc4_tilde_ft1(t_tabosc4_tilde *x, t_float f)
672 x->x_phase = f;
675 static void tabosc4_tilde_dsp(t_tabosc4_tilde *x, t_signal **sp)
677 x->x_conv = 1. / sp[0]->s_sr;
678 tabosc4_tilde_set(x, x->x_arrayname);
680 dsp_add(tabosc4_tilde_perform, 4, x,
681 sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
684 static void tabosc4_tilde_setup(void)
686 tabosc4_tilde_class = class_new(gensym("tabosc4~"),
687 (t_newmethod)tabosc4_tilde_new, 0,
688 sizeof(t_tabosc4_tilde), 0, A_DEFSYM, 0);
689 CLASS_MAINSIGNALIN(tabosc4_tilde_class, t_tabosc4_tilde, x_f);
690 class_addmethod(tabosc4_tilde_class, (t_method)tabosc4_tilde_dsp,
691 gensym("dsp"), 0);
692 class_addmethod(tabosc4_tilde_class, (t_method)tabosc4_tilde_set,
693 gensym("set"), A_SYMBOL, 0);
694 class_addmethod(tabosc4_tilde_class, (t_method)tabosc4_tilde_ft1,
695 gensym("ft1"), A_FLOAT, 0);
698 /* ------------------------ tabsend~ ------------------------- */
700 static t_class *tabsend_class;
702 typedef struct _tabsend
704 t_object x_obj;
705 float *x_vec;
706 int x_graphperiod;
707 int x_graphcount;
708 t_symbol *x_arrayname;
709 t_clock *x_clock;
710 float x_f;
711 } t_tabsend;
713 static void tabsend_tick(t_tabsend *x);
715 static void *tabsend_new(t_symbol *s)
717 t_tabsend *x = (t_tabsend *)pd_new(tabsend_class);
718 x->x_graphcount = 0;
719 x->x_arrayname = s;
720 x->x_clock = clock_new(x, (t_method)tabsend_tick);
721 x->x_f = 0;
722 return (x);
725 static t_int *tabsend_perform(t_int *w)
727 t_tabsend *x = (t_tabsend *)(w[1]);
728 t_float *in = (t_float *)(w[2]);
729 int n = w[3];
730 t_float *dest = x->x_vec;
731 int i = x->x_graphcount;
732 if (!x->x_vec) goto bad;
734 while (n--)
736 float f = *in++;
737 if (PD_BIGORSMALL(f))
738 f = 0;
739 *dest++ = f;
741 if (!i--)
743 clock_delay(x->x_clock, 0);
744 i = x->x_graphperiod;
746 x->x_graphcount = i;
747 bad:
748 return (w+4);
751 static void tabsend_dsp(t_tabsend *x, t_signal **sp)
753 int i, vecsize;
754 t_garray *a;
756 if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class)))
758 if (*x->x_arrayname->s_name)
759 pd_error(x, "tabsend~: %s: no such array", x->x_arrayname->s_name);
761 else if (!garray_getfloatarray(a, &vecsize, &x->x_vec))
762 pd_error(x, "%s: bad template for tabsend~", x->x_arrayname->s_name);
763 else
765 int n = sp[0]->s_n;
766 int ticksper = sp[0]->s_sr/n;
767 if (ticksper < 1) ticksper = 1;
768 x->x_graphperiod = ticksper;
769 if (x->x_graphcount > ticksper) x->x_graphcount = ticksper;
770 if (n < vecsize) vecsize = n;
771 garray_usedindsp(a);
772 dsp_add(tabsend_perform, 3, x, sp[0]->s_vec, vecsize);
776 static void tabsend_tick(t_tabsend *x)
778 t_garray *a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class);
779 if (!a) bug("tabsend_tick");
780 else garray_redraw(a);
783 static void tabsend_free(t_tabsend *x)
785 clock_free(x->x_clock);
788 static void tabsend_setup(void)
790 tabsend_class = class_new(gensym("tabsend~"), (t_newmethod)tabsend_new,
791 (t_method)tabsend_free, sizeof(t_tabsend), 0, A_DEFSYM, 0);
792 CLASS_MAINSIGNALIN(tabsend_class, t_tabsend, x_f);
793 class_addmethod(tabsend_class, (t_method)tabsend_dsp, gensym("dsp"), 0);
796 /* ------------------------ tabreceive~ ------------------------- */
798 static t_class *tabreceive_class;
800 typedef struct _tabreceive
802 t_object x_obj;
803 float *x_vec;
804 t_symbol *x_arrayname;
805 } t_tabreceive;
807 static t_int *tabreceive_perform(t_int *w)
809 t_tabreceive *x = (t_tabreceive *)(w[1]);
810 t_float *out = (t_float *)(w[2]);
811 int n = w[3];
812 t_float *from = x->x_vec;
813 if (from) while (n--) *out++ = *from++;
814 else while (n--) *out++ = 0;
815 return (w+4);
818 static void tabreceive_dsp(t_tabreceive *x, t_signal **sp)
820 t_garray *a;
821 int vecsize;
823 if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class)))
825 if (*x->x_arrayname->s_name)
826 pd_error(x, "tabsend~: %s: no such array", x->x_arrayname->s_name);
828 else if (!garray_getfloatarray(a, &vecsize, &x->x_vec))
829 pd_error(x, "%s: bad template for tabreceive~", x->x_arrayname->s_name);
830 else
832 int n = sp[0]->s_n;
833 if (n < vecsize) vecsize = n;
834 garray_usedindsp(a);
835 dsp_add(tabreceive_perform, 3, x, sp[0]->s_vec, vecsize);
839 static void *tabreceive_new(t_symbol *s)
841 t_tabreceive *x = (t_tabreceive *)pd_new(tabreceive_class);
842 x->x_arrayname = s;
843 outlet_new(&x->x_obj, &s_signal);
844 return (x);
847 static void tabreceive_setup(void)
849 tabreceive_class = class_new(gensym("tabreceive~"),
850 (t_newmethod)tabreceive_new, 0,
851 sizeof(t_tabreceive), 0, A_DEFSYM, 0);
852 class_addmethod(tabreceive_class, (t_method)tabreceive_dsp,
853 gensym("dsp"), 0);
857 /* ---------- tabread: control, non-interpolating ------------------------ */
859 static t_class *tabread_class;
861 typedef struct _tabread
863 t_object x_obj;
864 t_symbol *x_arrayname;
865 } t_tabread;
867 static void tabread_float(t_tabread *x, t_float f)
869 t_garray *a;
870 int npoints;
871 t_float *vec;
873 if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class)))
874 pd_error(x, "%s: no such array", x->x_arrayname->s_name);
875 else if (!garray_getfloatarray(a, &npoints, &vec))
876 pd_error(x, "%s: bad template for tabread", x->x_arrayname->s_name);
877 else
879 int n = f;
880 if (n < 0) n = 0;
881 else if (n >= npoints) n = npoints - 1;
882 outlet_float(x->x_obj.ob_outlet, (npoints ? vec[n] : 0));
886 static void tabread_set(t_tabread *x, t_symbol *s)
888 x->x_arrayname = s;
891 static void *tabread_new(t_symbol *s)
893 t_tabread *x = (t_tabread *)pd_new(tabread_class);
894 x->x_arrayname = s;
895 outlet_new(&x->x_obj, &s_float);
896 return (x);
899 static void tabread_setup(void)
901 tabread_class = class_new(gensym("tabread"), (t_newmethod)tabread_new,
902 0, sizeof(t_tabread), 0, A_DEFSYM, 0);
903 class_addfloat(tabread_class, (t_method)tabread_float);
904 class_addmethod(tabread_class, (t_method)tabread_set, gensym("set"),
905 A_SYMBOL, 0);
908 /* ---------- tabread4: control, non-interpolating ------------------------ */
910 static t_class *tabread4_class;
912 typedef struct _tabread4
914 t_object x_obj;
915 t_symbol *x_arrayname;
916 } t_tabread4;
918 static void tabread4_float(t_tabread4 *x, t_float f)
920 t_garray *a;
921 int npoints;
922 t_float *vec;
924 if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class)))
925 pd_error(x, "%s: no such array", x->x_arrayname->s_name);
926 else if (!garray_getfloatarray(a, &npoints, &vec))
927 pd_error(x, "%s: bad template for tabread4", x->x_arrayname->s_name);
928 else if (npoints < 4)
929 outlet_float(x->x_obj.ob_outlet, 0);
930 else if (f <= 1)
931 outlet_float(x->x_obj.ob_outlet, vec[1]);
932 else if (f >= npoints - 2)
933 outlet_float(x->x_obj.ob_outlet, vec[npoints - 2]);
934 else
936 int n = f;
937 float a, b, c, d, cminusb, frac, *fp;
938 if (n >= npoints - 2)
939 n = npoints - 3;
940 fp = vec + n;
941 frac = f - n;
942 a = fp[-1];
943 b = fp[0];
944 c = fp[1];
945 d = fp[2];
946 cminusb = c-b;
947 outlet_float(x->x_obj.ob_outlet, b + frac * (
948 cminusb - 0.1666667f * (1.-frac) * (
949 (d - a - 3.0f * cminusb) * frac + (d + 2.0f*a - 3.0f*b))));
953 static void tabread4_set(t_tabread4 *x, t_symbol *s)
955 x->x_arrayname = s;
958 static void *tabread4_new(t_symbol *s)
960 t_tabread4 *x = (t_tabread4 *)pd_new(tabread4_class);
961 x->x_arrayname = s;
962 outlet_new(&x->x_obj, &s_float);
963 return (x);
966 static void tabread4_setup(void)
968 tabread4_class = class_new(gensym("tabread4"), (t_newmethod)tabread4_new,
969 0, sizeof(t_tabread4), 0, A_DEFSYM, 0);
970 class_addfloat(tabread4_class, (t_method)tabread4_float);
971 class_addmethod(tabread4_class, (t_method)tabread4_set, gensym("set"),
972 A_SYMBOL, 0);
975 /* ------------------ tabwrite: control ------------------------ */
977 static t_class *tabwrite_class;
979 typedef struct _tabwrite
981 t_object x_obj;
982 t_symbol *x_arrayname;
983 t_clock *x_clock;
984 float x_ft1;
985 double x_updtime;
986 int x_set;
987 } t_tabwrite;
989 static void tabwrite_tick(t_tabwrite *x)
991 t_garray *a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class);
992 if (!a) bug("tabwrite_tick");
993 else garray_redraw(a);
994 x->x_set = 0;
995 x->x_updtime = clock_getsystime();
998 static void tabwrite_float(t_tabwrite *x, t_float f)
1000 int i, vecsize;
1001 t_garray *a;
1002 t_float *vec;
1004 if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class)))
1005 pd_error(x, "%s: no such array", x->x_arrayname->s_name);
1006 else if (!garray_getfloatarray(a, &vecsize, &vec))
1007 pd_error(x, "%s: bad template for tabwrite", x->x_arrayname->s_name);
1008 else
1010 int n = x->x_ft1;
1011 double timesince = clock_gettimesince(x->x_updtime);
1012 if (n < 0) n = 0;
1013 else if (n >= vecsize) n = vecsize-1;
1014 vec[n] = f;
1015 if (timesince > 1000)
1017 tabwrite_tick(x);
1019 else
1021 if (x->x_set == 0)
1023 clock_delay(x->x_clock, 1000 - timesince);
1024 x->x_set = 1;
1030 static void tabwrite_set(t_tabwrite *x, t_symbol *s)
1032 x->x_arrayname = s;
1035 static void tabwrite_free(t_tabwrite *x)
1037 clock_free(x->x_clock);
1040 static void *tabwrite_new(t_symbol *s)
1042 t_tabwrite *x = (t_tabwrite *)pd_new(tabwrite_class);
1043 x->x_ft1 = 0;
1044 x->x_arrayname = s;
1045 x->x_updtime = clock_getsystime();
1046 x->x_clock = clock_new(x, (t_method)tabwrite_tick);
1047 floatinlet_new(&x->x_obj, &x->x_ft1);
1048 return (x);
1051 void tabwrite_setup(void)
1053 tabwrite_class = class_new(gensym("tabwrite"), (t_newmethod)tabwrite_new,
1054 (t_method)tabwrite_free, sizeof(t_tabwrite), 0, A_DEFSYM, 0);
1055 class_addfloat(tabwrite_class, (t_method)tabwrite_float);
1056 class_addmethod(tabwrite_class, (t_method)tabwrite_set, gensym("set"), A_SYMBOL, 0);
1059 /* ------------------------ global setup routine ------------------------- */
1061 void d_array_setup(void)
1063 tabwrite_tilde_setup();
1064 tabplay_tilde_setup();
1065 tabread_tilde_setup();
1066 tabread4_tilde_setup();
1067 tabosc4_tilde_setup();
1068 tabsend_setup();
1069 tabreceive_setup();
1070 tabread_setup();
1071 tabread4_setup();
1072 tabwrite_setup();