Add FS #10214. Initial commit of the original PDa code for the GSoC Pure Data plugin...
[kugel-rb.git] / apps / plugins / pdbox / PDa / src / d_array.c
blob14ae464b0ba55dfd2a8a400d39d050f3d2a05343
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();
1075 /* Copyright (c) 1997-1999 Miller Puckette and others.
1076 * For information on usage and redistribution, and for a DISCLAIMER OF ALL
1077 * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
1079 /* sampling */
1081 /* LATER make tabread4 and tabread~ */
1083 #include "m_pd.h"
1086 /* ------------------------- tabwrite~ -------------------------- */
1088 static t_class *tabwrite_tilde_class;
1090 typedef struct _tabwrite_tilde
1092 t_object x_obj;
1093 int x_phase;
1094 int x_nsampsintab;
1095 float *x_vec;
1096 t_symbol *x_arrayname;
1097 t_clock *x_clock;
1098 float x_f;
1099 } t_tabwrite_tilde;
1101 static void tabwrite_tilde_tick(t_tabwrite_tilde *x);
1103 static void *tabwrite_tilde_new(t_symbol *s)
1105 t_tabwrite_tilde *x = (t_tabwrite_tilde *)pd_new(tabwrite_tilde_class);
1106 x->x_clock = clock_new(x, (t_method)tabwrite_tilde_tick);
1107 x->x_phase = 0x7fffffff;
1108 x->x_arrayname = s;
1109 x->x_f = 0;
1110 return (x);
1113 static t_int *tabwrite_tilde_perform(t_int *w)
1115 t_tabwrite_tilde *x = (t_tabwrite_tilde *)(w[1]);
1116 t_float *in = (t_float *)(w[2]);
1117 int n = (int)(w[3]), phase = x->x_phase, endphase = x->x_nsampsintab;
1118 if (!x->x_vec) goto bad;
1120 if (endphase > phase)
1122 int nxfer = endphase - phase;
1123 float *fp = x->x_vec + phase;
1124 if (nxfer > n) nxfer = n;
1125 phase += nxfer;
1126 while (nxfer--)
1128 float f = *in++;
1129 if (PD_BIGORSMALL(f))
1130 f = 0;
1131 *fp++ = f;
1133 if (phase >= endphase)
1135 clock_delay(x->x_clock, 0);
1136 phase = 0x7fffffff;
1138 x->x_phase = phase;
1140 bad:
1141 return (w+4);
1144 void tabwrite_tilde_set(t_tabwrite_tilde *x, t_symbol *s)
1146 t_garray *a;
1148 x->x_arrayname = s;
1149 if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class)))
1151 if (*s->s_name) pd_error(x, "tabwrite~: %s: no such array",
1152 x->x_arrayname->s_name);
1153 x->x_vec = 0;
1155 else if (!garray_getfloatarray(a, &x->x_nsampsintab, &x->x_vec))
1157 pd_error(x, "%s: bad template for tabwrite~", x->x_arrayname->s_name);
1158 x->x_vec = 0;
1160 else garray_usedindsp(a);
1163 static void tabwrite_tilde_dsp(t_tabwrite_tilde *x, t_signal **sp)
1165 tabwrite_tilde_set(x, x->x_arrayname);
1166 dsp_add(tabwrite_tilde_perform, 3, x, sp[0]->s_vec, sp[0]->s_n);
1169 static void tabwrite_tilde_bang(t_tabwrite_tilde *x)
1171 x->x_phase = 0;
1174 static void tabwrite_tilde_stop(t_tabwrite_tilde *x)
1176 if (x->x_phase != 0x7fffffff)
1178 tabwrite_tilde_tick(x);
1179 x->x_phase = 0x7fffffff;
1183 static void tabwrite_tilde_tick(t_tabwrite_tilde *x)
1185 t_garray *a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class);
1186 if (!a) bug("tabwrite_tilde_tick");
1187 else garray_redraw(a);
1190 static void tabwrite_tilde_free(t_tabwrite_tilde *x)
1192 clock_free(x->x_clock);
1195 static void tabwrite_tilde_setup(void)
1197 tabwrite_tilde_class = class_new(gensym("tabwrite~"),
1198 (t_newmethod)tabwrite_tilde_new, (t_method)tabwrite_tilde_free,
1199 sizeof(t_tabwrite_tilde), 0, A_DEFSYM, 0);
1200 CLASS_MAINSIGNALIN(tabwrite_tilde_class, t_tabwrite_tilde, x_f);
1201 class_addmethod(tabwrite_tilde_class, (t_method)tabwrite_tilde_dsp,
1202 gensym("dsp"), 0);
1203 class_addmethod(tabwrite_tilde_class, (t_method)tabwrite_tilde_set,
1204 gensym("set"), A_SYMBOL, 0);
1205 class_addmethod(tabwrite_tilde_class, (t_method)tabwrite_tilde_stop,
1206 gensym("stop"), 0);
1207 class_addbang(tabwrite_tilde_class, tabwrite_tilde_bang);
1210 /* ------------ tabplay~ - non-transposing sample playback --------------- */
1212 static t_class *tabplay_tilde_class;
1214 typedef struct _tabplay_tilde
1216 t_object x_obj;
1217 t_outlet *x_bangout;
1218 int x_phase;
1219 int x_nsampsintab;
1220 int x_limit;
1221 float *x_vec;
1222 t_symbol *x_arrayname;
1223 t_clock *x_clock;
1224 } t_tabplay_tilde;
1226 static void tabplay_tilde_tick(t_tabplay_tilde *x);
1228 static void *tabplay_tilde_new(t_symbol *s)
1230 t_tabplay_tilde *x = (t_tabplay_tilde *)pd_new(tabplay_tilde_class);
1231 x->x_clock = clock_new(x, (t_method)tabplay_tilde_tick);
1232 x->x_phase = 0x7fffffff;
1233 x->x_limit = 0;
1234 x->x_arrayname = s;
1235 outlet_new(&x->x_obj, &s_signal);
1236 x->x_bangout = outlet_new(&x->x_obj, &s_bang);
1237 return (x);
1240 static t_int *tabplay_tilde_perform(t_int *w)
1242 t_tabplay_tilde *x = (t_tabplay_tilde *)(w[1]);
1243 t_float *out = (t_float *)(w[2]), *fp;
1244 int n = (int)(w[3]), phase = x->x_phase,
1245 endphase = (x->x_nsampsintab < x->x_limit ?
1246 x->x_nsampsintab : x->x_limit), nxfer, n3;
1247 if (!x->x_vec || phase >= endphase)
1248 goto zero;
1250 nxfer = endphase - phase;
1251 fp = x->x_vec + phase;
1252 if (nxfer > n)
1253 nxfer = n;
1254 n3 = n - nxfer;
1255 phase += nxfer;
1256 while (nxfer--)
1257 *out++ = *fp++;
1258 if (phase >= endphase)
1260 clock_delay(x->x_clock, 0);
1261 x->x_phase = 0x7fffffff;
1262 while (n3--)
1263 *out++ = 0;
1265 else x->x_phase = phase;
1267 return (w+4);
1268 zero:
1269 while (n--) *out++ = 0;
1270 return (w+4);
1273 void tabplay_tilde_set(t_tabplay_tilde *x, t_symbol *s)
1275 t_garray *a;
1277 x->x_arrayname = s;
1278 if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class)))
1280 if (*s->s_name) pd_error(x, "tabplay~: %s: no such array",
1281 x->x_arrayname->s_name);
1282 x->x_vec = 0;
1284 else if (!garray_getfloatarray(a, &x->x_nsampsintab, &x->x_vec))
1286 pd_error(x, "%s: bad template for tabplay~", x->x_arrayname->s_name);
1287 x->x_vec = 0;
1289 else garray_usedindsp(a);
1292 static void tabplay_tilde_dsp(t_tabplay_tilde *x, t_signal **sp)
1294 tabplay_tilde_set(x, x->x_arrayname);
1295 dsp_add(tabplay_tilde_perform, 3, x, sp[0]->s_vec, sp[0]->s_n);
1298 static void tabplay_tilde_list(t_tabplay_tilde *x, t_symbol *s,
1299 int argc, t_atom *argv)
1301 long start = atom_getfloatarg(0, argc, argv);
1302 long length = atom_getfloatarg(1, argc, argv);
1303 if (start < 0) start = 0;
1304 if (length <= 0)
1305 x->x_limit = 0x7fffffff;
1306 else
1307 x->x_limit = start + length;
1308 x->x_phase = start;
1311 static void tabplay_tilde_stop(t_tabplay_tilde *x)
1313 x->x_phase = 0x7fffffff;
1316 static void tabplay_tilde_tick(t_tabplay_tilde *x)
1318 outlet_bang(x->x_bangout);
1321 static void tabplay_tilde_free(t_tabplay_tilde *x)
1323 clock_free(x->x_clock);
1326 static void tabplay_tilde_setup(void)
1328 tabplay_tilde_class = class_new(gensym("tabplay~"),
1329 (t_newmethod)tabplay_tilde_new, (t_method)tabplay_tilde_free,
1330 sizeof(t_tabplay_tilde), 0, A_DEFSYM, 0);
1331 class_addmethod(tabplay_tilde_class, (t_method)tabplay_tilde_dsp,
1332 gensym("dsp"), 0);
1333 class_addmethod(tabplay_tilde_class, (t_method)tabplay_tilde_stop,
1334 gensym("stop"), 0);
1335 class_addmethod(tabplay_tilde_class, (t_method)tabplay_tilde_set,
1336 gensym("set"), A_DEFSYM, 0);
1337 class_addlist(tabplay_tilde_class, tabplay_tilde_list);
1340 /******************** tabread~ ***********************/
1342 static t_class *tabread_tilde_class;
1344 typedef struct _tabread_tilde
1346 t_object x_obj;
1347 int x_npoints;
1348 float *x_vec;
1349 t_symbol *x_arrayname;
1350 float x_f;
1351 } t_tabread_tilde;
1353 static void *tabread_tilde_new(t_symbol *s)
1355 t_tabread_tilde *x = (t_tabread_tilde *)pd_new(tabread_tilde_class);
1356 x->x_arrayname = s;
1357 x->x_vec = 0;
1358 outlet_new(&x->x_obj, gensym("signal"));
1359 x->x_f = 0;
1360 return (x);
1363 static t_int *tabread_tilde_perform(t_int *w)
1365 t_tabread_tilde *x = (t_tabread_tilde *)(w[1]);
1366 t_float *in = (t_float *)(w[2]);
1367 t_float *out = (t_float *)(w[3]);
1368 int n = (int)(w[4]);
1369 int maxindex;
1370 float *buf = x->x_vec, *fp;
1371 int i;
1373 maxindex = x->x_npoints - 1;
1374 if (!buf) goto zero;
1376 for (i = 0; i < n; i++)
1378 int index = *in++;
1379 if (index < 0)
1380 index = 0;
1381 else if (index > maxindex)
1382 index = maxindex;
1383 *out++ = buf[index];
1385 return (w+5);
1386 zero:
1387 while (n--) *out++ = 0;
1389 return (w+5);
1392 void tabread_tilde_set(t_tabread_tilde *x, t_symbol *s)
1394 t_garray *a;
1396 x->x_arrayname = s;
1397 if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class)))
1399 if (*s->s_name)
1400 pd_error(x, "tabread~: %s: no such array", x->x_arrayname->s_name);
1401 x->x_vec = 0;
1403 else if (!garray_getfloatarray(a, &x->x_npoints, &x->x_vec))
1405 pd_error(x, "%s: bad template for tabread~", x->x_arrayname->s_name);
1406 x->x_vec = 0;
1408 else garray_usedindsp(a);
1411 static void tabread_tilde_dsp(t_tabread_tilde *x, t_signal **sp)
1413 tabread_tilde_set(x, x->x_arrayname);
1415 dsp_add(tabread_tilde_perform, 4, x,
1416 sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
1420 static void tabread_tilde_free(t_tabread_tilde *x)
1424 static void tabread_tilde_setup(void)
1426 tabread_tilde_class = class_new(gensym("tabread~"),
1427 (t_newmethod)tabread_tilde_new, (t_method)tabread_tilde_free,
1428 sizeof(t_tabread_tilde), 0, A_DEFSYM, 0);
1429 CLASS_MAINSIGNALIN(tabread_tilde_class, t_tabread_tilde, x_f);
1430 class_addmethod(tabread_tilde_class, (t_method)tabread_tilde_dsp,
1431 gensym("dsp"), 0);
1432 class_addmethod(tabread_tilde_class, (t_method)tabread_tilde_set,
1433 gensym("set"), A_SYMBOL, 0);
1436 /******************** tabread4~ ***********************/
1438 static t_class *tabread4_tilde_class;
1440 typedef struct _tabread4_tilde
1442 t_object x_obj;
1443 int x_npoints;
1444 float *x_vec;
1445 t_symbol *x_arrayname;
1446 float x_f;
1447 } t_tabread4_tilde;
1449 static void *tabread4_tilde_new(t_symbol *s)
1451 t_tabread4_tilde *x = (t_tabread4_tilde *)pd_new(tabread4_tilde_class);
1452 x->x_arrayname = s;
1453 x->x_vec = 0;
1454 outlet_new(&x->x_obj, gensym("signal"));
1455 x->x_f = 0;
1456 return (x);
1459 static t_int *tabread4_tilde_perform(t_int *w)
1461 t_tabread4_tilde *x = (t_tabread4_tilde *)(w[1]);
1462 t_float *in = (t_float *)(w[2]);
1463 t_float *out = (t_float *)(w[3]);
1464 int n = (int)(w[4]);
1465 int maxindex;
1466 float *buf = x->x_vec, *fp;
1467 int i;
1469 maxindex = x->x_npoints - 3;
1471 if (!buf) goto zero;
1473 #if 0 /* test for spam -- I'm not ready to deal with this */
1474 for (i = 0, xmax = 0, xmin = maxindex, fp = in1; i < n; i++, fp++)
1476 float f = *in1;
1477 if (f < xmin) xmin = f;
1478 else if (f > xmax) xmax = f;
1480 if (xmax < xmin + x->c_maxextent) xmax = xmin + x->c_maxextent;
1481 for (i = 0, splitlo = xmin+ x->c_maxextent, splithi = xmax - x->c_maxextent,
1482 fp = in1; i < n; i++, fp++)
1484 float f = *in1;
1485 if (f > splitlo && f < splithi) goto zero;
1487 #endif
1489 for (i = 0; i < n; i++)
1491 float findex = *in++;
1492 int index = findex;
1493 float frac, a, b, c, d, cminusb;
1494 static int count;
1495 if (index < 1)
1496 index = 1, frac = 0;
1497 else if (index > maxindex)
1498 index = maxindex, frac = 1;
1499 else frac = findex - index;
1500 fp = buf + index;
1501 a = fp[-1];
1502 b = fp[0];
1503 c = fp[1];
1504 d = fp[2];
1505 /* if (!i && !(count++ & 1023))
1506 post("fp = %lx, shit = %lx, b = %f", fp, buf->b_shit, b); */
1507 cminusb = c-b;
1508 *out++ = b + frac * (
1509 cminusb - 0.1666667f * (1.-frac) * (
1510 (d - a - 3.0f * cminusb) * frac + (d + 2.0f*a - 3.0f*b)
1514 return (w+5);
1515 zero:
1516 while (n--) *out++ = 0;
1518 return (w+5);
1521 void tabread4_tilde_set(t_tabread4_tilde *x, t_symbol *s)
1523 t_garray *a;
1525 x->x_arrayname = s;
1526 if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class)))
1528 if (*s->s_name)
1529 pd_error(x, "tabread4~: %s: no such array", x->x_arrayname->s_name);
1530 x->x_vec = 0;
1532 else if (!garray_getfloatarray(a, &x->x_npoints, &x->x_vec))
1534 pd_error(x, "%s: bad template for tabread4~", x->x_arrayname->s_name);
1535 x->x_vec = 0;
1537 else garray_usedindsp(a);
1540 static void tabread4_tilde_dsp(t_tabread4_tilde *x, t_signal **sp)
1542 tabread4_tilde_set(x, x->x_arrayname);
1544 dsp_add(tabread4_tilde_perform, 4, x,
1545 sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
1549 static void tabread4_tilde_free(t_tabread4_tilde *x)
1553 static void tabread4_tilde_setup(void)
1555 tabread4_tilde_class = class_new(gensym("tabread4~"),
1556 (t_newmethod)tabread4_tilde_new, (t_method)tabread4_tilde_free,
1557 sizeof(t_tabread4_tilde), 0, A_DEFSYM, 0);
1558 CLASS_MAINSIGNALIN(tabread4_tilde_class, t_tabread4_tilde, x_f);
1559 class_addmethod(tabread4_tilde_class, (t_method)tabread4_tilde_dsp,
1560 gensym("dsp"), 0);
1561 class_addmethod(tabread4_tilde_class, (t_method)tabread4_tilde_set,
1562 gensym("set"), A_SYMBOL, 0);
1565 /******************** tabosc4~ ***********************/
1567 /* this is all copied from d_osc.c... what include file could this go in? */
1568 #define UNITBIT32 1572864. /* 3*2^19; bit 32 has place value 1 */
1570 /* machine-dependent definitions. These ifdefs really
1571 should have been by CPU type and not by operating system! */
1572 #ifdef IRIX
1573 /* big-endian. Most significant byte is at low address in memory */
1574 #define HIOFFSET 0 /* word offset to find MSB */
1575 #define LOWOFFSET 1 /* word offset to find LSB */
1576 #define int32 long /* a data type that has 32 bits */
1577 #else
1578 #ifdef MSW
1579 /* little-endian; most significant byte is at highest address */
1580 #define HIOFFSET 1
1581 #define LOWOFFSET 0
1582 #define int32 long
1583 #else
1584 #ifdef __FreeBSD__
1585 #include <machine/endian.h>
1586 #if BYTE_ORDER == LITTLE_ENDIAN
1587 #define HIOFFSET 1
1588 #define LOWOFFSET 0
1589 #else
1590 #define HIOFFSET 0 /* word offset to find MSB */
1591 #define LOWOFFSET 1 /* word offset to find LSB */
1592 #endif /* BYTE_ORDER */
1593 #include <sys/types.h>
1594 #define int32 int32_t
1595 #endif
1597 #ifdef __linux__
1598 #include <endian.h>
1599 #if !defined(__BYTE_ORDER) || !defined(__LITTLE_ENDIAN)
1600 #error No byte order defined
1601 #endif
1603 #if __BYTE_ORDER == __LITTLE_ENDIAN
1604 #define HIOFFSET 1
1605 #define LOWOFFSET 0
1606 #else
1607 #define HIOFFSET 0 /* word offset to find MSB */
1608 #define LOWOFFSET 1 /* word offset to find LSB */
1609 #endif /* __BYTE_ORDER */
1611 #include <sys/types.h>
1612 #define int32 int32_t
1614 #else
1615 #ifdef MACOSX
1616 #define HIOFFSET 0 /* word offset to find MSB */
1617 #define LOWOFFSET 1 /* word offset to find LSB */
1618 #define int32 int /* a data type that has 32 bits */
1620 #endif /* MACOSX */
1621 #endif /* __linux__ */
1622 #endif /* MSW */
1623 #endif /* SGI */
1625 union tabfudge
1627 double tf_d;
1628 int32 tf_i[2];
1631 static t_class *tabosc4_tilde_class;
1633 typedef struct _tabosc4_tilde
1635 t_object x_obj;
1636 float x_fnpoints;
1637 float x_finvnpoints;
1638 float *x_vec;
1639 t_symbol *x_arrayname;
1640 float x_f;
1641 double x_phase;
1642 float x_conv;
1643 } t_tabosc4_tilde;
1645 static void *tabosc4_tilde_new(t_symbol *s)
1647 t_tabosc4_tilde *x = (t_tabosc4_tilde *)pd_new(tabosc4_tilde_class);
1648 x->x_arrayname = s;
1649 x->x_vec = 0;
1650 x->x_fnpoints = 512.;
1651 x->x_finvnpoints = (1./512.);
1652 outlet_new(&x->x_obj, gensym("signal"));
1653 inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("ft1"));
1654 x->x_f = 0;
1655 return (x);
1658 static t_int *tabosc4_tilde_perform(t_int *w)
1660 t_tabosc4_tilde *x = (t_tabosc4_tilde *)(w[1]);
1661 t_float *in = (t_float *)(w[2]);
1662 t_float *out = (t_float *)(w[3]);
1663 int n = (int)(w[4]);
1664 int normhipart;
1665 union tabfudge tf;
1666 float fnpoints = x->x_fnpoints;
1667 int mask = fnpoints - 1;
1668 float conv = fnpoints * x->x_conv;
1669 int maxindex;
1670 float *tab = x->x_vec, *addr;
1671 int i;
1672 double dphase = fnpoints * x->x_phase + UNITBIT32;
1674 if (!tab) goto zero;
1675 tf.tf_d = UNITBIT32;
1676 normhipart = tf.tf_i[HIOFFSET];
1678 #if 1
1679 while (n--)
1681 float frac, a, b, c, d, cminusb;
1682 tf.tf_d = dphase;
1683 dphase += *in++ * conv;
1684 addr = tab + (tf.tf_i[HIOFFSET] & mask);
1685 tf.tf_i[HIOFFSET] = normhipart;
1686 frac = tf.tf_d - UNITBIT32;
1687 a = addr[0];
1688 b = addr[1];
1689 c = addr[2];
1690 d = addr[3];
1691 cminusb = c-b;
1692 *out++ = b + frac * (
1693 cminusb - 0.1666667f * (1.-frac) * (
1694 (d - a - 3.0f * cminusb) * frac + (d + 2.0f*a - 3.0f*b)
1698 #endif
1700 tf.tf_d = UNITBIT32 * fnpoints;
1701 normhipart = tf.tf_i[HIOFFSET];
1702 tf.tf_d = dphase + (UNITBIT32 * fnpoints - UNITBIT32);
1703 tf.tf_i[HIOFFSET] = normhipart;
1704 x->x_phase = (tf.tf_d - UNITBIT32 * fnpoints) * x->x_finvnpoints;
1705 return (w+5);
1706 zero:
1707 while (n--) *out++ = 0;
1709 return (w+5);
1712 void tabosc4_tilde_set(t_tabosc4_tilde *x, t_symbol *s)
1714 t_garray *a;
1715 int npoints, pointsinarray;
1717 x->x_arrayname = s;
1718 if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class)))
1720 if (*s->s_name)
1721 pd_error(x, "tabosc4~: %s: no such array", x->x_arrayname->s_name);
1722 x->x_vec = 0;
1724 else if (!garray_getfloatarray(a, &pointsinarray, &x->x_vec))
1726 pd_error(x, "%s: bad template for tabosc4~", x->x_arrayname->s_name);
1727 x->x_vec = 0;
1729 else if ((npoints = pointsinarray - 3) != (1 << ilog2(pointsinarray - 3)))
1731 pd_error(x, "%s: number of points (%d) not a power of 2 plus three",
1732 x->x_arrayname->s_name, pointsinarray);
1733 x->x_vec = 0;
1734 garray_usedindsp(a);
1736 else
1738 x->x_fnpoints = npoints;
1739 x->x_finvnpoints = 1./npoints;
1740 garray_usedindsp(a);
1744 static void tabosc4_tilde_ft1(t_tabosc4_tilde *x, t_float f)
1746 x->x_phase = f;
1749 static void tabosc4_tilde_dsp(t_tabosc4_tilde *x, t_signal **sp)
1751 x->x_conv = 1. / sp[0]->s_sr;
1752 tabosc4_tilde_set(x, x->x_arrayname);
1754 dsp_add(tabosc4_tilde_perform, 4, x,
1755 sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
1758 static void tabosc4_tilde_setup(void)
1760 tabosc4_tilde_class = class_new(gensym("tabosc4~"),
1761 (t_newmethod)tabosc4_tilde_new, 0,
1762 sizeof(t_tabosc4_tilde), 0, A_DEFSYM, 0);
1763 CLASS_MAINSIGNALIN(tabosc4_tilde_class, t_tabosc4_tilde, x_f);
1764 class_addmethod(tabosc4_tilde_class, (t_method)tabosc4_tilde_dsp,
1765 gensym("dsp"), 0);
1766 class_addmethod(tabosc4_tilde_class, (t_method)tabosc4_tilde_set,
1767 gensym("set"), A_SYMBOL, 0);
1768 class_addmethod(tabosc4_tilde_class, (t_method)tabosc4_tilde_ft1,
1769 gensym("ft1"), A_FLOAT, 0);
1772 /* ------------------------ tabsend~ ------------------------- */
1774 static t_class *tabsend_class;
1776 typedef struct _tabsend
1778 t_object x_obj;
1779 float *x_vec;
1780 int x_graphperiod;
1781 int x_graphcount;
1782 t_symbol *x_arrayname;
1783 t_clock *x_clock;
1784 float x_f;
1785 } t_tabsend;
1787 static void tabsend_tick(t_tabsend *x);
1789 static void *tabsend_new(t_symbol *s)
1791 t_tabsend *x = (t_tabsend *)pd_new(tabsend_class);
1792 x->x_graphcount = 0;
1793 x->x_arrayname = s;
1794 x->x_clock = clock_new(x, (t_method)tabsend_tick);
1795 x->x_f = 0;
1796 return (x);
1799 static t_int *tabsend_perform(t_int *w)
1801 t_tabsend *x = (t_tabsend *)(w[1]);
1802 t_float *in = (t_float *)(w[2]);
1803 int n = w[3];
1804 t_float *dest = x->x_vec;
1805 int i = x->x_graphcount;
1806 if (!x->x_vec) goto bad;
1808 while (n--)
1810 float f = *in++;
1811 if (PD_BIGORSMALL(f))
1812 f = 0;
1813 *dest++ = f;
1815 if (!i--)
1817 clock_delay(x->x_clock, 0);
1818 i = x->x_graphperiod;
1820 x->x_graphcount = i;
1821 bad:
1822 return (w+4);
1825 static void tabsend_dsp(t_tabsend *x, t_signal **sp)
1827 int i, vecsize;
1828 t_garray *a;
1830 if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class)))
1832 if (*x->x_arrayname->s_name)
1833 pd_error(x, "tabsend~: %s: no such array", x->x_arrayname->s_name);
1835 else if (!garray_getfloatarray(a, &vecsize, &x->x_vec))
1836 pd_error(x, "%s: bad template for tabsend~", x->x_arrayname->s_name);
1837 else
1839 int n = sp[0]->s_n;
1840 int ticksper = sp[0]->s_sr/n;
1841 if (ticksper < 1) ticksper = 1;
1842 x->x_graphperiod = ticksper;
1843 if (x->x_graphcount > ticksper) x->x_graphcount = ticksper;
1844 if (n < vecsize) vecsize = n;
1845 garray_usedindsp(a);
1846 dsp_add(tabsend_perform, 3, x, sp[0]->s_vec, vecsize);
1850 static void tabsend_tick(t_tabsend *x)
1852 t_garray *a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class);
1853 if (!a) bug("tabsend_tick");
1854 else garray_redraw(a);
1857 static void tabsend_free(t_tabsend *x)
1859 clock_free(x->x_clock);
1862 static void tabsend_setup(void)
1864 tabsend_class = class_new(gensym("tabsend~"), (t_newmethod)tabsend_new,
1865 (t_method)tabsend_free, sizeof(t_tabsend), 0, A_DEFSYM, 0);
1866 CLASS_MAINSIGNALIN(tabsend_class, t_tabsend, x_f);
1867 class_addmethod(tabsend_class, (t_method)tabsend_dsp, gensym("dsp"), 0);
1870 /* ------------------------ tabreceive~ ------------------------- */
1872 static t_class *tabreceive_class;
1874 typedef struct _tabreceive
1876 t_object x_obj;
1877 float *x_vec;
1878 t_symbol *x_arrayname;
1879 } t_tabreceive;
1881 static t_int *tabreceive_perform(t_int *w)
1883 t_tabreceive *x = (t_tabreceive *)(w[1]);
1884 t_float *out = (t_float *)(w[2]);
1885 int n = w[3];
1886 t_float *from = x->x_vec;
1887 if (from) while (n--) *out++ = *from++;
1888 else while (n--) *out++ = 0;
1889 return (w+4);
1892 static void tabreceive_dsp(t_tabreceive *x, t_signal **sp)
1894 t_garray *a;
1895 int vecsize;
1897 if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class)))
1899 if (*x->x_arrayname->s_name)
1900 pd_error(x, "tabsend~: %s: no such array", x->x_arrayname->s_name);
1902 else if (!garray_getfloatarray(a, &vecsize, &x->x_vec))
1903 pd_error(x, "%s: bad template for tabreceive~", x->x_arrayname->s_name);
1904 else
1906 int n = sp[0]->s_n;
1907 if (n < vecsize) vecsize = n;
1908 garray_usedindsp(a);
1909 dsp_add(tabreceive_perform, 3, x, sp[0]->s_vec, vecsize);
1913 static void *tabreceive_new(t_symbol *s)
1915 t_tabreceive *x = (t_tabreceive *)pd_new(tabreceive_class);
1916 x->x_arrayname = s;
1917 outlet_new(&x->x_obj, &s_signal);
1918 return (x);
1921 static void tabreceive_setup(void)
1923 tabreceive_class = class_new(gensym("tabreceive~"),
1924 (t_newmethod)tabreceive_new, 0,
1925 sizeof(t_tabreceive), 0, A_DEFSYM, 0);
1926 class_addmethod(tabreceive_class, (t_method)tabreceive_dsp,
1927 gensym("dsp"), 0);
1931 /* ---------- tabread: control, non-interpolating ------------------------ */
1933 static t_class *tabread_class;
1935 typedef struct _tabread
1937 t_object x_obj;
1938 t_symbol *x_arrayname;
1939 } t_tabread;
1941 static void tabread_float(t_tabread *x, t_float f)
1943 t_garray *a;
1944 int npoints;
1945 t_float *vec;
1947 if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class)))
1948 pd_error(x, "%s: no such array", x->x_arrayname->s_name);
1949 else if (!garray_getfloatarray(a, &npoints, &vec))
1950 pd_error(x, "%s: bad template for tabread", x->x_arrayname->s_name);
1951 else
1953 int n = f;
1954 if (n < 0) n = 0;
1955 else if (n >= npoints) n = npoints - 1;
1956 outlet_float(x->x_obj.ob_outlet, (npoints ? vec[n] : 0));
1960 static void tabread_set(t_tabread *x, t_symbol *s)
1962 x->x_arrayname = s;
1965 static void *tabread_new(t_symbol *s)
1967 t_tabread *x = (t_tabread *)pd_new(tabread_class);
1968 x->x_arrayname = s;
1969 outlet_new(&x->x_obj, &s_float);
1970 return (x);
1973 static void tabread_setup(void)
1975 tabread_class = class_new(gensym("tabread"), (t_newmethod)tabread_new,
1976 0, sizeof(t_tabread), 0, A_DEFSYM, 0);
1977 class_addfloat(tabread_class, (t_method)tabread_float);
1978 class_addmethod(tabread_class, (t_method)tabread_set, gensym("set"),
1979 A_SYMBOL, 0);
1982 /* ---------- tabread4: control, non-interpolating ------------------------ */
1984 static t_class *tabread4_class;
1986 typedef struct _tabread4
1988 t_object x_obj;
1989 t_symbol *x_arrayname;
1990 } t_tabread4;
1992 static void tabread4_float(t_tabread4 *x, t_float f)
1994 t_garray *a;
1995 int npoints;
1996 t_float *vec;
1998 if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class)))
1999 pd_error(x, "%s: no such array", x->x_arrayname->s_name);
2000 else if (!garray_getfloatarray(a, &npoints, &vec))
2001 pd_error(x, "%s: bad template for tabread4", x->x_arrayname->s_name);
2002 else if (npoints < 4)
2003 outlet_float(x->x_obj.ob_outlet, 0);
2004 else if (f <= 1)
2005 outlet_float(x->x_obj.ob_outlet, vec[1]);
2006 else if (f >= npoints - 2)
2007 outlet_float(x->x_obj.ob_outlet, vec[npoints - 2]);
2008 else
2010 int n = f;
2011 float a, b, c, d, cminusb, frac, *fp;
2012 if (n >= npoints - 2)
2013 n = npoints - 3;
2014 fp = vec + n;
2015 frac = f - n;
2016 a = fp[-1];
2017 b = fp[0];
2018 c = fp[1];
2019 d = fp[2];
2020 cminusb = c-b;
2021 outlet_float(x->x_obj.ob_outlet, b + frac * (
2022 cminusb - 0.1666667f * (1.-frac) * (
2023 (d - a - 3.0f * cminusb) * frac + (d + 2.0f*a - 3.0f*b))));
2027 static void tabread4_set(t_tabread4 *x, t_symbol *s)
2029 x->x_arrayname = s;
2032 static void *tabread4_new(t_symbol *s)
2034 t_tabread4 *x = (t_tabread4 *)pd_new(tabread4_class);
2035 x->x_arrayname = s;
2036 outlet_new(&x->x_obj, &s_float);
2037 return (x);
2040 static void tabread4_setup(void)
2042 tabread4_class = class_new(gensym("tabread4"), (t_newmethod)tabread4_new,
2043 0, sizeof(t_tabread4), 0, A_DEFSYM, 0);
2044 class_addfloat(tabread4_class, (t_method)tabread4_float);
2045 class_addmethod(tabread4_class, (t_method)tabread4_set, gensym("set"),
2046 A_SYMBOL, 0);
2049 /* ------------------ tabwrite: control ------------------------ */
2051 static t_class *tabwrite_class;
2053 typedef struct _tabwrite
2055 t_object x_obj;
2056 t_symbol *x_arrayname;
2057 t_clock *x_clock;
2058 float x_ft1;
2059 double x_updtime;
2060 int x_set;
2061 } t_tabwrite;
2063 static void tabwrite_tick(t_tabwrite *x)
2065 t_garray *a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class);
2066 if (!a) bug("tabwrite_tick");
2067 else garray_redraw(a);
2068 x->x_set = 0;
2069 x->x_updtime = clock_getsystime();
2072 static void tabwrite_float(t_tabwrite *x, t_float f)
2074 int i, vecsize;
2075 t_garray *a;
2076 t_float *vec;
2078 if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class)))
2079 pd_error(x, "%s: no such array", x->x_arrayname->s_name);
2080 else if (!garray_getfloatarray(a, &vecsize, &vec))
2081 pd_error(x, "%s: bad template for tabwrite", x->x_arrayname->s_name);
2082 else
2084 int n = x->x_ft1;
2085 double timesince = clock_gettimesince(x->x_updtime);
2086 if (n < 0) n = 0;
2087 else if (n >= vecsize) n = vecsize-1;
2088 vec[n] = f;
2089 if (timesince > 1000)
2091 tabwrite_tick(x);
2093 else
2095 if (x->x_set == 0)
2097 clock_delay(x->x_clock, 1000 - timesince);
2098 x->x_set = 1;
2104 static void tabwrite_set(t_tabwrite *x, t_symbol *s)
2106 x->x_arrayname = s;
2109 static void tabwrite_free(t_tabwrite *x)
2111 clock_free(x->x_clock);
2114 static void *tabwrite_new(t_symbol *s)
2116 t_tabwrite *x = (t_tabwrite *)pd_new(tabwrite_class);
2117 x->x_ft1 = 0;
2118 x->x_arrayname = s;
2119 x->x_updtime = clock_getsystime();
2120 x->x_clock = clock_new(x, (t_method)tabwrite_tick);
2121 floatinlet_new(&x->x_obj, &x->x_ft1);
2122 return (x);
2125 void tabwrite_setup(void)
2127 tabwrite_class = class_new(gensym("tabwrite"), (t_newmethod)tabwrite_new,
2128 (t_method)tabwrite_free, sizeof(t_tabwrite), 0, A_DEFSYM, 0);
2129 class_addfloat(tabwrite_class, (t_method)tabwrite_float);
2130 class_addmethod(tabwrite_class, (t_method)tabwrite_set, gensym("set"), A_SYMBOL, 0);
2133 /* ------------------------ global setup routine ------------------------- */
2135 void d_array_setup(void)
2137 tabwrite_tilde_setup();
2138 tabplay_tilde_setup();
2139 tabread_tilde_setup();
2140 tabread4_tilde_setup();
2141 tabosc4_tilde_setup();
2142 tabsend_setup();
2143 tabreceive_setup();
2144 tabread_setup();
2145 tabread4_setup();
2146 tabwrite_setup();