summaryrefslogtreecommitdiff
path: root/apps/plugins/pdbox/PDa/src/d_array.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/pdbox/PDa/src/d_array.c')
-rw-r--r--apps/plugins/pdbox/PDa/src/d_array.c2148
1 files changed, 2148 insertions, 0 deletions
diff --git a/apps/plugins/pdbox/PDa/src/d_array.c b/apps/plugins/pdbox/PDa/src/d_array.c
new file mode 100644
index 0000000000..14ae464b0b
--- /dev/null
+++ b/apps/plugins/pdbox/PDa/src/d_array.c
@@ -0,0 +1,2148 @@
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. */
4
5/* sampling */
6
7/* LATER make tabread4 and tabread~ */
8
9#include "m_pd.h"
10
11
12/* ------------------------- tabwrite~ -------------------------- */
13
14static t_class *tabwrite_tilde_class;
15
16typedef struct _tabwrite_tilde
17{
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;
26
27static void tabwrite_tilde_tick(t_tabwrite_tilde *x);
28
29static void *tabwrite_tilde_new(t_symbol *s)
30{
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);
37}
38
39static t_int *tabwrite_tilde_perform(t_int *w)
40{
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;
45
46 if (endphase > phase)
47 {
48 int nxfer = endphase - phase;
49 float *fp = x->x_vec + phase;
50 if (nxfer > n) nxfer = n;
51 phase += nxfer;
52 while (nxfer--)
53 {
54 float f = *in++;
55 if (PD_BIGORSMALL(f))
56 f = 0;
57 *fp++ = f;
58 }
59 if (phase >= endphase)
60 {
61 clock_delay(x->x_clock, 0);
62 phase = 0x7fffffff;
63 }
64 x->x_phase = phase;
65 }
66bad:
67 return (w+4);
68}
69
70void tabwrite_tilde_set(t_tabwrite_tilde *x, t_symbol *s)
71{
72 t_garray *a;
73
74 x->x_arrayname = s;
75 if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class)))
76 {
77 if (*s->s_name) pd_error(x, "tabwrite~: %s: no such array",
78 x->x_arrayname->s_name);
79 x->x_vec = 0;
80 }
81 else if (!garray_getfloatarray(a, &x->x_nsampsintab, &x->x_vec))
82 {
83 pd_error(x, "%s: bad template for tabwrite~", x->x_arrayname->s_name);
84 x->x_vec = 0;
85 }
86 else garray_usedindsp(a);
87}
88
89static void tabwrite_tilde_dsp(t_tabwrite_tilde *x, t_signal **sp)
90{
91 tabwrite_tilde_set(x, x->x_arrayname);
92 dsp_add(tabwrite_tilde_perform, 3, x, sp[0]->s_vec, sp[0]->s_n);
93}
94
95static void tabwrite_tilde_bang(t_tabwrite_tilde *x)
96{
97 x->x_phase = 0;
98}
99
100static void tabwrite_tilde_stop(t_tabwrite_tilde *x)
101{
102 if (x->x_phase != 0x7fffffff)
103 {
104 tabwrite_tilde_tick(x);
105 x->x_phase = 0x7fffffff;
106 }
107}
108
109static void tabwrite_tilde_tick(t_tabwrite_tilde *x)
110{
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);
114}
115
116static void tabwrite_tilde_free(t_tabwrite_tilde *x)
117{
118 clock_free(x->x_clock);
119}
120
121static void tabwrite_tilde_setup(void)
122{
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);
134}
135
136/* ------------ tabplay~ - non-transposing sample playback --------------- */
137
138static t_class *tabplay_tilde_class;
139
140typedef struct _tabplay_tilde
141{
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;
151
152static void tabplay_tilde_tick(t_tabplay_tilde *x);
153
154static void *tabplay_tilde_new(t_symbol *s)
155{
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);
164}
165
166static t_int *tabplay_tilde_perform(t_int *w)
167{
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;
175
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)
185 {
186 clock_delay(x->x_clock, 0);
187 x->x_phase = 0x7fffffff;
188 while (n3--)
189 *out++ = 0;
190 }
191 else x->x_phase = phase;
192
193 return (w+4);
194zero:
195 while (n--) *out++ = 0;
196 return (w+4);
197}
198
199void tabplay_tilde_set(t_tabplay_tilde *x, t_symbol *s)
200{
201 t_garray *a;
202
203 x->x_arrayname = s;
204 if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class)))
205 {
206 if (*s->s_name) pd_error(x, "tabplay~: %s: no such array",
207 x->x_arrayname->s_name);
208 x->x_vec = 0;
209 }
210 else if (!garray_getfloatarray(a, &x->x_nsampsintab, &x->x_vec))
211 {
212 pd_error(x, "%s: bad template for tabplay~", x->x_arrayname->s_name);
213 x->x_vec = 0;
214 }
215 else garray_usedindsp(a);
216}
217
218static void tabplay_tilde_dsp(t_tabplay_tilde *x, t_signal **sp)
219{
220 tabplay_tilde_set(x, x->x_arrayname);
221 dsp_add(tabplay_tilde_perform, 3, x, sp[0]->s_vec, sp[0]->s_n);
222}
223
224static void tabplay_tilde_list(t_tabplay_tilde *x, t_symbol *s,
225 int argc, t_atom *argv)
226{
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;
235}
236
237static void tabplay_tilde_stop(t_tabplay_tilde *x)
238{
239 x->x_phase = 0x7fffffff;
240}
241
242static void tabplay_tilde_tick(t_tabplay_tilde *x)
243{
244 outlet_bang(x->x_bangout);
245}
246
247static void tabplay_tilde_free(t_tabplay_tilde *x)
248{
249 clock_free(x->x_clock);
250}
251
252static void tabplay_tilde_setup(void)
253{
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);
264}
265
266/******************** tabread~ ***********************/
267
268static t_class *tabread_tilde_class;
269
270typedef struct _tabread_tilde
271{
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;
278
279static void *tabread_tilde_new(t_symbol *s)
280{
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);
287}
288
289static t_int *tabread_tilde_perform(t_int *w)
290{
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;
298
299 maxindex = x->x_npoints - 1;
300 if (!buf) goto zero;
301
302 for (i = 0; i < n; i++)
303 {
304 int index = *in++;
305 if (index < 0)
306 index = 0;
307 else if (index > maxindex)
308 index = maxindex;
309 *out++ = buf[index];
310 }
311 return (w+5);
312 zero:
313 while (n--) *out++ = 0;
314
315 return (w+5);
316}
317
318void tabread_tilde_set(t_tabread_tilde *x, t_symbol *s)
319{
320 t_garray *a;
321
322 x->x_arrayname = s;
323 if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class)))
324 {
325 if (*s->s_name)
326 pd_error(x, "tabread~: %s: no such array", x->x_arrayname->s_name);
327 x->x_vec = 0;
328 }
329 else if (!garray_getfloatarray(a, &x->x_npoints, &x->x_vec))
330 {
331 pd_error(x, "%s: bad template for tabread~", x->x_arrayname->s_name);
332 x->x_vec = 0;
333 }
334 else garray_usedindsp(a);
335}
336
337static void tabread_tilde_dsp(t_tabread_tilde *x, t_signal **sp)
338{
339 tabread_tilde_set(x, x->x_arrayname);
340
341 dsp_add(tabread_tilde_perform, 4, x,
342 sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
343
344}
345
346static void tabread_tilde_free(t_tabread_tilde *x)
347{
348}
349
350static void tabread_tilde_setup(void)
351{
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);
360}
361
362/******************** tabread4~ ***********************/
363
364static t_class *tabread4_tilde_class;
365
366typedef struct _tabread4_tilde
367{
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;
374
375static void *tabread4_tilde_new(t_symbol *s)
376{
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);
383}
384
385static t_int *tabread4_tilde_perform(t_int *w)
386{
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;
394
395 maxindex = x->x_npoints - 3;
396
397 if (!buf) goto zero;
398
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++)
401 {
402 float f = *in1;
403 if (f < xmin) xmin = f;
404 else if (f > xmax) xmax = f;
405 }
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++)
409 {
410 float f = *in1;
411 if (f > splitlo && f < splithi) goto zero;
412 }
413#endif
414
415 for (i = 0; i < n; i++)
416 {
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)
437 )
438 );
439 }
440 return (w+5);
441 zero:
442 while (n--) *out++ = 0;
443
444 return (w+5);
445}
446
447void tabread4_tilde_set(t_tabread4_tilde *x, t_symbol *s)
448{
449 t_garray *a;
450
451 x->x_arrayname = s;
452 if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class)))
453 {
454 if (*s->s_name)
455 pd_error(x, "tabread4~: %s: no such array", x->x_arrayname->s_name);
456 x->x_vec = 0;
457 }
458 else if (!garray_getfloatarray(a, &x->x_npoints, &x->x_vec))
459 {
460 pd_error(x, "%s: bad template for tabread4~", x->x_arrayname->s_name);
461 x->x_vec = 0;
462 }
463 else garray_usedindsp(a);
464}
465
466static void tabread4_tilde_dsp(t_tabread4_tilde *x, t_signal **sp)
467{
468 tabread4_tilde_set(x, x->x_arrayname);
469
470 dsp_add(tabread4_tilde_perform, 4, x,
471 sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
472
473}
474
475static void tabread4_tilde_free(t_tabread4_tilde *x)
476{
477}
478
479static void tabread4_tilde_setup(void)
480{
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);
489}
490
491/******************** tabosc4~ ***********************/
492
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 */
495
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
522
523#ifdef __linux__
524#include <endian.h>
525#if !defined(__BYTE_ORDER) || !defined(__LITTLE_ENDIAN)
526#error No byte order defined
527#endif
528
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 */
536
537#include <sys/types.h>
538#define int32 int32_t
539
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 */
545
546#endif /* MACOSX */
547#endif /* __linux__ */
548#endif /* MSW */
549#endif /* SGI */
550
551union tabfudge
552{
553 double tf_d;
554 int32 tf_i[2];
555};
556
557static t_class *tabosc4_tilde_class;
558
559typedef struct _tabosc4_tilde
560{
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;
570
571static void *tabosc4_tilde_new(t_symbol *s)
572{
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);
582}
583
584static t_int *tabosc4_tilde_perform(t_int *w)
585{
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;
599
600 if (!tab) goto zero;
601 tf.tf_d = UNITBIT32;
602 normhipart = tf.tf_i[HIOFFSET];
603
604#if 1
605 while (n--)
606 {
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)
621 )
622 );
623 }
624#endif
625
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;
634
635 return (w+5);
636}
637
638void tabosc4_tilde_set(t_tabosc4_tilde *x, t_symbol *s)
639{
640 t_garray *a;
641 int npoints, pointsinarray;
642
643 x->x_arrayname = s;
644 if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class)))
645 {
646 if (*s->s_name)
647 pd_error(x, "tabosc4~: %s: no such array", x->x_arrayname->s_name);
648 x->x_vec = 0;
649 }
650 else if (!garray_getfloatarray(a, &pointsinarray, &x->x_vec))
651 {
652 pd_error(x, "%s: bad template for tabosc4~", x->x_arrayname->s_name);
653 x->x_vec = 0;
654 }
655 else if ((npoints = pointsinarray - 3) != (1 << ilog2(pointsinarray - 3)))
656 {
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);
661 }
662 else
663 {
664 x->x_fnpoints = npoints;
665 x->x_finvnpoints = 1./npoints;
666 garray_usedindsp(a);
667 }
668}
669
670static void tabosc4_tilde_ft1(t_tabosc4_tilde *x, t_float f)
671{
672 x->x_phase = f;
673}
674
675static void tabosc4_tilde_dsp(t_tabosc4_tilde *x, t_signal **sp)
676{
677 x->x_conv = 1. / sp[0]->s_sr;
678 tabosc4_tilde_set(x, x->x_arrayname);
679
680 dsp_add(tabosc4_tilde_perform, 4, x,
681 sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
682}
683
684static void tabosc4_tilde_setup(void)
685{
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);
696}
697
698/* ------------------------ tabsend~ ------------------------- */
699
700static t_class *tabsend_class;
701
702typedef struct _tabsend
703{
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;
712
713static void tabsend_tick(t_tabsend *x);
714
715static void *tabsend_new(t_symbol *s)
716{
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);
723}
724
725static t_int *tabsend_perform(t_int *w)
726{
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;
733
734 while (n--)
735 {
736 float f = *in++;
737 if (PD_BIGORSMALL(f))
738 f = 0;
739 *dest++ = f;
740 }
741 if (!i--)
742 {
743 clock_delay(x->x_clock, 0);
744 i = x->x_graphperiod;
745 }
746 x->x_graphcount = i;
747bad:
748 return (w+4);
749}
750
751static void tabsend_dsp(t_tabsend *x, t_signal **sp)
752{
753 int i, vecsize;
754 t_garray *a;
755
756 if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class)))
757 {
758 if (*x->x_arrayname->s_name)
759 pd_error(x, "tabsend~: %s: no such array", x->x_arrayname->s_name);
760 }
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
764 {
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);
773 }
774}
775
776static void tabsend_tick(t_tabsend *x)
777{
778 t_garray *a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class);
779 if (!a) bug("tabsend_tick");
780 else garray_redraw(a);
781}
782
783static void tabsend_free(t_tabsend *x)
784{
785 clock_free(x->x_clock);
786}
787
788static void tabsend_setup(void)
789{
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);
794}
795
796/* ------------------------ tabreceive~ ------------------------- */
797
798static t_class *tabreceive_class;
799
800typedef struct _tabreceive
801{
802 t_object x_obj;
803 float *x_vec;
804 t_symbol *x_arrayname;
805} t_tabreceive;
806
807static t_int *tabreceive_perform(t_int *w)
808{
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);
816}
817
818static void tabreceive_dsp(t_tabreceive *x, t_signal **sp)
819{
820 t_garray *a;
821 int vecsize;
822
823 if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class)))
824 {
825 if (*x->x_arrayname->s_name)
826 pd_error(x, "tabsend~: %s: no such array", x->x_arrayname->s_name);
827 }
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
831 {
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);
836 }
837}
838
839static void *tabreceive_new(t_symbol *s)
840{
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);
845}
846
847static void tabreceive_setup(void)
848{
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);
854}
855
856
857/* ---------- tabread: control, non-interpolating ------------------------ */
858
859static t_class *tabread_class;
860
861typedef struct _tabread
862{
863 t_object x_obj;
864 t_symbol *x_arrayname;
865} t_tabread;
866
867static void tabread_float(t_tabread *x, t_float f)
868{
869 t_garray *a;
870 int npoints;
871 t_float *vec;
872
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
878 {
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));
883 }
884}
885
886static void tabread_set(t_tabread *x, t_symbol *s)
887{
888 x->x_arrayname = s;
889}
890
891static void *tabread_new(t_symbol *s)
892{
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);
897}
898
899static void tabread_setup(void)
900{
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);
906}
907
908/* ---------- tabread4: control, non-interpolating ------------------------ */
909
910static t_class *tabread4_class;
911
912typedef struct _tabread4
913{
914 t_object x_obj;
915 t_symbol *x_arrayname;
916} t_tabread4;
917
918static void tabread4_float(t_tabread4 *x, t_float f)
919{
920 t_garray *a;
921 int npoints;
922 t_float *vec;
923
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
935 {
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))));
950 }
951}
952
953static void tabread4_set(t_tabread4 *x, t_symbol *s)
954{
955 x->x_arrayname = s;
956}
957
958static void *tabread4_new(t_symbol *s)
959{
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);
964}
965
966static void tabread4_setup(void)
967{
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);
973}
974
975/* ------------------ tabwrite: control ------------------------ */
976
977static t_class *tabwrite_class;
978
979typedef struct _tabwrite
980{
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;
988
989static void tabwrite_tick(t_tabwrite *x)
990{
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();
996}
997
998static void tabwrite_float(t_tabwrite *x, t_float f)
999{
1000 int i, vecsize;
1001 t_garray *a;
1002 t_float *vec;
1003
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
1009 {
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)
1016 {
1017 tabwrite_tick(x);
1018 }
1019 else
1020 {
1021 if (x->x_set == 0)
1022 {
1023 clock_delay(x->x_clock, 1000 - timesince);
1024 x->x_set = 1;
1025 }
1026 }
1027 }
1028}
1029
1030static void tabwrite_set(t_tabwrite *x, t_symbol *s)
1031{
1032 x->x_arrayname = s;
1033}
1034
1035static void tabwrite_free(t_tabwrite *x)
1036{
1037 clock_free(x->x_clock);
1038}
1039
1040static void *tabwrite_new(t_symbol *s)
1041{
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);
1049}
1050
1051void tabwrite_setup(void)
1052{
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);
1057}
1058
1059/* ------------------------ global setup routine ------------------------- */
1060
1061void d_array_setup(void)
1062{
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();
1073}
1074
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. */
1078
1079/* sampling */
1080
1081/* LATER make tabread4 and tabread~ */
1082
1083#include "m_pd.h"
1084
1085
1086/* ------------------------- tabwrite~ -------------------------- */
1087
1088static t_class *tabwrite_tilde_class;
1089
1090typedef struct _tabwrite_tilde
1091{
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;
1100
1101static void tabwrite_tilde_tick(t_tabwrite_tilde *x);
1102
1103static void *tabwrite_tilde_new(t_symbol *s)
1104{
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);
1111}
1112
1113static t_int *tabwrite_tilde_perform(t_int *w)
1114{
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;
1119
1120 if (endphase > phase)
1121 {
1122 int nxfer = endphase - phase;
1123 float *fp = x->x_vec + phase;
1124 if (nxfer > n) nxfer = n;
1125 phase += nxfer;
1126 while (nxfer--)
1127 {
1128 float f = *in++;
1129 if (PD_BIGORSMALL(f))
1130 f = 0;
1131 *fp++ = f;
1132 }
1133 if (phase >= endphase)
1134 {
1135 clock_delay(x->x_clock, 0);
1136 phase = 0x7fffffff;
1137 }
1138 x->x_phase = phase;
1139 }
1140bad:
1141 return (w+4);
1142}
1143
1144void tabwrite_tilde_set(t_tabwrite_tilde *x, t_symbol *s)
1145{
1146 t_garray *a;
1147
1148 x->x_arrayname = s;
1149 if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class)))
1150 {
1151 if (*s->s_name) pd_error(x, "tabwrite~: %s: no such array",
1152 x->x_arrayname->s_name);
1153 x->x_vec = 0;
1154 }
1155 else if (!garray_getfloatarray(a, &x->x_nsampsintab, &x->x_vec))
1156 {
1157 pd_error(x, "%s: bad template for tabwrite~", x->x_arrayname->s_name);
1158 x->x_vec = 0;
1159 }
1160 else garray_usedindsp(a);
1161}
1162
1163static void tabwrite_tilde_dsp(t_tabwrite_tilde *x, t_signal **sp)
1164{
1165 tabwrite_tilde_set(x, x->x_arrayname);
1166 dsp_add(tabwrite_tilde_perform, 3, x, sp[0]->s_vec, sp[0]->s_n);
1167}
1168
1169static void tabwrite_tilde_bang(t_tabwrite_tilde *x)
1170{
1171 x->x_phase = 0;
1172}
1173
1174static void tabwrite_tilde_stop(t_tabwrite_tilde *x)
1175{
1176 if (x->x_phase != 0x7fffffff)
1177 {
1178 tabwrite_tilde_tick(x);
1179 x->x_phase = 0x7fffffff;
1180 }
1181}
1182
1183static void tabwrite_tilde_tick(t_tabwrite_tilde *x)
1184{
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);
1188}
1189
1190static void tabwrite_tilde_free(t_tabwrite_tilde *x)
1191{
1192 clock_free(x->x_clock);
1193}
1194
1195static void tabwrite_tilde_setup(void)
1196{
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);
1208}
1209
1210/* ------------ tabplay~ - non-transposing sample playback --------------- */
1211
1212static t_class *tabplay_tilde_class;
1213
1214typedef struct _tabplay_tilde
1215{
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;
1225
1226static void tabplay_tilde_tick(t_tabplay_tilde *x);
1227
1228static void *tabplay_tilde_new(t_symbol *s)
1229{
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);
1238}
1239
1240static t_int *tabplay_tilde_perform(t_int *w)
1241{
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;
1249
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)
1259 {
1260 clock_delay(x->x_clock, 0);
1261 x->x_phase = 0x7fffffff;
1262 while (n3--)
1263 *out++ = 0;
1264 }
1265 else x->x_phase = phase;
1266
1267 return (w+4);
1268zero:
1269 while (n--) *out++ = 0;
1270 return (w+4);
1271}
1272
1273void tabplay_tilde_set(t_tabplay_tilde *x, t_symbol *s)
1274{
1275 t_garray *a;
1276
1277 x->x_arrayname = s;
1278 if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class)))
1279 {
1280 if (*s->s_name) pd_error(x, "tabplay~: %s: no such array",
1281 x->x_arrayname->s_name);
1282 x->x_vec = 0;
1283 }
1284 else if (!garray_getfloatarray(a, &x->x_nsampsintab, &x->x_vec))
1285 {
1286 pd_error(x, "%s: bad template for tabplay~", x->x_arrayname->s_name);
1287 x->x_vec = 0;
1288 }
1289 else garray_usedindsp(a);
1290}
1291
1292static void tabplay_tilde_dsp(t_tabplay_tilde *x, t_signal **sp)
1293{
1294 tabplay_tilde_set(x, x->x_arrayname);
1295 dsp_add(tabplay_tilde_perform, 3, x, sp[0]->s_vec, sp[0]->s_n);
1296}
1297
1298static void tabplay_tilde_list(t_tabplay_tilde *x, t_symbol *s,
1299 int argc, t_atom *argv)
1300{
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;
1309}
1310
1311static void tabplay_tilde_stop(t_tabplay_tilde *x)
1312{
1313 x->x_phase = 0x7fffffff;
1314}
1315
1316static void tabplay_tilde_tick(t_tabplay_tilde *x)
1317{
1318 outlet_bang(x->x_bangout);
1319}
1320
1321static void tabplay_tilde_free(t_tabplay_tilde *x)
1322{
1323 clock_free(x->x_clock);
1324}
1325
1326static void tabplay_tilde_setup(void)
1327{
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);
1338}
1339
1340/******************** tabread~ ***********************/
1341
1342static t_class *tabread_tilde_class;
1343
1344typedef struct _tabread_tilde
1345{
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;
1352
1353static void *tabread_tilde_new(t_symbol *s)
1354{
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);
1361}
1362
1363static t_int *tabread_tilde_perform(t_int *w)
1364{
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;
1372
1373 maxindex = x->x_npoints - 1;
1374 if (!buf) goto zero;
1375
1376 for (i = 0; i < n; i++)
1377 {
1378 int index = *in++;
1379 if (index < 0)
1380 index = 0;
1381 else if (index > maxindex)
1382 index = maxindex;
1383 *out++ = buf[index];
1384 }
1385 return (w+5);
1386 zero:
1387 while (n--) *out++ = 0;
1388
1389 return (w+5);
1390}
1391
1392void tabread_tilde_set(t_tabread_tilde *x, t_symbol *s)
1393{
1394 t_garray *a;
1395
1396 x->x_arrayname = s;
1397 if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class)))
1398 {
1399 if (*s->s_name)
1400 pd_error(x, "tabread~: %s: no such array", x->x_arrayname->s_name);
1401 x->x_vec = 0;
1402 }
1403 else if (!garray_getfloatarray(a, &x->x_npoints, &x->x_vec))
1404 {
1405 pd_error(x, "%s: bad template for tabread~", x->x_arrayname->s_name);
1406 x->x_vec = 0;
1407 }
1408 else garray_usedindsp(a);
1409}
1410
1411static void tabread_tilde_dsp(t_tabread_tilde *x, t_signal **sp)
1412{
1413 tabread_tilde_set(x, x->x_arrayname);
1414
1415 dsp_add(tabread_tilde_perform, 4, x,
1416 sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
1417
1418}
1419
1420static void tabread_tilde_free(t_tabread_tilde *x)
1421{
1422}
1423
1424static void tabread_tilde_setup(void)
1425{
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);
1434}
1435
1436/******************** tabread4~ ***********************/
1437
1438static t_class *tabread4_tilde_class;
1439
1440typedef struct _tabread4_tilde
1441{
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;
1448
1449static void *tabread4_tilde_new(t_symbol *s)
1450{
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);
1457}
1458
1459static t_int *tabread4_tilde_perform(t_int *w)
1460{
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;
1468
1469 maxindex = x->x_npoints - 3;
1470
1471 if (!buf) goto zero;
1472
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++)
1475 {
1476 float f = *in1;
1477 if (f < xmin) xmin = f;
1478 else if (f > xmax) xmax = f;
1479 }
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++)
1483 {
1484 float f = *in1;
1485 if (f > splitlo && f < splithi) goto zero;
1486 }
1487#endif
1488
1489 for (i = 0; i < n; i++)
1490 {
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)
1511 )
1512 );
1513 }
1514 return (w+5);
1515 zero:
1516 while (n--) *out++ = 0;
1517
1518 return (w+5);
1519}
1520
1521void tabread4_tilde_set(t_tabread4_tilde *x, t_symbol *s)
1522{
1523 t_garray *a;
1524
1525 x->x_arrayname = s;
1526 if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class)))
1527 {
1528 if (*s->s_name)
1529 pd_error(x, "tabread4~: %s: no such array", x->x_arrayname->s_name);
1530 x->x_vec = 0;
1531 }
1532 else if (!garray_getfloatarray(a, &x->x_npoints, &x->x_vec))
1533 {
1534 pd_error(x, "%s: bad template for tabread4~", x->x_arrayname->s_name);
1535 x->x_vec = 0;
1536 }
1537 else garray_usedindsp(a);
1538}
1539
1540static void tabread4_tilde_dsp(t_tabread4_tilde *x, t_signal **sp)
1541{
1542 tabread4_tilde_set(x, x->x_arrayname);
1543
1544 dsp_add(tabread4_tilde_perform, 4, x,
1545 sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
1546
1547}
1548
1549static void tabread4_tilde_free(t_tabread4_tilde *x)
1550{
1551}
1552
1553static void tabread4_tilde_setup(void)
1554{
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);
1563}
1564
1565/******************** tabosc4~ ***********************/
1566
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 */
1569
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
1596
1597#ifdef __linux__
1598#include <endian.h>
1599#if !defined(__BYTE_ORDER) || !defined(__LITTLE_ENDIAN)
1600#error No byte order defined
1601#endif
1602
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 */
1610
1611#include <sys/types.h>
1612#define int32 int32_t
1613
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 */
1619
1620#endif /* MACOSX */
1621#endif /* __linux__ */
1622#endif /* MSW */
1623#endif /* SGI */
1624
1625union tabfudge
1626{
1627 double tf_d;
1628 int32 tf_i[2];
1629};
1630
1631static t_class *tabosc4_tilde_class;
1632
1633typedef struct _tabosc4_tilde
1634{
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;
1644
1645static void *tabosc4_tilde_new(t_symbol *s)
1646{
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);
1656}
1657
1658static t_int *tabosc4_tilde_perform(t_int *w)
1659{
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;
1673
1674 if (!tab) goto zero;
1675 tf.tf_d = UNITBIT32;
1676 normhipart = tf.tf_i[HIOFFSET];
1677
1678#if 1
1679 while (n--)
1680 {
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)
1695 )
1696 );
1697 }
1698#endif
1699
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;
1708
1709 return (w+5);
1710}
1711
1712void tabosc4_tilde_set(t_tabosc4_tilde *x, t_symbol *s)
1713{
1714 t_garray *a;
1715 int npoints, pointsinarray;
1716
1717 x->x_arrayname = s;
1718 if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class)))
1719 {
1720 if (*s->s_name)
1721 pd_error(x, "tabosc4~: %s: no such array", x->x_arrayname->s_name);
1722 x->x_vec = 0;
1723 }
1724 else if (!garray_getfloatarray(a, &pointsinarray, &x->x_vec))
1725 {
1726 pd_error(x, "%s: bad template for tabosc4~", x->x_arrayname->s_name);
1727 x->x_vec = 0;
1728 }
1729 else if ((npoints = pointsinarray - 3) != (1 << ilog2(pointsinarray - 3)))
1730 {
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);
1735 }
1736 else
1737 {
1738 x->x_fnpoints = npoints;
1739 x->x_finvnpoints = 1./npoints;
1740 garray_usedindsp(a);
1741 }
1742}
1743
1744static void tabosc4_tilde_ft1(t_tabosc4_tilde *x, t_float f)
1745{
1746 x->x_phase = f;
1747}
1748
1749static void tabosc4_tilde_dsp(t_tabosc4_tilde *x, t_signal **sp)
1750{
1751 x->x_conv = 1. / sp[0]->s_sr;
1752 tabosc4_tilde_set(x, x->x_arrayname);
1753
1754 dsp_add(tabosc4_tilde_perform, 4, x,
1755 sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
1756}
1757
1758static void tabosc4_tilde_setup(void)
1759{
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);
1770}
1771
1772/* ------------------------ tabsend~ ------------------------- */
1773
1774static t_class *tabsend_class;
1775
1776typedef struct _tabsend
1777{
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;
1786
1787static void tabsend_tick(t_tabsend *x);
1788
1789static void *tabsend_new(t_symbol *s)
1790{
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);
1797}
1798
1799static t_int *tabsend_perform(t_int *w)
1800{
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;
1807
1808 while (n--)
1809 {
1810 float f = *in++;
1811 if (PD_BIGORSMALL(f))
1812 f = 0;
1813 *dest++ = f;
1814 }
1815 if (!i--)
1816 {
1817 clock_delay(x->x_clock, 0);
1818 i = x->x_graphperiod;
1819 }
1820 x->x_graphcount = i;
1821bad:
1822 return (w+4);
1823}
1824
1825static void tabsend_dsp(t_tabsend *x, t_signal **sp)
1826{
1827 int i, vecsize;
1828 t_garray *a;
1829
1830 if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class)))
1831 {
1832 if (*x->x_arrayname->s_name)
1833 pd_error(x, "tabsend~: %s: no such array", x->x_arrayname->s_name);
1834 }
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
1838 {
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);
1847 }
1848}
1849
1850static void tabsend_tick(t_tabsend *x)
1851{
1852 t_garray *a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class);
1853 if (!a) bug("tabsend_tick");
1854 else garray_redraw(a);
1855}
1856
1857static void tabsend_free(t_tabsend *x)
1858{
1859 clock_free(x->x_clock);
1860}
1861
1862static void tabsend_setup(void)
1863{
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);
1868}
1869
1870/* ------------------------ tabreceive~ ------------------------- */
1871
1872static t_class *tabreceive_class;
1873
1874typedef struct _tabreceive
1875{
1876 t_object x_obj;
1877 float *x_vec;
1878 t_symbol *x_arrayname;
1879} t_tabreceive;
1880
1881static t_int *tabreceive_perform(t_int *w)
1882{
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);
1890}
1891
1892static void tabreceive_dsp(t_tabreceive *x, t_signal **sp)
1893{
1894 t_garray *a;
1895 int vecsize;
1896
1897 if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class)))
1898 {
1899 if (*x->x_arrayname->s_name)
1900 pd_error(x, "tabsend~: %s: no such array", x->x_arrayname->s_name);
1901 }
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
1905 {
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);
1910 }
1911}
1912
1913static void *tabreceive_new(t_symbol *s)
1914{
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);
1919}
1920
1921static void tabreceive_setup(void)
1922{
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);
1928}
1929
1930
1931/* ---------- tabread: control, non-interpolating ------------------------ */
1932
1933static t_class *tabread_class;
1934
1935typedef struct _tabread
1936{
1937 t_object x_obj;
1938 t_symbol *x_arrayname;
1939} t_tabread;
1940
1941static void tabread_float(t_tabread *x, t_float f)
1942{
1943 t_garray *a;
1944 int npoints;
1945 t_float *vec;
1946
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
1952 {
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));
1957 }
1958}
1959
1960static void tabread_set(t_tabread *x, t_symbol *s)
1961{
1962 x->x_arrayname = s;
1963}
1964
1965static void *tabread_new(t_symbol *s)
1966{
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);
1971}
1972
1973static void tabread_setup(void)
1974{
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);
1980}
1981
1982/* ---------- tabread4: control, non-interpolating ------------------------ */
1983
1984static t_class *tabread4_class;
1985
1986typedef struct _tabread4
1987{
1988 t_object x_obj;
1989 t_symbol *x_arrayname;
1990} t_tabread4;
1991
1992static void tabread4_float(t_tabread4 *x, t_float f)
1993{
1994 t_garray *a;
1995 int npoints;
1996 t_float *vec;
1997
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
2009 {
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))));
2024 }
2025}
2026
2027static void tabread4_set(t_tabread4 *x, t_symbol *s)
2028{
2029 x->x_arrayname = s;
2030}
2031
2032static void *tabread4_new(t_symbol *s)
2033{
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);
2038}
2039
2040static void tabread4_setup(void)
2041{
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);
2047}
2048
2049/* ------------------ tabwrite: control ------------------------ */
2050
2051static t_class *tabwrite_class;
2052
2053typedef struct _tabwrite
2054{
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;
2062
2063static void tabwrite_tick(t_tabwrite *x)
2064{
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();
2070}
2071
2072static void tabwrite_float(t_tabwrite *x, t_float f)
2073{
2074 int i, vecsize;
2075 t_garray *a;
2076 t_float *vec;
2077
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
2083 {
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)
2090 {
2091 tabwrite_tick(x);
2092 }
2093 else
2094 {
2095 if (x->x_set == 0)
2096 {
2097 clock_delay(x->x_clock, 1000 - timesince);
2098 x->x_set = 1;
2099 }
2100 }
2101 }
2102}
2103
2104static void tabwrite_set(t_tabwrite *x, t_symbol *s)
2105{
2106 x->x_arrayname = s;
2107}
2108
2109static void tabwrite_free(t_tabwrite *x)
2110{
2111 clock_free(x->x_clock);
2112}
2113
2114static void *tabwrite_new(t_symbol *s)
2115{
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);
2123}
2124
2125void tabwrite_setup(void)
2126{
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);
2131}
2132
2133/* ------------------------ global setup routine ------------------------- */
2134
2135void d_array_setup(void)
2136{
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();
2147}
2148