diff options
Diffstat (limited to 'apps/plugins/pdbox/PDa/src/d_delay.c')
-rw-r--r-- | apps/plugins/pdbox/PDa/src/d_delay.c | 638 |
1 files changed, 638 insertions, 0 deletions
diff --git a/apps/plugins/pdbox/PDa/src/d_delay.c b/apps/plugins/pdbox/PDa/src/d_delay.c new file mode 100644 index 0000000000..37fb90ea5b --- /dev/null +++ b/apps/plugins/pdbox/PDa/src/d_delay.c | |||
@@ -0,0 +1,638 @@ | |||
1 | /* Copyright (c) 1997-1999 Miller Puckette. | ||
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 | /* send~, delread~, throw~, catch~ */ | ||
6 | |||
7 | #include "m_pd.h" | ||
8 | extern int ugen_getsortno(void); | ||
9 | |||
10 | #define DEFDELVS 64 /* LATER get this from canvas at DSP time */ | ||
11 | static int delread_zero = 0; /* four bytes of zero for delread~, vd~ */ | ||
12 | |||
13 | /* ----------------------------- delwrite~ ----------------------------- */ | ||
14 | static t_class *sigdelwrite_class; | ||
15 | |||
16 | typedef struct delwritectl | ||
17 | { | ||
18 | int c_n; | ||
19 | float *c_vec; | ||
20 | int c_phase; | ||
21 | } t_delwritectl; | ||
22 | |||
23 | typedef struct _sigdelwrite | ||
24 | { | ||
25 | t_object x_obj; | ||
26 | t_symbol *x_sym; | ||
27 | t_delwritectl x_cspace; | ||
28 | int x_sortno; /* DSP sort number at which this was last put on chain */ | ||
29 | int x_rsortno; /* DSP sort # for first delread or write in chain */ | ||
30 | int x_vecsize; /* vector size for delread~ to use */ | ||
31 | float x_f; | ||
32 | } t_sigdelwrite; | ||
33 | |||
34 | #define XTRASAMPS 4 | ||
35 | #define SAMPBLK 4 | ||
36 | |||
37 | /* routine to check that all delwrites/delreads/vds have same vecsize */ | ||
38 | static void sigdelwrite_checkvecsize(t_sigdelwrite *x, int vecsize) | ||
39 | { | ||
40 | /* | ||
41 | LATER this should really check sample rate and blocking, once that is | ||
42 | supported. Probably we don't actually care about vecsize. | ||
43 | For now just suppress this check... */ | ||
44 | #if 0 | ||
45 | if (x->x_rsortno != ugen_getsortno()) | ||
46 | { | ||
47 | x->x_vecsize = vecsize; | ||
48 | x->x_rsortno = ugen_getsortno(); | ||
49 | } | ||
50 | else if (vecsize != x->x_vecsize) | ||
51 | pd_error(x, "delread/delwrite/vd vector size mismatch"); | ||
52 | #endif | ||
53 | } | ||
54 | |||
55 | static void *sigdelwrite_new(t_symbol *s, t_floatarg msec) | ||
56 | { | ||
57 | int nsamps; | ||
58 | t_sigdelwrite *x = (t_sigdelwrite *)pd_new(sigdelwrite_class); | ||
59 | if (!*s->s_name) s = gensym("delwrite~"); | ||
60 | pd_bind(&x->x_obj.ob_pd, s); | ||
61 | x->x_sym = s; | ||
62 | nsamps = msec * sys_getsr() * (float)(0.001f); | ||
63 | if (nsamps < 1) nsamps = 1; | ||
64 | nsamps += ((- nsamps) & (SAMPBLK - 1)); | ||
65 | nsamps += DEFDELVS; | ||
66 | x->x_cspace.c_n = nsamps; | ||
67 | x->x_cspace.c_vec = | ||
68 | (float *)getbytes((nsamps + XTRASAMPS) * sizeof(float)); | ||
69 | x->x_cspace.c_phase = XTRASAMPS; | ||
70 | x->x_sortno = 0; | ||
71 | x->x_vecsize = 0; | ||
72 | x->x_f = 0; | ||
73 | return (x); | ||
74 | } | ||
75 | |||
76 | static t_int *sigdelwrite_perform(t_int *w) | ||
77 | { | ||
78 | t_float *in = (t_float *)(w[1]); | ||
79 | t_delwritectl *c = (t_delwritectl *)(w[2]); | ||
80 | int n = (int)(w[3]); | ||
81 | int phase = c->c_phase, nsamps = c->c_n; | ||
82 | float *vp = c->c_vec, *bp = vp + phase, *ep = vp + (c->c_n + XTRASAMPS); | ||
83 | phase += n; | ||
84 | while (n--) | ||
85 | { | ||
86 | float f = *in++; | ||
87 | if (PD_BIGORSMALL(f)) | ||
88 | f = 0; | ||
89 | *bp++ = f; | ||
90 | if (bp == ep) | ||
91 | { | ||
92 | vp[0] = ep[-4]; | ||
93 | vp[1] = ep[-3]; | ||
94 | vp[2] = ep[-2]; | ||
95 | vp[3] = ep[-1]; | ||
96 | bp = vp + XTRASAMPS; | ||
97 | phase -= nsamps; | ||
98 | } | ||
99 | } | ||
100 | c->c_phase = phase; | ||
101 | return (w+4); | ||
102 | } | ||
103 | |||
104 | static void sigdelwrite_dsp(t_sigdelwrite *x, t_signal **sp) | ||
105 | { | ||
106 | dsp_add(sigdelwrite_perform, 3, sp[0]->s_vec, &x->x_cspace, sp[0]->s_n); | ||
107 | x->x_sortno = ugen_getsortno(); | ||
108 | sigdelwrite_checkvecsize(x, sp[0]->s_n); | ||
109 | } | ||
110 | |||
111 | static void sigdelwrite_free(t_sigdelwrite *x) | ||
112 | { | ||
113 | pd_unbind(&x->x_obj.ob_pd, x->x_sym); | ||
114 | freebytes(x->x_cspace.c_vec, | ||
115 | (x->x_cspace.c_n + XTRASAMPS) * sizeof(float)); | ||
116 | } | ||
117 | |||
118 | static void sigdelwrite_setup(void) | ||
119 | { | ||
120 | sigdelwrite_class = class_new(gensym("delwrite~"), | ||
121 | (t_newmethod)sigdelwrite_new, (t_method)sigdelwrite_free, | ||
122 | sizeof(t_sigdelwrite), 0, A_DEFSYM, A_DEFFLOAT, 0); | ||
123 | CLASS_MAINSIGNALIN(sigdelwrite_class, t_sigdelwrite, x_f); | ||
124 | class_addmethod(sigdelwrite_class, (t_method)sigdelwrite_dsp, | ||
125 | gensym("dsp"), 0); | ||
126 | } | ||
127 | |||
128 | /* ----------------------------- delread~ ----------------------------- */ | ||
129 | static t_class *sigdelread_class; | ||
130 | |||
131 | typedef struct _sigdelread | ||
132 | { | ||
133 | t_object x_obj; | ||
134 | t_symbol *x_sym; | ||
135 | t_float x_deltime; /* delay in msec */ | ||
136 | int x_delsamps; /* delay in samples */ | ||
137 | t_float x_sr; /* samples per msec */ | ||
138 | t_float x_n; /* vector size */ | ||
139 | int x_zerodel; /* 0 or vecsize depending on read/write order */ | ||
140 | } t_sigdelread; | ||
141 | |||
142 | static void sigdelread_float(t_sigdelread *x, t_float f); | ||
143 | |||
144 | static void *sigdelread_new(t_symbol *s, t_floatarg f) | ||
145 | { | ||
146 | t_sigdelread *x = (t_sigdelread *)pd_new(sigdelread_class); | ||
147 | x->x_sym = s; | ||
148 | x->x_sr = 1; | ||
149 | x->x_n = 1; | ||
150 | x->x_zerodel = 0; | ||
151 | sigdelread_float(x, f); | ||
152 | outlet_new(&x->x_obj, &s_signal); | ||
153 | return (x); | ||
154 | } | ||
155 | |||
156 | static void sigdelread_float(t_sigdelread *x, t_float f) | ||
157 | { | ||
158 | int samps; | ||
159 | t_sigdelwrite *delwriter = | ||
160 | (t_sigdelwrite *)pd_findbyclass(x->x_sym, sigdelwrite_class); | ||
161 | x->x_deltime = f; | ||
162 | if (delwriter) | ||
163 | { | ||
164 | int delsize = delwriter->x_cspace.c_n; | ||
165 | x->x_delsamps = (int)(0.5 + x->x_sr * x->x_deltime) | ||
166 | + x->x_n - x->x_zerodel; | ||
167 | if (x->x_delsamps < x->x_n) x->x_delsamps = x->x_n; | ||
168 | else if (x->x_delsamps > delwriter->x_cspace.c_n - DEFDELVS) | ||
169 | x->x_delsamps = delwriter->x_cspace.c_n - DEFDELVS; | ||
170 | } | ||
171 | } | ||
172 | |||
173 | static t_int *sigdelread_perform(t_int *w) | ||
174 | { | ||
175 | t_float *out = (t_float *)(w[1]); | ||
176 | t_delwritectl *c = (t_delwritectl *)(w[2]); | ||
177 | int delsamps = *(int *)(w[3]); | ||
178 | int n = (int)(w[4]); | ||
179 | int phase = c->c_phase - delsamps, nsamps = c->c_n; | ||
180 | float *vp = c->c_vec, *bp, *ep = vp + (c->c_n + XTRASAMPS); | ||
181 | |||
182 | if (phase < 0) phase += nsamps; | ||
183 | bp = vp + phase; | ||
184 | while (n--) | ||
185 | { | ||
186 | *out++ = *bp++; | ||
187 | if (bp == ep) bp -= nsamps; | ||
188 | } | ||
189 | return (w+5); | ||
190 | } | ||
191 | |||
192 | static void sigdelread_dsp(t_sigdelread *x, t_signal **sp) | ||
193 | { | ||
194 | t_sigdelwrite *delwriter = | ||
195 | (t_sigdelwrite *)pd_findbyclass(x->x_sym, sigdelwrite_class); | ||
196 | x->x_sr = sp[0]->s_sr * 0.001; | ||
197 | x->x_n = sp[0]->s_n; | ||
198 | if (delwriter) | ||
199 | { | ||
200 | sigdelwrite_checkvecsize(delwriter, sp[0]->s_n); | ||
201 | x->x_zerodel = (delwriter->x_sortno == ugen_getsortno() ? | ||
202 | 0 : delwriter->x_vecsize); | ||
203 | sigdelread_float(x, x->x_deltime); | ||
204 | dsp_add(sigdelread_perform, 4, | ||
205 | sp[0]->s_vec, &delwriter->x_cspace, &x->x_delsamps, sp[0]->s_n); | ||
206 | } | ||
207 | else if (*x->x_sym->s_name) | ||
208 | error("delread~: %s: no such delwrite~",x->x_sym->s_name); | ||
209 | } | ||
210 | |||
211 | static void sigdelread_setup(void) | ||
212 | { | ||
213 | sigdelread_class = class_new(gensym("delread~"), | ||
214 | (t_newmethod)sigdelread_new, 0, | ||
215 | sizeof(t_sigdelread), 0, A_DEFSYM, A_DEFFLOAT, 0); | ||
216 | class_addmethod(sigdelread_class, (t_method)sigdelread_dsp, | ||
217 | gensym("dsp"), 0); | ||
218 | class_addfloat(sigdelread_class, (t_method)sigdelread_float); | ||
219 | } | ||
220 | |||
221 | |||
222 | /* ----------------------------- vd~ ----------------------------- */ | ||
223 | static t_class *sigvd_class; | ||
224 | |||
225 | typedef struct _sigvd | ||
226 | { | ||
227 | t_object x_obj; | ||
228 | t_symbol *x_sym; | ||
229 | t_float x_sr; /* samples per msec */ | ||
230 | int x_zerodel; /* 0 or vecsize depending on read/write order */ | ||
231 | float x_f; | ||
232 | } t_sigvd; | ||
233 | |||
234 | static void *sigvd_new(t_symbol *s) | ||
235 | { | ||
236 | t_sigvd *x = (t_sigvd *)pd_new(sigvd_class); | ||
237 | if (!*s->s_name) s = gensym("vd~"); | ||
238 | x->x_sym = s; | ||
239 | x->x_sr = 1; | ||
240 | x->x_zerodel = 0; | ||
241 | outlet_new(&x->x_obj, &s_signal); | ||
242 | x->x_f = 0; | ||
243 | return (x); | ||
244 | } | ||
245 | |||
246 | static t_int *sigvd_perform(t_int *w) | ||
247 | { | ||
248 | t_float *in = (t_float *)(w[1]); | ||
249 | t_float *out = (t_float *)(w[2]); | ||
250 | t_delwritectl *ctl = (t_delwritectl *)(w[3]); | ||
251 | t_sigvd *x = (t_sigvd *)(w[4]); | ||
252 | int n = (int)(w[5]); | ||
253 | |||
254 | int nsamps = ctl->c_n; | ||
255 | float limit = nsamps - n - 1; | ||
256 | float fn = n-1; | ||
257 | float *vp = ctl->c_vec, *bp, *wp = vp + ctl->c_phase; | ||
258 | float zerodel = x->x_zerodel; | ||
259 | while (n--) | ||
260 | { | ||
261 | float delsamps = x->x_sr * *in++ - zerodel, frac; | ||
262 | int idelsamps; | ||
263 | float a, b, c, d, cminusb; | ||
264 | if (delsamps < 1.00001f) delsamps = 1.00001f; | ||
265 | if (delsamps > limit) delsamps = limit; | ||
266 | delsamps += fn; | ||
267 | fn = fn - 1.0f; | ||
268 | idelsamps = delsamps; | ||
269 | frac = delsamps - (float)idelsamps; | ||
270 | bp = wp - idelsamps; | ||
271 | if (bp < vp + 4) bp += nsamps; | ||
272 | d = bp[-3]; | ||
273 | c = bp[-2]; | ||
274 | b = bp[-1]; | ||
275 | a = bp[0]; | ||
276 | cminusb = c-b; | ||
277 | *out++ = b + frac * ( | ||
278 | cminusb - 0.1666667f * (1.-frac) * ( | ||
279 | (d - a - 3.0f * cminusb) * frac + (d + 2.0f*a - 3.0f*b) | ||
280 | ) | ||
281 | ); | ||
282 | } | ||
283 | return (w+6); | ||
284 | } | ||
285 | |||
286 | static void sigvd_dsp(t_sigvd *x, t_signal **sp) | ||
287 | { | ||
288 | t_sigdelwrite *delwriter = | ||
289 | (t_sigdelwrite *)pd_findbyclass(x->x_sym, sigdelwrite_class); | ||
290 | x->x_sr = sp[0]->s_sr * 0.001; | ||
291 | if (delwriter) | ||
292 | { | ||
293 | sigdelwrite_checkvecsize(delwriter, sp[0]->s_n); | ||
294 | x->x_zerodel = (delwriter->x_sortno == ugen_getsortno() ? | ||
295 | 0 : delwriter->x_vecsize); | ||
296 | dsp_add(sigvd_perform, 5, | ||
297 | sp[0]->s_vec, sp[1]->s_vec, | ||
298 | &delwriter->x_cspace, x, sp[0]->s_n); | ||
299 | } | ||
300 | else error("vd~: %s: no such delwrite~",x->x_sym->s_name); | ||
301 | } | ||
302 | |||
303 | static void sigvd_setup(void) | ||
304 | { | ||
305 | sigvd_class = class_new(gensym("vd~"), (t_newmethod)sigvd_new, 0, | ||
306 | sizeof(t_sigvd), 0, A_DEFSYM, 0); | ||
307 | class_addmethod(sigvd_class, (t_method)sigvd_dsp, gensym("dsp"), 0); | ||
308 | CLASS_MAINSIGNALIN(sigvd_class, t_sigvd, x_f); | ||
309 | } | ||
310 | |||
311 | /* ----------------------- global setup routine ---------------- */ | ||
312 | |||
313 | void d_delay_setup(void) | ||
314 | { | ||
315 | sigdelwrite_setup(); | ||
316 | sigdelread_setup(); | ||
317 | sigvd_setup(); | ||
318 | } | ||
319 | |||
320 | /* Copyright (c) 1997-1999 Miller Puckette. | ||
321 | * For information on usage and redistribution, and for a DISCLAIMER OF ALL | ||
322 | * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ | ||
323 | |||
324 | /* send~, delread~, throw~, catch~ */ | ||
325 | |||
326 | #include "m_pd.h" | ||
327 | extern int ugen_getsortno(void); | ||
328 | |||
329 | #define DEFDELVS 64 /* LATER get this from canvas at DSP time */ | ||
330 | static int delread_zero = 0; /* four bytes of zero for delread~, vd~ */ | ||
331 | |||
332 | /* ----------------------------- delwrite~ ----------------------------- */ | ||
333 | static t_class *sigdelwrite_class; | ||
334 | |||
335 | typedef struct delwritectl | ||
336 | { | ||
337 | int c_n; | ||
338 | float *c_vec; | ||
339 | int c_phase; | ||
340 | } t_delwritectl; | ||
341 | |||
342 | typedef struct _sigdelwrite | ||
343 | { | ||
344 | t_object x_obj; | ||
345 | t_symbol *x_sym; | ||
346 | t_delwritectl x_cspace; | ||
347 | int x_sortno; /* DSP sort number at which this was last put on chain */ | ||
348 | int x_rsortno; /* DSP sort # for first delread or write in chain */ | ||
349 | int x_vecsize; /* vector size for delread~ to use */ | ||
350 | float x_f; | ||
351 | } t_sigdelwrite; | ||
352 | |||
353 | #define XTRASAMPS 4 | ||
354 | #define SAMPBLK 4 | ||
355 | |||
356 | /* routine to check that all delwrites/delreads/vds have same vecsize */ | ||
357 | static void sigdelwrite_checkvecsize(t_sigdelwrite *x, int vecsize) | ||
358 | { | ||
359 | /* | ||
360 | LATER this should really check sample rate and blocking, once that is | ||
361 | supported. Probably we don't actually care about vecsize. | ||
362 | For now just suppress this check... */ | ||
363 | #if 0 | ||
364 | if (x->x_rsortno != ugen_getsortno()) | ||
365 | { | ||
366 | x->x_vecsize = vecsize; | ||
367 | x->x_rsortno = ugen_getsortno(); | ||
368 | } | ||
369 | else if (vecsize != x->x_vecsize) | ||
370 | pd_error(x, "delread/delwrite/vd vector size mismatch"); | ||
371 | #endif | ||
372 | } | ||
373 | |||
374 | static void *sigdelwrite_new(t_symbol *s, t_floatarg msec) | ||
375 | { | ||
376 | int nsamps; | ||
377 | t_sigdelwrite *x = (t_sigdelwrite *)pd_new(sigdelwrite_class); | ||
378 | if (!*s->s_name) s = gensym("delwrite~"); | ||
379 | pd_bind(&x->x_obj.ob_pd, s); | ||
380 | x->x_sym = s; | ||
381 | nsamps = msec * sys_getsr() * (float)(0.001f); | ||
382 | if (nsamps < 1) nsamps = 1; | ||
383 | nsamps += ((- nsamps) & (SAMPBLK - 1)); | ||
384 | nsamps += DEFDELVS; | ||
385 | x->x_cspace.c_n = nsamps; | ||
386 | x->x_cspace.c_vec = | ||
387 | (float *)getbytes((nsamps + XTRASAMPS) * sizeof(float)); | ||
388 | x->x_cspace.c_phase = XTRASAMPS; | ||
389 | x->x_sortno = 0; | ||
390 | x->x_vecsize = 0; | ||
391 | x->x_f = 0; | ||
392 | return (x); | ||
393 | } | ||
394 | |||
395 | static t_int *sigdelwrite_perform(t_int *w) | ||
396 | { | ||
397 | t_float *in = (t_float *)(w[1]); | ||
398 | t_delwritectl *c = (t_delwritectl *)(w[2]); | ||
399 | int n = (int)(w[3]); | ||
400 | int phase = c->c_phase, nsamps = c->c_n; | ||
401 | float *vp = c->c_vec, *bp = vp + phase, *ep = vp + (c->c_n + XTRASAMPS); | ||
402 | phase += n; | ||
403 | while (n--) | ||
404 | { | ||
405 | float f = *in++; | ||
406 | if (PD_BIGORSMALL(f)) | ||
407 | f = 0; | ||
408 | *bp++ = f; | ||
409 | if (bp == ep) | ||
410 | { | ||
411 | vp[0] = ep[-4]; | ||
412 | vp[1] = ep[-3]; | ||
413 | vp[2] = ep[-2]; | ||
414 | vp[3] = ep[-1]; | ||
415 | bp = vp + XTRASAMPS; | ||
416 | phase -= nsamps; | ||
417 | } | ||
418 | } | ||
419 | c->c_phase = phase; | ||
420 | return (w+4); | ||
421 | } | ||
422 | |||
423 | static void sigdelwrite_dsp(t_sigdelwrite *x, t_signal **sp) | ||
424 | { | ||
425 | dsp_add(sigdelwrite_perform, 3, sp[0]->s_vec, &x->x_cspace, sp[0]->s_n); | ||
426 | x->x_sortno = ugen_getsortno(); | ||
427 | sigdelwrite_checkvecsize(x, sp[0]->s_n); | ||
428 | } | ||
429 | |||
430 | static void sigdelwrite_free(t_sigdelwrite *x) | ||
431 | { | ||
432 | pd_unbind(&x->x_obj.ob_pd, x->x_sym); | ||
433 | freebytes(x->x_cspace.c_vec, | ||
434 | (x->x_cspace.c_n + XTRASAMPS) * sizeof(float)); | ||
435 | } | ||
436 | |||
437 | static void sigdelwrite_setup(void) | ||
438 | { | ||
439 | sigdelwrite_class = class_new(gensym("delwrite~"), | ||
440 | (t_newmethod)sigdelwrite_new, (t_method)sigdelwrite_free, | ||
441 | sizeof(t_sigdelwrite), 0, A_DEFSYM, A_DEFFLOAT, 0); | ||
442 | CLASS_MAINSIGNALIN(sigdelwrite_class, t_sigdelwrite, x_f); | ||
443 | class_addmethod(sigdelwrite_class, (t_method)sigdelwrite_dsp, | ||
444 | gensym("dsp"), 0); | ||
445 | } | ||
446 | |||
447 | /* ----------------------------- delread~ ----------------------------- */ | ||
448 | static t_class *sigdelread_class; | ||
449 | |||
450 | typedef struct _sigdelread | ||
451 | { | ||
452 | t_object x_obj; | ||
453 | t_symbol *x_sym; | ||
454 | t_float x_deltime; /* delay in msec */ | ||
455 | int x_delsamps; /* delay in samples */ | ||
456 | t_float x_sr; /* samples per msec */ | ||
457 | t_float x_n; /* vector size */ | ||
458 | int x_zerodel; /* 0 or vecsize depending on read/write order */ | ||
459 | } t_sigdelread; | ||
460 | |||
461 | static void sigdelread_float(t_sigdelread *x, t_float f); | ||
462 | |||
463 | static void *sigdelread_new(t_symbol *s, t_floatarg f) | ||
464 | { | ||
465 | t_sigdelread *x = (t_sigdelread *)pd_new(sigdelread_class); | ||
466 | x->x_sym = s; | ||
467 | x->x_sr = 1; | ||
468 | x->x_n = 1; | ||
469 | x->x_zerodel = 0; | ||
470 | sigdelread_float(x, f); | ||
471 | outlet_new(&x->x_obj, &s_signal); | ||
472 | return (x); | ||
473 | } | ||
474 | |||
475 | static void sigdelread_float(t_sigdelread *x, t_float f) | ||
476 | { | ||
477 | int samps; | ||
478 | t_sigdelwrite *delwriter = | ||
479 | (t_sigdelwrite *)pd_findbyclass(x->x_sym, sigdelwrite_class); | ||
480 | x->x_deltime = f; | ||
481 | if (delwriter) | ||
482 | { | ||
483 | int delsize = delwriter->x_cspace.c_n; | ||
484 | x->x_delsamps = (int)(0.5 + x->x_sr * x->x_deltime) | ||
485 | + x->x_n - x->x_zerodel; | ||
486 | if (x->x_delsamps < x->x_n) x->x_delsamps = x->x_n; | ||
487 | else if (x->x_delsamps > delwriter->x_cspace.c_n - DEFDELVS) | ||
488 | x->x_delsamps = delwriter->x_cspace.c_n - DEFDELVS; | ||
489 | } | ||
490 | } | ||
491 | |||
492 | static t_int *sigdelread_perform(t_int *w) | ||
493 | { | ||
494 | t_float *out = (t_float *)(w[1]); | ||
495 | t_delwritectl *c = (t_delwritectl *)(w[2]); | ||
496 | int delsamps = *(int *)(w[3]); | ||
497 | int n = (int)(w[4]); | ||
498 | int phase = c->c_phase - delsamps, nsamps = c->c_n; | ||
499 | float *vp = c->c_vec, *bp, *ep = vp + (c->c_n + XTRASAMPS); | ||
500 | |||
501 | if (phase < 0) phase += nsamps; | ||
502 | bp = vp + phase; | ||
503 | while (n--) | ||
504 | { | ||
505 | *out++ = *bp++; | ||
506 | if (bp == ep) bp -= nsamps; | ||
507 | } | ||
508 | return (w+5); | ||
509 | } | ||
510 | |||
511 | static void sigdelread_dsp(t_sigdelread *x, t_signal **sp) | ||
512 | { | ||
513 | t_sigdelwrite *delwriter = | ||
514 | (t_sigdelwrite *)pd_findbyclass(x->x_sym, sigdelwrite_class); | ||
515 | x->x_sr = sp[0]->s_sr * 0.001; | ||
516 | x->x_n = sp[0]->s_n; | ||
517 | if (delwriter) | ||
518 | { | ||
519 | sigdelwrite_checkvecsize(delwriter, sp[0]->s_n); | ||
520 | x->x_zerodel = (delwriter->x_sortno == ugen_getsortno() ? | ||
521 | 0 : delwriter->x_vecsize); | ||
522 | sigdelread_float(x, x->x_deltime); | ||
523 | dsp_add(sigdelread_perform, 4, | ||
524 | sp[0]->s_vec, &delwriter->x_cspace, &x->x_delsamps, sp[0]->s_n); | ||
525 | } | ||
526 | else if (*x->x_sym->s_name) | ||
527 | error("delread~: %s: no such delwrite~",x->x_sym->s_name); | ||
528 | } | ||
529 | |||
530 | static void sigdelread_setup(void) | ||
531 | { | ||
532 | sigdelread_class = class_new(gensym("delread~"), | ||
533 | (t_newmethod)sigdelread_new, 0, | ||
534 | sizeof(t_sigdelread), 0, A_DEFSYM, A_DEFFLOAT, 0); | ||
535 | class_addmethod(sigdelread_class, (t_method)sigdelread_dsp, | ||
536 | gensym("dsp"), 0); | ||
537 | class_addfloat(sigdelread_class, (t_method)sigdelread_float); | ||
538 | } | ||
539 | |||
540 | |||
541 | /* ----------------------------- vd~ ----------------------------- */ | ||
542 | static t_class *sigvd_class; | ||
543 | |||
544 | typedef struct _sigvd | ||
545 | { | ||
546 | t_object x_obj; | ||
547 | t_symbol *x_sym; | ||
548 | t_float x_sr; /* samples per msec */ | ||
549 | int x_zerodel; /* 0 or vecsize depending on read/write order */ | ||
550 | float x_f; | ||
551 | } t_sigvd; | ||
552 | |||
553 | static void *sigvd_new(t_symbol *s) | ||
554 | { | ||
555 | t_sigvd *x = (t_sigvd *)pd_new(sigvd_class); | ||
556 | if (!*s->s_name) s = gensym("vd~"); | ||
557 | x->x_sym = s; | ||
558 | x->x_sr = 1; | ||
559 | x->x_zerodel = 0; | ||
560 | outlet_new(&x->x_obj, &s_signal); | ||
561 | x->x_f = 0; | ||
562 | return (x); | ||
563 | } | ||
564 | |||
565 | static t_int *sigvd_perform(t_int *w) | ||
566 | { | ||
567 | t_float *in = (t_float *)(w[1]); | ||
568 | t_float *out = (t_float *)(w[2]); | ||
569 | t_delwritectl *ctl = (t_delwritectl *)(w[3]); | ||
570 | t_sigvd *x = (t_sigvd *)(w[4]); | ||
571 | int n = (int)(w[5]); | ||
572 | |||
573 | int nsamps = ctl->c_n; | ||
574 | float limit = nsamps - n - 1; | ||
575 | float fn = n-1; | ||
576 | float *vp = ctl->c_vec, *bp, *wp = vp + ctl->c_phase; | ||
577 | float zerodel = x->x_zerodel; | ||
578 | while (n--) | ||
579 | { | ||
580 | float delsamps = x->x_sr * *in++ - zerodel, frac; | ||
581 | int idelsamps; | ||
582 | float a, b, c, d, cminusb; | ||
583 | if (delsamps < 1.00001f) delsamps = 1.00001f; | ||
584 | if (delsamps > limit) delsamps = limit; | ||
585 | delsamps += fn; | ||
586 | fn = fn - 1.0f; | ||
587 | idelsamps = delsamps; | ||
588 | frac = delsamps - (float)idelsamps; | ||
589 | bp = wp - idelsamps; | ||
590 | if (bp < vp + 4) bp += nsamps; | ||
591 | d = bp[-3]; | ||
592 | c = bp[-2]; | ||
593 | b = bp[-1]; | ||
594 | a = bp[0]; | ||
595 | cminusb = c-b; | ||
596 | *out++ = b + frac * ( | ||
597 | cminusb - 0.1666667f * (1.-frac) * ( | ||
598 | (d - a - 3.0f * cminusb) * frac + (d + 2.0f*a - 3.0f*b) | ||
599 | ) | ||
600 | ); | ||
601 | } | ||
602 | return (w+6); | ||
603 | } | ||
604 | |||
605 | static void sigvd_dsp(t_sigvd *x, t_signal **sp) | ||
606 | { | ||
607 | t_sigdelwrite *delwriter = | ||
608 | (t_sigdelwrite *)pd_findbyclass(x->x_sym, sigdelwrite_class); | ||
609 | x->x_sr = sp[0]->s_sr * 0.001; | ||
610 | if (delwriter) | ||
611 | { | ||
612 | sigdelwrite_checkvecsize(delwriter, sp[0]->s_n); | ||
613 | x->x_zerodel = (delwriter->x_sortno == ugen_getsortno() ? | ||
614 | 0 : delwriter->x_vecsize); | ||
615 | dsp_add(sigvd_perform, 5, | ||
616 | sp[0]->s_vec, sp[1]->s_vec, | ||
617 | &delwriter->x_cspace, x, sp[0]->s_n); | ||
618 | } | ||
619 | else error("vd~: %s: no such delwrite~",x->x_sym->s_name); | ||
620 | } | ||
621 | |||
622 | static void sigvd_setup(void) | ||
623 | { | ||
624 | sigvd_class = class_new(gensym("vd~"), (t_newmethod)sigvd_new, 0, | ||
625 | sizeof(t_sigvd), 0, A_DEFSYM, 0); | ||
626 | class_addmethod(sigvd_class, (t_method)sigvd_dsp, gensym("dsp"), 0); | ||
627 | CLASS_MAINSIGNALIN(sigvd_class, t_sigvd, x_f); | ||
628 | } | ||
629 | |||
630 | /* ----------------------- global setup routine ---------------- */ | ||
631 | |||
632 | void d_delay_setup(void) | ||
633 | { | ||
634 | sigdelwrite_setup(); | ||
635 | sigdelread_setup(); | ||
636 | sigvd_setup(); | ||
637 | } | ||
638 | |||