summaryrefslogtreecommitdiff
path: root/apps/plugins/pdbox/PDa/intern/vline~.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/pdbox/PDa/intern/vline~.c')
-rw-r--r--apps/plugins/pdbox/PDa/intern/vline~.c368
1 files changed, 368 insertions, 0 deletions
diff --git a/apps/plugins/pdbox/PDa/intern/vline~.c b/apps/plugins/pdbox/PDa/intern/vline~.c
new file mode 100644
index 0000000000..74edb83bc6
--- /dev/null
+++ b/apps/plugins/pdbox/PDa/intern/vline~.c
@@ -0,0 +1,368 @@
1#include <m_pd.h>
2#include <m_fixed.h>
3
4
5
6static t_class *vline_tilde_class;
7
8typedef struct _vseg
9{
10 t_time s_targettime;
11 t_time s_starttime;
12 t_sample s_target;
13 struct _vseg *s_next;
14} t_vseg;
15
16typedef struct _vline
17{
18 t_object x_obj;
19 t_sample x_value;
20 t_sample x_inc;
21 t_time x_referencetime;
22 t_time x_samppermsec;
23 t_time x_msecpersamp;
24 t_time x_targettime;
25 t_sample x_target;
26 float x_inlet1;
27 float x_inlet2;
28 t_vseg *x_list;
29} t_vline;
30
31static t_int *vline_tilde_perform(t_int *w)
32{
33 t_vline *x = (t_vline *)(w[1]);
34 t_sample *out = (t_sample *)(w[2]);
35 int n = (int)(w[3]), i;
36 t_sample f = x->x_value;
37 t_sample inc = x->x_inc;
38 t_time msecpersamp = x->x_msecpersamp;
39 t_time samppermsec = x->x_samppermsec;
40 t_time timenow = clock_gettimesince(x->x_referencetime) - n * msecpersamp;
41 t_vseg *s = x->x_list;
42 for (i = 0; i < n; i++)
43 {
44 t_time timenext = timenow + msecpersamp;
45 checknext:
46 if (s)
47 {
48 /* has starttime elapsed? If so update value and increment */
49 if (s->s_starttime < timenext)
50 {
51 if (x->x_targettime <= timenext)
52 f = x->x_target, inc = 0;
53 /* if zero-length segment bash output value */
54 if (s->s_targettime <= s->s_starttime)
55 {
56 f = s->s_target;
57 inc = 0;
58 }
59 else
60 {
61 t_time incpermsec = div((s->s_target - f),
62 (s->s_targettime - s->s_starttime));
63 f = mult(f + incpermsec,(timenext - s->s_starttime));
64 inc = mult(incpermsec,msecpersamp);
65 }
66 x->x_inc = inc;
67 x->x_target = s->s_target;
68 x->x_targettime = s->s_targettime;
69 x->x_list = s->s_next;
70 t_freebytes(s, sizeof(*s));
71 s = x->x_list;
72 goto checknext;
73 }
74 }
75 if (x->x_targettime <= timenext)
76 f = x->x_target, inc = 0;
77 *out++ = f;
78 f = f + inc;
79 timenow = timenext;
80 }
81 x->x_value = f;
82 return (w+4);
83}
84
85static void vline_tilde_stop(t_vline *x)
86{
87 t_vseg *s1, *s2;
88 for (s1 = x->x_list; s1; s1 = s2)
89 s2 = s1->s_next, t_freebytes(s1, sizeof(*s1));
90 x->x_list = 0;
91 x->x_inc = 0;
92 x->x_inlet1 = x->x_inlet2 = 0;
93}
94
95static void vline_tilde_float(t_vline *x, t_float f)
96{
97 t_time timenow = clock_gettimesince(x->x_referencetime);
98 t_sample inlet1 = (x->x_inlet1 < 0 ? 0 : (t_sample)x->x_inlet1);
99 t_sample inlet2 = (t_sample) x->x_inlet2;
100 t_time starttime = timenow + inlet2;
101 t_vseg *s1, *s2, *deletefrom = 0,
102 *snew = (t_vseg *)t_getbytes(sizeof(*snew));
103 if (PD_BADFLOAT(f))
104 f = 0;
105
106 /* negative delay input means stop and jump immediately to new value */
107 if (inlet2 < 0)
108 {
109 vline_tilde_stop(x);
110 x->x_value = ftofix(f);
111 return;
112 }
113 /* check if we supplant the first item in the list. We supplant
114 an item by having an earlier starttime, or an equal starttime unless
115 the equal one was instantaneous and the new one isn't (in which case
116 we'll do a jump-and-slide starting at that time.) */
117 if (!x->x_list || x->x_list->s_starttime > starttime ||
118 (x->x_list->s_starttime == starttime &&
119 (x->x_list->s_targettime > x->x_list->s_starttime || inlet1 <= 0)))
120 {
121 deletefrom = x->x_list;
122 x->x_list = snew;
123 }
124 else
125 {
126 for (s1 = x->x_list; s2 = s1->s_next; s1 = s2)
127 {
128 if (s2->s_starttime > starttime ||
129 (s2->s_starttime == starttime &&
130 (s2->s_targettime > s2->s_starttime || inlet1 <= 0)))
131 {
132 deletefrom = s2;
133 s1->s_next = snew;
134 goto didit;
135 }
136 }
137 s1->s_next = snew;
138 deletefrom = 0;
139 didit: ;
140 }
141 while (deletefrom)
142 {
143 s1 = deletefrom->s_next;
144 t_freebytes(deletefrom, sizeof(*deletefrom));
145 deletefrom = s1;
146 }
147 snew->s_next = 0;
148 snew->s_target = f;
149 snew->s_starttime = starttime;
150 snew->s_targettime = starttime + inlet1;
151 x->x_inlet1 = x->x_inlet2 = 0;
152}
153
154static void vline_tilde_dsp(t_vline *x, t_signal **sp)
155{
156 dsp_add(vline_tilde_perform, 3, x, sp[0]->s_vec, sp[0]->s_n);
157 x->x_samppermsec = idiv(ftofix(sp[0]->s_sr),ftofix(1000));
158 x->x_msecpersamp = idiv(ftofix(1000),ftofix(sp[0]->s_sr));
159}
160
161static void *vline_tilde_new(void)
162{
163 t_vline *x = (t_vline *)pd_new(vline_tilde_class);
164 outlet_new(&x->x_obj, gensym("signal"));
165 floatinlet_new(&x->x_obj, &x->x_inlet1);
166 floatinlet_new(&x->x_obj, &x->x_inlet2);
167 x->x_inlet1 = x->x_inlet2 = 0;
168 x->x_value = x->x_inc = 0;
169 x->x_referencetime = clock_getlogicaltime();
170 x->x_list = 0;
171 x->x_samppermsec = 0;
172 return (x);
173}
174
175void vline_tilde_setup(void)
176{
177 vline_tilde_class = class_new(gensym("vline~"), vline_tilde_new,
178 (t_method)vline_tilde_stop, sizeof(t_vline), 0, 0);
179 class_addfloat(vline_tilde_class, (t_method)vline_tilde_float);
180 class_addmethod(vline_tilde_class, (t_method)vline_tilde_dsp,
181 gensym("dsp"), 0);
182 class_addmethod(vline_tilde_class, (t_method)vline_tilde_stop,
183 gensym("stop"), 0);
184}
185#include <m_pd.h>
186#include <m_fixed.h>
187
188
189
190static t_class *vline_tilde_class;
191
192typedef struct _vseg
193{
194 t_time s_targettime;
195 t_time s_starttime;
196 t_sample s_target;
197 struct _vseg *s_next;
198} t_vseg;
199
200typedef struct _vline
201{
202 t_object x_obj;
203 t_sample x_value;
204 t_sample x_inc;
205 t_time x_referencetime;
206 t_time x_samppermsec;
207 t_time x_msecpersamp;
208 t_time x_targettime;
209 t_sample x_target;
210 float x_inlet1;
211 float x_inlet2;
212 t_vseg *x_list;
213} t_vline;
214
215static t_int *vline_tilde_perform(t_int *w)
216{
217 t_vline *x = (t_vline *)(w[1]);
218 t_sample *out = (t_sample *)(w[2]);
219 int n = (int)(w[3]), i;
220 t_sample f = x->x_value;
221 t_sample inc = x->x_inc;
222 t_time msecpersamp = x->x_msecpersamp;
223 t_time samppermsec = x->x_samppermsec;
224 t_time timenow = clock_gettimesince(x->x_referencetime) - n * msecpersamp;
225 t_vseg *s = x->x_list;
226 for (i = 0; i < n; i++)
227 {
228 t_time timenext = timenow + msecpersamp;
229 checknext:
230 if (s)
231 {
232 /* has starttime elapsed? If so update value and increment */
233 if (s->s_starttime < timenext)
234 {
235 if (x->x_targettime <= timenext)
236 f = x->x_target, inc = 0;
237 /* if zero-length segment bash output value */
238 if (s->s_targettime <= s->s_starttime)
239 {
240 f = s->s_target;
241 inc = 0;
242 }
243 else
244 {
245 t_time incpermsec = div((s->s_target - f),
246 (s->s_targettime - s->s_starttime));
247 f = mult(f + incpermsec,(timenext - s->s_starttime));
248 inc = mult(incpermsec,msecpersamp);
249 }
250 x->x_inc = inc;
251 x->x_target = s->s_target;
252 x->x_targettime = s->s_targettime;
253 x->x_list = s->s_next;
254 t_freebytes(s, sizeof(*s));
255 s = x->x_list;
256 goto checknext;
257 }
258 }
259 if (x->x_targettime <= timenext)
260 f = x->x_target, inc = 0;
261 *out++ = f;
262 f = f + inc;
263 timenow = timenext;
264 }
265 x->x_value = f;
266 return (w+4);
267}
268
269static void vline_tilde_stop(t_vline *x)
270{
271 t_vseg *s1, *s2;
272 for (s1 = x->x_list; s1; s1 = s2)
273 s2 = s1->s_next, t_freebytes(s1, sizeof(*s1));
274 x->x_list = 0;
275 x->x_inc = 0;
276 x->x_inlet1 = x->x_inlet2 = 0;
277}
278
279static void vline_tilde_float(t_vline *x, t_float f)
280{
281 t_time timenow = clock_gettimesince(x->x_referencetime);
282 t_sample inlet1 = (x->x_inlet1 < 0 ? 0 : (t_sample)x->x_inlet1);
283 t_sample inlet2 = (t_sample) x->x_inlet2;
284 t_time starttime = timenow + inlet2;
285 t_vseg *s1, *s2, *deletefrom = 0,
286 *snew = (t_vseg *)t_getbytes(sizeof(*snew));
287 if (PD_BADFLOAT(f))
288 f = 0;
289
290 /* negative delay input means stop and jump immediately to new value */
291 if (inlet2 < 0)
292 {
293 vline_tilde_stop(x);
294 x->x_value = ftofix(f);
295 return;
296 }
297 /* check if we supplant the first item in the list. We supplant
298 an item by having an earlier starttime, or an equal starttime unless
299 the equal one was instantaneous and the new one isn't (in which case
300 we'll do a jump-and-slide starting at that time.) */
301 if (!x->x_list || x->x_list->s_starttime > starttime ||
302 (x->x_list->s_starttime == starttime &&
303 (x->x_list->s_targettime > x->x_list->s_starttime || inlet1 <= 0)))
304 {
305 deletefrom = x->x_list;
306 x->x_list = snew;
307 }
308 else
309 {
310 for (s1 = x->x_list; s2 = s1->s_next; s1 = s2)
311 {
312 if (s2->s_starttime > starttime ||
313 (s2->s_starttime == starttime &&
314 (s2->s_targettime > s2->s_starttime || inlet1 <= 0)))
315 {
316 deletefrom = s2;
317 s1->s_next = snew;
318 goto didit;
319 }
320 }
321 s1->s_next = snew;
322 deletefrom = 0;
323 didit: ;
324 }
325 while (deletefrom)
326 {
327 s1 = deletefrom->s_next;
328 t_freebytes(deletefrom, sizeof(*deletefrom));
329 deletefrom = s1;
330 }
331 snew->s_next = 0;
332 snew->s_target = f;
333 snew->s_starttime = starttime;
334 snew->s_targettime = starttime + inlet1;
335 x->x_inlet1 = x->x_inlet2 = 0;
336}
337
338static void vline_tilde_dsp(t_vline *x, t_signal **sp)
339{
340 dsp_add(vline_tilde_perform, 3, x, sp[0]->s_vec, sp[0]->s_n);
341 x->x_samppermsec = idiv(ftofix(sp[0]->s_sr),ftofix(1000));
342 x->x_msecpersamp = idiv(ftofix(1000),ftofix(sp[0]->s_sr));
343}
344
345static void *vline_tilde_new(void)
346{
347 t_vline *x = (t_vline *)pd_new(vline_tilde_class);
348 outlet_new(&x->x_obj, gensym("signal"));
349 floatinlet_new(&x->x_obj, &x->x_inlet1);
350 floatinlet_new(&x->x_obj, &x->x_inlet2);
351 x->x_inlet1 = x->x_inlet2 = 0;
352 x->x_value = x->x_inc = 0;
353 x->x_referencetime = clock_getlogicaltime();
354 x->x_list = 0;
355 x->x_samppermsec = 0;
356 return (x);
357}
358
359void vline_tilde_setup(void)
360{
361 vline_tilde_class = class_new(gensym("vline~"), vline_tilde_new,
362 (t_method)vline_tilde_stop, sizeof(t_vline), 0, 0);
363 class_addfloat(vline_tilde_class, (t_method)vline_tilde_float);
364 class_addmethod(vline_tilde_class, (t_method)vline_tilde_dsp,
365 gensym("dsp"), 0);
366 class_addmethod(vline_tilde_class, (t_method)vline_tilde_stop,
367 gensym("stop"), 0);
368}