diff options
author | Peter D'Hoye <peter.dhoye@gmail.com> | 2009-05-22 21:58:48 +0000 |
---|---|---|
committer | Peter D'Hoye <peter.dhoye@gmail.com> | 2009-05-22 21:58:48 +0000 |
commit | 513389b4c1bc8afe4b2dc9947c534bfeb105e3da (patch) | |
tree | 10e673b35651ac567fed2eda0c679c7ade64cbc6 /apps/plugins/pdbox/PDa/src/x_midi.c | |
parent | 95fa7f6a2ef466444fbe3fe87efc6d5db6b77b36 (diff) | |
download | rockbox-513389b4c1bc8afe4b2dc9947c534bfeb105e3da.tar.gz rockbox-513389b4c1bc8afe4b2dc9947c534bfeb105e3da.zip |
Add FS #10214. Initial commit of the original PDa code for the GSoC Pure Data plugin project of Wincent Balin. Stripped some non-sourcefiles and added a rockbox readme that needs a bit more info from Wincent. Is added to CATEGORIES and viewers, but not yet to SUBDIRS (ie doesn't build yet)
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@21044 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/plugins/pdbox/PDa/src/x_midi.c')
-rw-r--r-- | apps/plugins/pdbox/PDa/src/x_midi.c | 2626 |
1 files changed, 2626 insertions, 0 deletions
diff --git a/apps/plugins/pdbox/PDa/src/x_midi.c b/apps/plugins/pdbox/PDa/src/x_midi.c new file mode 100644 index 0000000000..a71000f121 --- /dev/null +++ b/apps/plugins/pdbox/PDa/src/x_midi.c | |||
@@ -0,0 +1,2626 @@ | |||
1 | /* Copyright (c) 1997-2001 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 | /* MIDI. */ | ||
6 | |||
7 | #include "m_pd.h" | ||
8 | void outmidi_noteon(int portno, int channel, int pitch, int velo); | ||
9 | void outmidi_controlchange(int portno, int channel, int ctlno, int value); | ||
10 | void outmidi_programchange(int portno, int channel, int value); | ||
11 | void outmidi_pitchbend(int portno, int channel, int value); | ||
12 | void outmidi_aftertouch(int portno, int channel, int value); | ||
13 | void outmidi_polyaftertouch(int portno, int channel, int pitch, int value); | ||
14 | void outmidi_mclk(int portno); | ||
15 | |||
16 | /* ----------------------- midiin and sysexin ------------------------- */ | ||
17 | |||
18 | static t_symbol *midiin_sym, *sysexin_sym; | ||
19 | |||
20 | static t_class *midiin_class, *sysexin_class; | ||
21 | |||
22 | typedef struct _midiin | ||
23 | { | ||
24 | t_object x_obj; | ||
25 | t_outlet *x_outlet1; | ||
26 | t_outlet *x_outlet2; | ||
27 | } t_midiin; | ||
28 | |||
29 | static void *midiin_new( void) | ||
30 | { | ||
31 | t_midiin *x = (t_midiin *)pd_new(midiin_class); | ||
32 | x->x_outlet1 = outlet_new(&x->x_obj, &s_float); | ||
33 | x->x_outlet2 = outlet_new(&x->x_obj, &s_float); | ||
34 | pd_bind(&x->x_obj.ob_pd, midiin_sym); | ||
35 | #ifndef __linux__ | ||
36 | pd_error(x, "midiin: works under Linux only"); | ||
37 | #endif | ||
38 | return (x); | ||
39 | } | ||
40 | |||
41 | static void midiin_list(t_midiin *x, t_symbol *s, int ac, t_atom *av) | ||
42 | { | ||
43 | outlet_float(x->x_outlet2, atom_getfloatarg(1, ac, av) + 1); | ||
44 | outlet_float(x->x_outlet1, atom_getfloatarg(0, ac, av)); | ||
45 | } | ||
46 | |||
47 | static void midiin_free(t_midiin *x) | ||
48 | { | ||
49 | pd_unbind(&x->x_obj.ob_pd, midiin_sym); | ||
50 | } | ||
51 | |||
52 | static void *sysexin_new( void) | ||
53 | { | ||
54 | t_midiin *x = (t_midiin *)pd_new(sysexin_class); | ||
55 | x->x_outlet1 = outlet_new(&x->x_obj, &s_float); | ||
56 | x->x_outlet2 = outlet_new(&x->x_obj, &s_float); | ||
57 | pd_bind(&x->x_obj.ob_pd, sysexin_sym); | ||
58 | #ifndef __linux__ | ||
59 | pd_error(x, "sysexin: works under Linux only"); | ||
60 | #endif | ||
61 | return (x); | ||
62 | } | ||
63 | |||
64 | static void sysexin_free(t_midiin *x) | ||
65 | { | ||
66 | pd_unbind(&x->x_obj.ob_pd, sysexin_sym); | ||
67 | } | ||
68 | |||
69 | static void midiin_setup(void) | ||
70 | { | ||
71 | midiin_class = class_new(gensym("midiin"), (t_newmethod)midiin_new, | ||
72 | (t_method)midiin_free, sizeof(t_midiin), | ||
73 | CLASS_NOINLET, A_DEFFLOAT, 0); | ||
74 | class_addlist(midiin_class, midiin_list); | ||
75 | class_sethelpsymbol(midiin_class, gensym("midi")); | ||
76 | midiin_sym = gensym("#midiin"); | ||
77 | |||
78 | sysexin_class = class_new(gensym("sysexin"), (t_newmethod)sysexin_new, | ||
79 | (t_method)sysexin_free, sizeof(t_midiin), | ||
80 | CLASS_NOINLET, A_DEFFLOAT, 0); | ||
81 | class_addlist(sysexin_class, midiin_list); | ||
82 | class_sethelpsymbol(sysexin_class, gensym("midi")); | ||
83 | sysexin_sym = gensym("#sysexin"); | ||
84 | } | ||
85 | |||
86 | void inmidi_byte(int portno, int byte) | ||
87 | { | ||
88 | t_atom at[2]; | ||
89 | if (midiin_sym->s_thing) | ||
90 | { | ||
91 | SETFLOAT(at, byte); | ||
92 | SETFLOAT(at+1, portno + 1); | ||
93 | pd_list(midiin_sym->s_thing, 0, 2, at); | ||
94 | } | ||
95 | } | ||
96 | |||
97 | void inmidi_sysex(int portno, int byte) | ||
98 | { | ||
99 | t_atom at[2]; | ||
100 | if (sysexin_sym->s_thing) | ||
101 | { | ||
102 | SETFLOAT(at, byte); | ||
103 | SETFLOAT(at+1, portno + 1); | ||
104 | pd_list(sysexin_sym->s_thing, 0, 2, at); | ||
105 | } | ||
106 | } | ||
107 | |||
108 | /* ----------------------- notein ------------------------- */ | ||
109 | |||
110 | static t_symbol *notein_sym; | ||
111 | |||
112 | static t_class *notein_class; | ||
113 | |||
114 | typedef struct _notein | ||
115 | { | ||
116 | t_object x_obj; | ||
117 | t_float x_channel; | ||
118 | t_outlet *x_outlet1; | ||
119 | t_outlet *x_outlet2; | ||
120 | t_outlet *x_outlet3; | ||
121 | } t_notein; | ||
122 | |||
123 | static void *notein_new(t_floatarg f) | ||
124 | { | ||
125 | t_notein *x = (t_notein *)pd_new(notein_class); | ||
126 | x->x_channel = f; | ||
127 | x->x_outlet1 = outlet_new(&x->x_obj, &s_float); | ||
128 | x->x_outlet2 = outlet_new(&x->x_obj, &s_float); | ||
129 | if (f == 0) x->x_outlet3 = outlet_new(&x->x_obj, &s_float); | ||
130 | pd_bind(&x->x_obj.ob_pd, notein_sym); | ||
131 | return (x); | ||
132 | } | ||
133 | |||
134 | static void notein_list(t_notein *x, t_symbol *s, int argc, t_atom *argv) | ||
135 | { | ||
136 | float pitch = atom_getfloatarg(0, argc, argv); | ||
137 | float velo = atom_getfloatarg(1, argc, argv); | ||
138 | float channel = atom_getfloatarg(2, argc, argv); | ||
139 | if (x->x_channel != 0) | ||
140 | { | ||
141 | if (channel != x->x_channel) return; | ||
142 | outlet_float(x->x_outlet2, velo); | ||
143 | outlet_float(x->x_outlet1, pitch); | ||
144 | } | ||
145 | else | ||
146 | { | ||
147 | outlet_float(x->x_outlet3, channel); | ||
148 | outlet_float(x->x_outlet2, velo); | ||
149 | outlet_float(x->x_outlet1, pitch); | ||
150 | } | ||
151 | } | ||
152 | |||
153 | static void notein_free(t_notein *x) | ||
154 | { | ||
155 | pd_unbind(&x->x_obj.ob_pd, notein_sym); | ||
156 | } | ||
157 | |||
158 | static void notein_setup(void) | ||
159 | { | ||
160 | notein_class = class_new(gensym("notein"), (t_newmethod)notein_new, | ||
161 | (t_method)notein_free, sizeof(t_notein), CLASS_NOINLET, A_DEFFLOAT, 0); | ||
162 | class_addlist(notein_class, notein_list); | ||
163 | class_sethelpsymbol(notein_class, gensym("midi")); | ||
164 | notein_sym = gensym("#notein"); | ||
165 | } | ||
166 | |||
167 | void inmidi_noteon(int portno, int channel, int pitch, int velo) | ||
168 | { | ||
169 | if (notein_sym->s_thing) | ||
170 | { | ||
171 | t_atom at[3]; | ||
172 | SETFLOAT(at, pitch); | ||
173 | SETFLOAT(at+1, velo); | ||
174 | SETFLOAT(at+2, (channel + (portno << 4) + 1)); | ||
175 | pd_list(notein_sym->s_thing, &s_list, 3, at); | ||
176 | } | ||
177 | } | ||
178 | |||
179 | /* ----------------------- ctlin ------------------------- */ | ||
180 | |||
181 | static t_symbol *ctlin_sym; | ||
182 | |||
183 | static t_class *ctlin_class; | ||
184 | |||
185 | typedef struct _ctlin | ||
186 | { | ||
187 | t_object x_obj; | ||
188 | t_float x_channel; | ||
189 | t_float x_ctlno; | ||
190 | t_outlet *x_outlet1; | ||
191 | t_outlet *x_outlet2; | ||
192 | t_outlet *x_outlet3; | ||
193 | } t_ctlin; | ||
194 | |||
195 | static void *ctlin_new(t_symbol *s, int argc, t_atom *argv) | ||
196 | { | ||
197 | int ctlno, channel; | ||
198 | t_ctlin *x = (t_ctlin *)pd_new(ctlin_class); | ||
199 | if (!argc) ctlno = -1; | ||
200 | else ctlno = atom_getfloatarg(0, argc, argv); | ||
201 | channel = atom_getfloatarg(1, argc, argv); | ||
202 | x->x_channel = channel; | ||
203 | x->x_ctlno = ctlno; | ||
204 | x->x_outlet1 = outlet_new(&x->x_obj, &s_float); | ||
205 | if (!channel) | ||
206 | { | ||
207 | if (x->x_ctlno < 0) x->x_outlet2 = outlet_new(&x->x_obj, &s_float); | ||
208 | x->x_outlet3 = outlet_new(&x->x_obj, &s_float); | ||
209 | } | ||
210 | pd_bind(&x->x_obj.ob_pd, ctlin_sym); | ||
211 | return (x); | ||
212 | } | ||
213 | |||
214 | static void ctlin_list(t_ctlin *x, t_symbol *s, int argc, t_atom *argv) | ||
215 | { | ||
216 | t_float ctlnumber = atom_getfloatarg(0, argc, argv); | ||
217 | t_float value = atom_getfloatarg(1, argc, argv); | ||
218 | t_float channel = atom_getfloatarg(2, argc, argv); | ||
219 | if (x->x_ctlno >= 0 && x->x_ctlno != ctlnumber) return; | ||
220 | if (x->x_channel > 0 && x->x_channel != channel) return; | ||
221 | if (x->x_channel == 0) outlet_float(x->x_outlet3, channel); | ||
222 | if (x->x_ctlno < 0) outlet_float(x->x_outlet2, ctlnumber); | ||
223 | outlet_float(x->x_outlet1, value); | ||
224 | } | ||
225 | |||
226 | static void ctlin_free(t_ctlin *x) | ||
227 | { | ||
228 | pd_unbind(&x->x_obj.ob_pd, ctlin_sym); | ||
229 | } | ||
230 | |||
231 | static void ctlin_setup(void) | ||
232 | { | ||
233 | ctlin_class = class_new(gensym("ctlin"), (t_newmethod)ctlin_new, | ||
234 | (t_method)ctlin_free, sizeof(t_ctlin), | ||
235 | CLASS_NOINLET, A_GIMME, 0); | ||
236 | class_addlist(ctlin_class, ctlin_list); | ||
237 | class_sethelpsymbol(ctlin_class, gensym("midi")); | ||
238 | ctlin_sym = gensym("#ctlin"); | ||
239 | } | ||
240 | |||
241 | void inmidi_controlchange(int portno, int channel, int ctlnumber, int value) | ||
242 | { | ||
243 | if (ctlin_sym->s_thing) | ||
244 | { | ||
245 | t_atom at[3]; | ||
246 | SETFLOAT(at, ctlnumber); | ||
247 | SETFLOAT(at+1, value); | ||
248 | SETFLOAT(at+2, (channel + (portno << 4) + 1)); | ||
249 | pd_list(ctlin_sym->s_thing, &s_list, 3, at); | ||
250 | } | ||
251 | } | ||
252 | |||
253 | /* ----------------------- pgmin ------------------------- */ | ||
254 | |||
255 | static t_symbol *pgmin_sym; | ||
256 | |||
257 | static t_class *pgmin_class; | ||
258 | |||
259 | typedef struct _pgmin | ||
260 | { | ||
261 | t_object x_obj; | ||
262 | t_float x_channel; | ||
263 | t_outlet *x_outlet1; | ||
264 | t_outlet *x_outlet2; | ||
265 | } t_pgmin; | ||
266 | |||
267 | static void *pgmin_new(t_floatarg f) | ||
268 | { | ||
269 | t_pgmin *x = (t_pgmin *)pd_new(pgmin_class); | ||
270 | x->x_channel = f; | ||
271 | x->x_outlet1 = outlet_new(&x->x_obj, &s_float); | ||
272 | if (f == 0) x->x_outlet2 = outlet_new(&x->x_obj, &s_float); | ||
273 | pd_bind(&x->x_obj.ob_pd, pgmin_sym); | ||
274 | return (x); | ||
275 | } | ||
276 | |||
277 | static void pgmin_list(t_pgmin *x, t_symbol *s, int argc, t_atom *argv) | ||
278 | { | ||
279 | float value = atom_getfloatarg(0, argc, argv); | ||
280 | float channel = atom_getfloatarg(1, argc, argv); | ||
281 | if (x->x_channel != 0) | ||
282 | { | ||
283 | if (channel != x->x_channel) return; | ||
284 | outlet_float(x->x_outlet1, value); | ||
285 | } | ||
286 | else | ||
287 | { | ||
288 | outlet_float(x->x_outlet2, channel); | ||
289 | outlet_float(x->x_outlet1, value); | ||
290 | } | ||
291 | } | ||
292 | |||
293 | static void pgmin_free(t_pgmin *x) | ||
294 | { | ||
295 | pd_unbind(&x->x_obj.ob_pd, pgmin_sym); | ||
296 | } | ||
297 | |||
298 | static void pgmin_setup(void) | ||
299 | { | ||
300 | pgmin_class = class_new(gensym("pgmin"), (t_newmethod)pgmin_new, | ||
301 | (t_method)pgmin_free, sizeof(t_pgmin), | ||
302 | CLASS_NOINLET, A_DEFFLOAT, 0); | ||
303 | class_addlist(pgmin_class, pgmin_list); | ||
304 | class_sethelpsymbol(pgmin_class, gensym("midi")); | ||
305 | pgmin_sym = gensym("#pgmin"); | ||
306 | } | ||
307 | |||
308 | void inmidi_programchange(int portno, int channel, int value) | ||
309 | { | ||
310 | if (pgmin_sym->s_thing) | ||
311 | { | ||
312 | t_atom at[2]; | ||
313 | SETFLOAT(at, value + 1); | ||
314 | SETFLOAT(at+1, (channel + (portno << 4) + 1)); | ||
315 | pd_list(pgmin_sym->s_thing, &s_list, 2, at); | ||
316 | } | ||
317 | } | ||
318 | |||
319 | /* ----------------------- bendin ------------------------- */ | ||
320 | |||
321 | static t_symbol *bendin_sym; | ||
322 | |||
323 | static t_class *bendin_class; | ||
324 | |||
325 | typedef struct _bendin | ||
326 | { | ||
327 | t_object x_obj; | ||
328 | t_float x_channel; | ||
329 | t_outlet *x_outlet1; | ||
330 | t_outlet *x_outlet2; | ||
331 | } t_bendin; | ||
332 | |||
333 | static void *bendin_new(t_floatarg f) | ||
334 | { | ||
335 | t_bendin *x = (t_bendin *)pd_new(bendin_class); | ||
336 | x->x_channel = f; | ||
337 | x->x_outlet1 = outlet_new(&x->x_obj, &s_float); | ||
338 | if (f == 0) x->x_outlet2 = outlet_new(&x->x_obj, &s_float); | ||
339 | pd_bind(&x->x_obj.ob_pd, bendin_sym); | ||
340 | return (x); | ||
341 | } | ||
342 | |||
343 | static void bendin_list(t_bendin *x, t_symbol *s, int argc, t_atom *argv) | ||
344 | { | ||
345 | t_float value = atom_getfloatarg(0, argc, argv); | ||
346 | t_float channel = atom_getfloatarg(1, argc, argv); | ||
347 | if (x->x_channel != 0) | ||
348 | { | ||
349 | if (channel != x->x_channel) return; | ||
350 | outlet_float(x->x_outlet1, value); | ||
351 | } | ||
352 | else | ||
353 | { | ||
354 | outlet_float(x->x_outlet2, channel); | ||
355 | outlet_float(x->x_outlet1, value); | ||
356 | } | ||
357 | } | ||
358 | |||
359 | static void bendin_free(t_bendin *x) | ||
360 | { | ||
361 | pd_unbind(&x->x_obj.ob_pd, bendin_sym); | ||
362 | } | ||
363 | |||
364 | static void bendin_setup(void) | ||
365 | { | ||
366 | bendin_class = class_new(gensym("bendin"), (t_newmethod)bendin_new, | ||
367 | (t_method)bendin_free, sizeof(t_bendin), CLASS_NOINLET, A_DEFFLOAT, 0); | ||
368 | class_addlist(bendin_class, bendin_list); | ||
369 | class_sethelpsymbol(bendin_class, gensym("midi")); | ||
370 | bendin_sym = gensym("#bendin"); | ||
371 | } | ||
372 | |||
373 | void inmidi_pitchbend(int portno, int channel, int value) | ||
374 | { | ||
375 | if (bendin_sym->s_thing) | ||
376 | { | ||
377 | t_atom at[2]; | ||
378 | SETFLOAT(at, value); | ||
379 | SETFLOAT(at+1, (channel + (portno << 4) + 1)); | ||
380 | pd_list(bendin_sym->s_thing, &s_list, 2, at); | ||
381 | } | ||
382 | } | ||
383 | |||
384 | /* ----------------------- touchin ------------------------- */ | ||
385 | |||
386 | static t_symbol *touchin_sym; | ||
387 | |||
388 | static t_class *touchin_class; | ||
389 | |||
390 | typedef struct _touchin | ||
391 | { | ||
392 | t_object x_obj; | ||
393 | t_float x_channel; | ||
394 | t_outlet *x_outlet1; | ||
395 | t_outlet *x_outlet2; | ||
396 | } t_touchin; | ||
397 | |||
398 | static void *touchin_new(t_floatarg f) | ||
399 | { | ||
400 | t_touchin *x = (t_touchin *)pd_new(touchin_class); | ||
401 | x->x_channel = f; | ||
402 | x->x_outlet1 = outlet_new(&x->x_obj, &s_float); | ||
403 | if (f == 0) x->x_outlet2 = outlet_new(&x->x_obj, &s_float); | ||
404 | pd_bind(&x->x_obj.ob_pd, touchin_sym); | ||
405 | return (x); | ||
406 | } | ||
407 | |||
408 | static void touchin_list(t_touchin *x, t_symbol *s, int argc, t_atom *argv) | ||
409 | { | ||
410 | t_float value = atom_getfloatarg(0, argc, argv); | ||
411 | t_float channel = atom_getfloatarg(1, argc, argv); | ||
412 | if (x->x_channel) | ||
413 | { | ||
414 | if (channel != x->x_channel) return; | ||
415 | outlet_float(x->x_outlet1, value); | ||
416 | } | ||
417 | else | ||
418 | { | ||
419 | outlet_float(x->x_outlet2, channel); | ||
420 | outlet_float(x->x_outlet1, value); | ||
421 | } | ||
422 | } | ||
423 | |||
424 | static void touchin_free(t_touchin *x) | ||
425 | { | ||
426 | pd_unbind(&x->x_obj.ob_pd, touchin_sym); | ||
427 | } | ||
428 | |||
429 | static void touchin_setup(void) | ||
430 | { | ||
431 | touchin_class = class_new(gensym("touchin"), (t_newmethod)touchin_new, | ||
432 | (t_method)touchin_free, sizeof(t_touchin), | ||
433 | CLASS_NOINLET, A_DEFFLOAT, 0); | ||
434 | class_addlist(touchin_class, touchin_list); | ||
435 | class_sethelpsymbol(touchin_class, gensym("midi")); | ||
436 | touchin_sym = gensym("#touchin"); | ||
437 | } | ||
438 | |||
439 | void inmidi_aftertouch(int portno, int channel, int value) | ||
440 | { | ||
441 | if (touchin_sym->s_thing) | ||
442 | { | ||
443 | t_atom at[2]; | ||
444 | SETFLOAT(at, value); | ||
445 | SETFLOAT(at+1, (channel + (portno << 4) + 1)); | ||
446 | pd_list(touchin_sym->s_thing, &s_list, 2, at); | ||
447 | } | ||
448 | } | ||
449 | |||
450 | /* ----------------------- polytouchin ------------------------- */ | ||
451 | |||
452 | static t_symbol *polytouchin_sym; | ||
453 | |||
454 | static t_class *polytouchin_class; | ||
455 | |||
456 | typedef struct _polytouchin | ||
457 | { | ||
458 | t_object x_obj; | ||
459 | t_float x_channel; | ||
460 | t_outlet *x_outlet1; | ||
461 | t_outlet *x_outlet2; | ||
462 | t_outlet *x_outlet3; | ||
463 | } t_polytouchin; | ||
464 | |||
465 | static void *polytouchin_new(t_floatarg f) | ||
466 | { | ||
467 | t_polytouchin *x = (t_polytouchin *)pd_new(polytouchin_class); | ||
468 | x->x_channel = f; | ||
469 | x->x_outlet1 = outlet_new(&x->x_obj, &s_float); | ||
470 | x->x_outlet2 = outlet_new(&x->x_obj, &s_float); | ||
471 | if (f == 0) x->x_outlet3 = outlet_new(&x->x_obj, &s_float); | ||
472 | pd_bind(&x->x_obj.ob_pd, polytouchin_sym); | ||
473 | return (x); | ||
474 | } | ||
475 | |||
476 | static void polytouchin_list(t_polytouchin *x, t_symbol *s, int argc, | ||
477 | t_atom *argv) | ||
478 | { | ||
479 | t_float pitch = atom_getfloatarg(0, argc, argv); | ||
480 | t_float value = atom_getfloatarg(1, argc, argv); | ||
481 | t_float channel = atom_getfloatarg(2, argc, argv); | ||
482 | if (x->x_channel != 0) | ||
483 | { | ||
484 | if (channel != x->x_channel) return; | ||
485 | outlet_float(x->x_outlet2, pitch); | ||
486 | outlet_float(x->x_outlet1, value); | ||
487 | } | ||
488 | else | ||
489 | { | ||
490 | outlet_float(x->x_outlet3, channel); | ||
491 | outlet_float(x->x_outlet2, pitch); | ||
492 | outlet_float(x->x_outlet1, value); | ||
493 | } | ||
494 | } | ||
495 | |||
496 | static void polytouchin_free(t_polytouchin *x) | ||
497 | { | ||
498 | pd_unbind(&x->x_obj.ob_pd, polytouchin_sym); | ||
499 | } | ||
500 | |||
501 | static void polytouchin_setup(void) | ||
502 | { | ||
503 | polytouchin_class = class_new(gensym("polytouchin"), | ||
504 | (t_newmethod)polytouchin_new, (t_method)polytouchin_free, | ||
505 | sizeof(t_polytouchin), CLASS_NOINLET, A_DEFFLOAT, 0); | ||
506 | class_addlist(polytouchin_class, polytouchin_list); | ||
507 | class_sethelpsymbol(polytouchin_class, gensym("midi")); | ||
508 | polytouchin_sym = gensym("#polytouchin"); | ||
509 | } | ||
510 | |||
511 | void inmidi_polyaftertouch(int portno, int channel, int pitch, int value) | ||
512 | { | ||
513 | if (polytouchin_sym->s_thing) | ||
514 | { | ||
515 | t_atom at[3]; | ||
516 | SETFLOAT(at, pitch); | ||
517 | SETFLOAT(at+1, value); | ||
518 | SETFLOAT(at+2, (channel + (portno << 4) + 1)); | ||
519 | pd_list(polytouchin_sym->s_thing, &s_list, 3, at); | ||
520 | } | ||
521 | } | ||
522 | |||
523 | /*----------------------- midiclkin--(midi F8 message )---------------------*/ | ||
524 | static t_symbol *midiclkin_sym; | ||
525 | |||
526 | static t_class *midiclkin_class; | ||
527 | |||
528 | |||
529 | typedef struct _midiclkin | ||
530 | { | ||
531 | t_object x_obj; | ||
532 | t_outlet *x_outlet1; | ||
533 | t_outlet *x_outlet2; | ||
534 | } t_midiclkin; | ||
535 | |||
536 | static void *midiclkin_new(t_floatarg f) | ||
537 | { | ||
538 | t_midiclkin *x = (t_midiclkin *)pd_new(midiclkin_class); | ||
539 | x->x_outlet1 = outlet_new(&x->x_obj, &s_float); | ||
540 | x->x_outlet2 = outlet_new(&x->x_obj, &s_float); | ||
541 | pd_bind(&x->x_obj.ob_pd, midiclkin_sym); | ||
542 | return (x); | ||
543 | } | ||
544 | |||
545 | static void midiclkin_list(t_midiclkin *x, t_symbol *s, int argc, t_atom *argv) | ||
546 | { | ||
547 | float value = atom_getfloatarg(0, argc, argv); | ||
548 | float count = atom_getfloatarg(1, argc, argv); | ||
549 | outlet_float(x->x_outlet2, count); | ||
550 | outlet_float(x->x_outlet1, value); | ||
551 | } | ||
552 | |||
553 | static void midiclkin_free(t_midiclkin *x) | ||
554 | { | ||
555 | pd_unbind(&x->x_obj.ob_pd, midiclkin_sym); | ||
556 | } | ||
557 | |||
558 | static void midiclkin_setup(void) | ||
559 | { | ||
560 | midiclkin_class = class_new(gensym("midiclkin"), | ||
561 | (t_newmethod)midiclkin_new, (t_method)midiclkin_free, | ||
562 | sizeof(t_midiclkin), CLASS_NOINLET, A_DEFFLOAT, 0); | ||
563 | class_addlist(midiclkin_class, midiclkin_list); | ||
564 | class_sethelpsymbol(midiclkin_class, gensym("midi")); | ||
565 | midiclkin_sym = gensym("#midiclkin"); | ||
566 | } | ||
567 | |||
568 | void inmidi_clk(double timing) | ||
569 | { | ||
570 | |||
571 | static float prev = 0; | ||
572 | static float count = 0; | ||
573 | float cur,diff; | ||
574 | |||
575 | if (midiclkin_sym->s_thing) | ||
576 | { | ||
577 | t_atom at[2]; | ||
578 | diff =timing - prev; | ||
579 | count++; | ||
580 | |||
581 | if (count == 3) | ||
582 | { /* 24 count per quoter note */ | ||
583 | SETFLOAT(at, 1 ); | ||
584 | count = 0; | ||
585 | } | ||
586 | else SETFLOAT(at, 0); | ||
587 | |||
588 | SETFLOAT(at+1, diff); | ||
589 | pd_list(midiclkin_sym->s_thing, &s_list, 2, at); | ||
590 | prev = timing; | ||
591 | } | ||
592 | } | ||
593 | |||
594 | /*----------midirealtimein (midi FA,FB,FC,FF message )-----------------*/ | ||
595 | |||
596 | static t_symbol *midirealtimein_sym; | ||
597 | |||
598 | static t_class *midirealtimein_class; | ||
599 | |||
600 | typedef struct _midirealtimein | ||
601 | { | ||
602 | t_object x_obj; | ||
603 | t_outlet *x_outlet1; | ||
604 | t_outlet *x_outlet2; | ||
605 | } t_midirealtimein; | ||
606 | |||
607 | static void *midirealtimein_new( void) | ||
608 | { | ||
609 | t_midirealtimein *x = (t_midirealtimein *)pd_new(midirealtimein_class); | ||
610 | x->x_outlet1 = outlet_new(&x->x_obj, &s_float); | ||
611 | x->x_outlet2 = outlet_new(&x->x_obj, &s_float); | ||
612 | pd_bind(&x->x_obj.ob_pd, midirealtimein_sym); | ||
613 | #ifndef MSW | ||
614 | pd_error(x, "midirealtimein: works under MSW only"); | ||
615 | #endif | ||
616 | return (x); | ||
617 | } | ||
618 | |||
619 | static void midirealtimein_list(t_midirealtimein *x, t_symbol *s, | ||
620 | int argc, t_atom *argv) | ||
621 | { | ||
622 | float portno = atom_getfloatarg(0, argc, argv); | ||
623 | float byte = atom_getfloatarg(1, argc, argv); | ||
624 | |||
625 | outlet_float(x->x_outlet2, portno); | ||
626 | outlet_float(x->x_outlet1, byte); | ||
627 | } | ||
628 | |||
629 | static void midirealtimein_free(t_midirealtimein *x) | ||
630 | { | ||
631 | pd_unbind(&x->x_obj.ob_pd, midirealtimein_sym); | ||
632 | } | ||
633 | |||
634 | static void midirealtimein_setup(void) | ||
635 | { | ||
636 | midirealtimein_class = class_new(gensym("midirealtimein"), | ||
637 | (t_newmethod)midirealtimein_new, (t_method)midirealtimein_free, | ||
638 | sizeof(t_midirealtimein), CLASS_NOINLET, A_DEFFLOAT, 0); | ||
639 | class_addlist(midirealtimein_class, midirealtimein_list); | ||
640 | class_sethelpsymbol(midirealtimein_class, gensym("midi")); | ||
641 | midirealtimein_sym = gensym("#midirealtimein"); | ||
642 | } | ||
643 | |||
644 | void inmidi_realtimein(int portno, int SysMsg) | ||
645 | { | ||
646 | if (midirealtimein_sym->s_thing) | ||
647 | { | ||
648 | t_atom at[2]; | ||
649 | SETFLOAT(at, portno); | ||
650 | SETFLOAT(at+1, SysMsg); | ||
651 | pd_list(midirealtimein_sym->s_thing, &s_list, 1, at); | ||
652 | } | ||
653 | } | ||
654 | |||
655 | /* -------------------------- midiout -------------------------- */ | ||
656 | |||
657 | static t_class *midiout_class; | ||
658 | |||
659 | void sys_putmidibyte(int portno, int byte); | ||
660 | |||
661 | typedef struct _midiout | ||
662 | { | ||
663 | t_object x_obj; | ||
664 | t_float x_portno; | ||
665 | } t_midiout; | ||
666 | |||
667 | static void *midiout_new(t_floatarg portno) | ||
668 | { | ||
669 | t_midiout *x = (t_midiout *)pd_new(midiout_class); | ||
670 | if (portno <= 0) portno = 1; | ||
671 | x->x_portno = portno; | ||
672 | floatinlet_new(&x->x_obj, &x->x_portno); | ||
673 | #ifdef __irix__ | ||
674 | post("midiout: unimplemented in IRIX"); | ||
675 | #endif | ||
676 | return (x); | ||
677 | } | ||
678 | |||
679 | static void midiout_float(t_midiout *x, t_floatarg f) | ||
680 | { | ||
681 | sys_putmidibyte(x->x_portno - 1, f); | ||
682 | } | ||
683 | |||
684 | static void midiout_setup(void) | ||
685 | { | ||
686 | midiout_class = class_new(gensym("midiout"), (t_newmethod)midiout_new, 0, | ||
687 | sizeof(t_midiout), 0, A_DEFFLOAT, A_DEFFLOAT, 0); | ||
688 | class_addfloat(midiout_class, midiout_float); | ||
689 | class_sethelpsymbol(midiout_class, gensym("midi")); | ||
690 | } | ||
691 | |||
692 | /* -------------------------- noteout -------------------------- */ | ||
693 | |||
694 | static t_class *noteout_class; | ||
695 | |||
696 | typedef struct _noteout | ||
697 | { | ||
698 | t_object x_obj; | ||
699 | t_float x_velo; | ||
700 | t_float x_channel; | ||
701 | } t_noteout; | ||
702 | |||
703 | static void *noteout_new(t_floatarg channel) | ||
704 | { | ||
705 | t_noteout *x = (t_noteout *)pd_new(noteout_class); | ||
706 | x->x_velo = 0; | ||
707 | if (channel < 1) channel = 1; | ||
708 | x->x_channel = channel; | ||
709 | floatinlet_new(&x->x_obj, &x->x_velo); | ||
710 | floatinlet_new(&x->x_obj, &x->x_channel); | ||
711 | return (x); | ||
712 | } | ||
713 | |||
714 | static void noteout_float(t_noteout *x, t_float f) | ||
715 | { | ||
716 | int binchan = x->x_channel - 1; | ||
717 | if (binchan < 0) | ||
718 | binchan = 0; | ||
719 | outmidi_noteon((binchan >> 4), | ||
720 | (binchan & 15), (int)f, (int)x->x_velo); | ||
721 | } | ||
722 | |||
723 | static void noteout_setup(void) | ||
724 | { | ||
725 | noteout_class = class_new(gensym("noteout"), (t_newmethod)noteout_new, 0, | ||
726 | sizeof(t_noteout), 0, A_DEFFLOAT, 0); | ||
727 | class_addfloat(noteout_class, noteout_float); | ||
728 | class_sethelpsymbol(noteout_class, gensym("midi")); | ||
729 | } | ||
730 | |||
731 | |||
732 | /* -------------------------- ctlout -------------------------- */ | ||
733 | |||
734 | static t_class *ctlout_class; | ||
735 | |||
736 | typedef struct _ctlout | ||
737 | { | ||
738 | t_object x_obj; | ||
739 | t_float x_ctl; | ||
740 | t_float x_channel; | ||
741 | } t_ctlout; | ||
742 | |||
743 | static void *ctlout_new(t_floatarg ctl, t_floatarg channel) | ||
744 | { | ||
745 | t_ctlout *x = (t_ctlout *)pd_new(ctlout_class); | ||
746 | x->x_ctl = ctl; | ||
747 | if (channel <= 0) channel = 1; | ||
748 | x->x_channel = channel; | ||
749 | floatinlet_new(&x->x_obj, &x->x_ctl); | ||
750 | floatinlet_new(&x->x_obj, &x->x_channel); | ||
751 | return (x); | ||
752 | } | ||
753 | |||
754 | static void ctlout_float(t_ctlout *x, t_float f) | ||
755 | { | ||
756 | int binchan = x->x_channel - 1; | ||
757 | if (binchan < 0) | ||
758 | binchan = 0; | ||
759 | outmidi_controlchange((binchan >> 4), | ||
760 | (binchan & 15), (int)(x->x_ctl), (int)f); | ||
761 | } | ||
762 | |||
763 | static void ctlout_setup(void) | ||
764 | { | ||
765 | ctlout_class = class_new(gensym("ctlout"), (t_newmethod)ctlout_new, 0, | ||
766 | sizeof(t_ctlout), 0, A_DEFFLOAT, A_DEFFLOAT, 0); | ||
767 | class_addfloat(ctlout_class, ctlout_float); | ||
768 | class_sethelpsymbol(ctlout_class, gensym("midi")); | ||
769 | } | ||
770 | |||
771 | |||
772 | /* -------------------------- pgmout -------------------------- */ | ||
773 | |||
774 | static t_class *pgmout_class; | ||
775 | |||
776 | typedef struct _pgmout | ||
777 | { | ||
778 | t_object x_obj; | ||
779 | t_float x_channel; | ||
780 | } t_pgmout; | ||
781 | |||
782 | static void *pgmout_new(t_floatarg channel) | ||
783 | { | ||
784 | t_pgmout *x = (t_pgmout *)pd_new(pgmout_class); | ||
785 | if (channel <= 0) channel = 1; | ||
786 | x->x_channel = channel; | ||
787 | floatinlet_new(&x->x_obj, &x->x_channel); | ||
788 | return (x); | ||
789 | } | ||
790 | |||
791 | static void pgmout_float(t_pgmout *x, t_floatarg f) | ||
792 | { | ||
793 | int binchan = x->x_channel - 1; | ||
794 | int n = f - 1; | ||
795 | if (binchan < 0) | ||
796 | binchan = 0; | ||
797 | if (n < 0) n = 0; | ||
798 | else if (n > 127) n = 127; | ||
799 | outmidi_programchange((binchan >> 4), | ||
800 | (binchan & 15), n); | ||
801 | } | ||
802 | |||
803 | static void pgmout_setup(void) | ||
804 | { | ||
805 | pgmout_class = class_new(gensym("pgmout"), (t_newmethod)pgmout_new, 0, | ||
806 | sizeof(t_pgmout), 0, A_DEFFLOAT, 0); | ||
807 | class_addfloat(pgmout_class, pgmout_float); | ||
808 | class_sethelpsymbol(pgmout_class, gensym("midi")); | ||
809 | } | ||
810 | |||
811 | |||
812 | /* -------------------------- bendout -------------------------- */ | ||
813 | |||
814 | static t_class *bendout_class; | ||
815 | |||
816 | typedef struct _bendout | ||
817 | { | ||
818 | t_object x_obj; | ||
819 | t_float x_channel; | ||
820 | } t_bendout; | ||
821 | |||
822 | static void *bendout_new(t_floatarg channel) | ||
823 | { | ||
824 | t_bendout *x = (t_bendout *)pd_new(bendout_class); | ||
825 | if (channel <= 0) channel = 1; | ||
826 | x->x_channel = channel; | ||
827 | floatinlet_new(&x->x_obj, &x->x_channel); | ||
828 | return (x); | ||
829 | } | ||
830 | |||
831 | static void bendout_float(t_bendout *x, t_float f) | ||
832 | { | ||
833 | int binchan = x->x_channel - 1; | ||
834 | int n = (int)f + 8192; | ||
835 | if (binchan < 0) | ||
836 | binchan = 0; | ||
837 | outmidi_pitchbend((binchan >> 4), (binchan & 15), n); | ||
838 | } | ||
839 | |||
840 | static void bendout_setup(void) | ||
841 | { | ||
842 | bendout_class = class_new(gensym("bendout"), (t_newmethod)bendout_new, 0, | ||
843 | sizeof(t_bendout), 0, A_DEFFLOAT, 0); | ||
844 | class_addfloat(bendout_class, bendout_float); | ||
845 | class_sethelpsymbol(bendout_class, gensym("midi")); | ||
846 | } | ||
847 | |||
848 | /* -------------------------- touch -------------------------- */ | ||
849 | |||
850 | static t_class *touchout_class; | ||
851 | |||
852 | typedef struct _touchout | ||
853 | { | ||
854 | t_object x_obj; | ||
855 | t_float x_channel; | ||
856 | } t_touchout; | ||
857 | |||
858 | static void *touchout_new(t_floatarg channel) | ||
859 | { | ||
860 | t_touchout *x = (t_touchout *)pd_new(touchout_class); | ||
861 | if (channel <= 0) channel = 1; | ||
862 | x->x_channel = channel; | ||
863 | floatinlet_new(&x->x_obj, &x->x_channel); | ||
864 | return (x); | ||
865 | } | ||
866 | |||
867 | static void touchout_float(t_touchout *x, t_float f) | ||
868 | { | ||
869 | int binchan = x->x_channel - 1; | ||
870 | if (binchan < 0) | ||
871 | binchan = 0; | ||
872 | outmidi_aftertouch((binchan >> 4), (binchan & 15), (int)f); | ||
873 | } | ||
874 | |||
875 | static void touchout_setup(void) | ||
876 | { | ||
877 | touchout_class = class_new(gensym("touchout"), (t_newmethod)touchout_new, 0, | ||
878 | sizeof(t_touchout), 0, A_DEFFLOAT, 0); | ||
879 | class_addfloat(touchout_class, touchout_float); | ||
880 | class_sethelpsymbol(touchout_class, gensym("midi")); | ||
881 | } | ||
882 | |||
883 | /* -------------------------- polytouch -------------------------- */ | ||
884 | |||
885 | static t_class *polytouchout_class; | ||
886 | |||
887 | typedef struct _polytouchout | ||
888 | { | ||
889 | t_object x_obj; | ||
890 | t_float x_channel; | ||
891 | t_float x_pitch; | ||
892 | } t_polytouchout; | ||
893 | |||
894 | static void *polytouchout_new(t_floatarg channel) | ||
895 | { | ||
896 | t_polytouchout *x = (t_polytouchout *)pd_new(polytouchout_class); | ||
897 | if (channel <= 0) channel = 1; | ||
898 | x->x_channel = channel; | ||
899 | x->x_pitch = 0; | ||
900 | floatinlet_new(&x->x_obj, &x->x_pitch); | ||
901 | floatinlet_new(&x->x_obj, &x->x_channel); | ||
902 | return (x); | ||
903 | } | ||
904 | |||
905 | static void polytouchout_float(t_polytouchout *x, t_float n) | ||
906 | { | ||
907 | int binchan = x->x_channel - 1; | ||
908 | if (binchan < 0) | ||
909 | binchan = 0; | ||
910 | outmidi_polyaftertouch((binchan >> 4), (binchan & 15), x->x_pitch, n); | ||
911 | } | ||
912 | |||
913 | static void polytouchout_setup(void) | ||
914 | { | ||
915 | polytouchout_class = class_new(gensym("polytouchout"), | ||
916 | (t_newmethod)polytouchout_new, 0, | ||
917 | sizeof(t_polytouchout), 0, A_DEFFLOAT, 0); | ||
918 | class_addfloat(polytouchout_class, polytouchout_float); | ||
919 | class_sethelpsymbol(polytouchout_class, gensym("midi")); | ||
920 | } | ||
921 | |||
922 | /* -------------------------- makenote -------------------------- */ | ||
923 | |||
924 | static t_class *makenote_class; | ||
925 | |||
926 | typedef struct _hang | ||
927 | { | ||
928 | t_clock *h_clock; | ||
929 | struct _hang *h_next; | ||
930 | t_float h_pitch; | ||
931 | struct _makenote *h_owner; | ||
932 | } t_hang; | ||
933 | |||
934 | typedef struct _makenote | ||
935 | { | ||
936 | t_object x_obj; | ||
937 | t_float x_velo; | ||
938 | t_float x_dur; | ||
939 | t_outlet *x_pitchout; | ||
940 | t_outlet *x_velout; | ||
941 | t_hang *x_hang; | ||
942 | } t_makenote; | ||
943 | |||
944 | static void *makenote_new(t_floatarg velo, t_floatarg dur) | ||
945 | { | ||
946 | t_makenote *x = (t_makenote *)pd_new(makenote_class); | ||
947 | x->x_velo = velo; | ||
948 | x->x_dur = dur; | ||
949 | floatinlet_new(&x->x_obj, &x->x_velo); | ||
950 | floatinlet_new(&x->x_obj, &x->x_dur); | ||
951 | x->x_pitchout = outlet_new(&x->x_obj, &s_float); | ||
952 | x->x_velout = outlet_new(&x->x_obj, &s_float); | ||
953 | x->x_hang = 0; | ||
954 | return (x); | ||
955 | } | ||
956 | |||
957 | static void makenote_tick(t_hang *hang) | ||
958 | { | ||
959 | t_makenote *x = hang->h_owner; | ||
960 | t_hang *h2, *h3; | ||
961 | outlet_float(x->x_velout, 0); | ||
962 | outlet_float(x->x_pitchout, hang->h_pitch); | ||
963 | if (x->x_hang == hang) x->x_hang = hang->h_next; | ||
964 | else for (h2 = x->x_hang; h3 = h2->h_next; h2 = h3) | ||
965 | { | ||
966 | if (h3 == hang) | ||
967 | { | ||
968 | h2->h_next = h3->h_next; | ||
969 | break; | ||
970 | } | ||
971 | } | ||
972 | clock_free(hang->h_clock); | ||
973 | freebytes(hang, sizeof(*hang)); | ||
974 | } | ||
975 | |||
976 | static void makenote_float(t_makenote *x, t_float f) | ||
977 | { | ||
978 | t_hang *hang; | ||
979 | if (!x->x_velo) return; | ||
980 | outlet_float(x->x_velout, x->x_velo); | ||
981 | outlet_float(x->x_pitchout, f); | ||
982 | hang = (t_hang *)getbytes(sizeof *hang); | ||
983 | hang->h_next = x->x_hang; | ||
984 | x->x_hang = hang; | ||
985 | hang->h_pitch = f; | ||
986 | hang->h_owner = x; | ||
987 | hang->h_clock = clock_new(hang, (t_method)makenote_tick); | ||
988 | clock_delay(hang->h_clock, (x->x_dur >= 0 ? x->x_dur : 0)); | ||
989 | } | ||
990 | |||
991 | static void makenote_stop(t_makenote *x) | ||
992 | { | ||
993 | t_hang *hang; | ||
994 | while (hang = x->x_hang) | ||
995 | { | ||
996 | outlet_float(x->x_velout, 0); | ||
997 | outlet_float(x->x_pitchout, hang->h_pitch); | ||
998 | x->x_hang = hang->h_next; | ||
999 | clock_free(hang->h_clock); | ||
1000 | freebytes(hang, sizeof(*hang)); | ||
1001 | } | ||
1002 | } | ||
1003 | |||
1004 | static void makenote_clear(t_makenote *x) | ||
1005 | { | ||
1006 | t_hang *hang; | ||
1007 | while (hang = x->x_hang) | ||
1008 | { | ||
1009 | x->x_hang = hang->h_next; | ||
1010 | clock_free(hang->h_clock); | ||
1011 | freebytes(hang, sizeof(*hang)); | ||
1012 | } | ||
1013 | } | ||
1014 | |||
1015 | static void makenote_setup(void) | ||
1016 | { | ||
1017 | makenote_class = class_new(gensym("makenote"), | ||
1018 | (t_newmethod)makenote_new, (t_method)makenote_clear, | ||
1019 | sizeof(t_makenote), 0, A_DEFFLOAT, A_DEFFLOAT, 0); | ||
1020 | class_addfloat(makenote_class, makenote_float); | ||
1021 | class_addmethod(makenote_class, (t_method)makenote_stop, gensym("stop"), | ||
1022 | 0); | ||
1023 | class_addmethod(makenote_class, (t_method)makenote_clear, gensym("clear"), | ||
1024 | 0); | ||
1025 | } | ||
1026 | |||
1027 | /* -------------------------- stripnote -------------------------- */ | ||
1028 | |||
1029 | static t_class *stripnote_class; | ||
1030 | |||
1031 | typedef struct _stripnote | ||
1032 | { | ||
1033 | t_object x_obj; | ||
1034 | t_float x_velo; | ||
1035 | t_outlet *x_pitchout; | ||
1036 | t_outlet *x_velout; | ||
1037 | } t_stripnote; | ||
1038 | |||
1039 | static void *stripnote_new(void ) | ||
1040 | { | ||
1041 | t_stripnote *x = (t_stripnote *)pd_new(stripnote_class); | ||
1042 | floatinlet_new(&x->x_obj, &x->x_velo); | ||
1043 | x->x_pitchout = outlet_new(&x->x_obj, &s_float); | ||
1044 | x->x_velout = outlet_new(&x->x_obj, &s_float); | ||
1045 | return (x); | ||
1046 | } | ||
1047 | |||
1048 | static void stripnote_float(t_stripnote *x, t_float f) | ||
1049 | { | ||
1050 | t_hang *hang; | ||
1051 | if (!x->x_velo) return; | ||
1052 | outlet_float(x->x_velout, x->x_velo); | ||
1053 | outlet_float(x->x_pitchout, f); | ||
1054 | } | ||
1055 | |||
1056 | static void stripnote_setup(void) | ||
1057 | { | ||
1058 | stripnote_class = class_new(gensym("stripnote"), | ||
1059 | (t_newmethod)stripnote_new, 0, sizeof(t_stripnote), 0, 0); | ||
1060 | class_addfloat(stripnote_class, stripnote_float); | ||
1061 | } | ||
1062 | |||
1063 | /* -------------------------- poly -------------------------- */ | ||
1064 | |||
1065 | static t_class *poly_class; | ||
1066 | |||
1067 | typedef struct voice | ||
1068 | { | ||
1069 | float v_pitch; | ||
1070 | int v_used; | ||
1071 | unsigned long v_serial; | ||
1072 | } t_voice; | ||
1073 | |||
1074 | typedef struct poly | ||
1075 | { | ||
1076 | t_object x_obj; | ||
1077 | int x_n; | ||
1078 | t_voice *x_vec; | ||
1079 | float x_vel; | ||
1080 | t_outlet *x_pitchout; | ||
1081 | t_outlet *x_velout; | ||
1082 | unsigned long x_serial; | ||
1083 | int x_steal; | ||
1084 | } t_poly; | ||
1085 | |||
1086 | static void *poly_new(float fnvoice, float fsteal) | ||
1087 | { | ||
1088 | int i, n = fnvoice; | ||
1089 | t_poly *x = (t_poly *)pd_new(poly_class); | ||
1090 | t_voice *v; | ||
1091 | if (n < 1) n = 1; | ||
1092 | x->x_n = n; | ||
1093 | x->x_vec = (t_voice *)getbytes(n * sizeof(*x->x_vec)); | ||
1094 | for (v = x->x_vec, i = n; i--; v++) | ||
1095 | v->v_pitch = v->v_used = v->v_serial = 0; | ||
1096 | x->x_vel = 0; | ||
1097 | x->x_steal = (fsteal != 0); | ||
1098 | floatinlet_new(&x->x_obj, &x->x_vel); | ||
1099 | outlet_new(&x->x_obj, &s_float); | ||
1100 | x->x_pitchout = outlet_new(&x->x_obj, &s_float); | ||
1101 | x->x_velout = outlet_new(&x->x_obj, &s_float); | ||
1102 | x->x_serial = 0; | ||
1103 | return (x); | ||
1104 | } | ||
1105 | |||
1106 | static void poly_float(t_poly *x, t_float f) | ||
1107 | { | ||
1108 | int i; | ||
1109 | t_voice *v; | ||
1110 | t_voice *firston, *firstoff; | ||
1111 | unsigned int serialon, serialoff, onindex = 0, offindex = 0; | ||
1112 | if (x->x_vel > 0) | ||
1113 | { | ||
1114 | /* note on. Look for a vacant voice */ | ||
1115 | for (v = x->x_vec, i = 0, firston = firstoff = 0, | ||
1116 | serialon = serialoff = 0xffffffff; i < x->x_n; v++, i++) | ||
1117 | { | ||
1118 | if (v->v_used && v->v_serial < serialon) | ||
1119 | firston = v, serialon = v->v_serial, onindex = i; | ||
1120 | else if (!v->v_used && v->v_serial < serialoff) | ||
1121 | firstoff = v, serialoff = v->v_serial, offindex = i; | ||
1122 | } | ||
1123 | if (firstoff) | ||
1124 | { | ||
1125 | outlet_float(x->x_velout, x->x_vel); | ||
1126 | outlet_float(x->x_pitchout, firstoff->v_pitch = f); | ||
1127 | outlet_float(x->x_obj.ob_outlet, offindex+1); | ||
1128 | firstoff->v_used = 1; | ||
1129 | firstoff->v_serial = x->x_serial++; | ||
1130 | } | ||
1131 | /* if none, steal one */ | ||
1132 | else if (firston && x->x_steal) | ||
1133 | { | ||
1134 | outlet_float(x->x_velout, 0); | ||
1135 | outlet_float(x->x_pitchout, firston->v_pitch); | ||
1136 | outlet_float(x->x_obj.ob_outlet, onindex+1); | ||
1137 | outlet_float(x->x_velout, x->x_vel); | ||
1138 | outlet_float(x->x_pitchout, firston->v_pitch = f); | ||
1139 | outlet_float(x->x_obj.ob_outlet, onindex+1); | ||
1140 | firston->v_serial = x->x_serial++; | ||
1141 | } | ||
1142 | } | ||
1143 | else /* note off. Turn off oldest match */ | ||
1144 | { | ||
1145 | for (v = x->x_vec, i = 0, firston = 0, serialon = 0xffffffff; | ||
1146 | i < x->x_n; v++, i++) | ||
1147 | if (v->v_used && v->v_pitch == f && v->v_serial < serialon) | ||
1148 | firston = v, serialon = v->v_serial, onindex = i; | ||
1149 | if (firston) | ||
1150 | { | ||
1151 | firston->v_used = 0; | ||
1152 | firston->v_serial = x->x_serial++; | ||
1153 | outlet_float(x->x_velout, 0); | ||
1154 | outlet_float(x->x_pitchout, firston->v_pitch); | ||
1155 | outlet_float(x->x_obj.ob_outlet, onindex+1); | ||
1156 | } | ||
1157 | } | ||
1158 | } | ||
1159 | |||
1160 | static void poly_stop(t_poly *x) | ||
1161 | { | ||
1162 | int i; | ||
1163 | t_voice *v; | ||
1164 | for (i = 0, v = x->x_vec; i < x->x_n; i++, v++) | ||
1165 | if (v->v_used) | ||
1166 | { | ||
1167 | outlet_float(x->x_velout, 0L); | ||
1168 | outlet_float(x->x_pitchout, v->v_pitch); | ||
1169 | outlet_float(x->x_obj.ob_outlet, i+1); | ||
1170 | v->v_used = 0; | ||
1171 | v->v_serial = x->x_serial++; | ||
1172 | } | ||
1173 | } | ||
1174 | |||
1175 | static void poly_clear(t_poly *x) | ||
1176 | { | ||
1177 | int i; | ||
1178 | t_voice *v; | ||
1179 | for (v = x->x_vec, i = x->x_n; i--; v++) v->v_used = v->v_serial = 0; | ||
1180 | } | ||
1181 | |||
1182 | static void poly_free(t_poly *x) | ||
1183 | { | ||
1184 | freebytes(x->x_vec, x->x_n * sizeof (*x->x_vec)); | ||
1185 | } | ||
1186 | |||
1187 | static void poly_setup(void) | ||
1188 | { | ||
1189 | poly_class = class_new(gensym("poly"), | ||
1190 | (t_newmethod)poly_new, (t_method)poly_clear, | ||
1191 | sizeof(t_poly), 0, A_DEFFLOAT, A_DEFFLOAT, 0); | ||
1192 | class_addfloat(poly_class, poly_float); | ||
1193 | class_addmethod(poly_class, (t_method)poly_stop, gensym("stop"), 0); | ||
1194 | class_addmethod(poly_class, (t_method)poly_clear, gensym("clear"), 0); | ||
1195 | } | ||
1196 | |||
1197 | /* -------------------------- bag -------------------------- */ | ||
1198 | |||
1199 | static t_class *bag_class; | ||
1200 | |||
1201 | typedef struct _bagelem | ||
1202 | { | ||
1203 | struct _bagelem *e_next; | ||
1204 | t_float e_value; | ||
1205 | } t_bagelem; | ||
1206 | |||
1207 | typedef struct _bag | ||
1208 | { | ||
1209 | t_object x_obj; | ||
1210 | t_float x_velo; | ||
1211 | t_bagelem *x_first; | ||
1212 | } t_bag; | ||
1213 | |||
1214 | static void *bag_new(void ) | ||
1215 | { | ||
1216 | t_bag *x = (t_bag *)pd_new(bag_class); | ||
1217 | x->x_velo = 0; | ||
1218 | floatinlet_new(&x->x_obj, &x->x_velo); | ||
1219 | outlet_new(&x->x_obj, &s_float); | ||
1220 | x->x_first = 0; | ||
1221 | return (x); | ||
1222 | } | ||
1223 | |||
1224 | static void bag_float(t_bag *x, t_float f) | ||
1225 | { | ||
1226 | t_bagelem *bagelem, *e2, *e3; | ||
1227 | if (x->x_velo != 0) | ||
1228 | { | ||
1229 | bagelem = (t_bagelem *)getbytes(sizeof *bagelem); | ||
1230 | bagelem->e_next = 0; | ||
1231 | bagelem->e_value = f; | ||
1232 | if (!x->x_first) x->x_first = bagelem; | ||
1233 | else /* LATER replace with a faster algorithm */ | ||
1234 | { | ||
1235 | for (e2 = x->x_first; e3 = e2->e_next; e2 = e3) | ||
1236 | ; | ||
1237 | e2->e_next = bagelem; | ||
1238 | } | ||
1239 | } | ||
1240 | else | ||
1241 | { | ||
1242 | if (!x->x_first) return; | ||
1243 | if (x->x_first->e_value == f) | ||
1244 | { | ||
1245 | bagelem = x->x_first; | ||
1246 | x->x_first = x->x_first->e_next; | ||
1247 | freebytes(bagelem, sizeof(*bagelem)); | ||
1248 | return; | ||
1249 | } | ||
1250 | for (e2 = x->x_first; e3 = e2->e_next; e2 = e3) | ||
1251 | if (e3->e_value == f) | ||
1252 | { | ||
1253 | e2->e_next = e3->e_next; | ||
1254 | freebytes(e3, sizeof(*e3)); | ||
1255 | return; | ||
1256 | } | ||
1257 | } | ||
1258 | } | ||
1259 | |||
1260 | static void bag_flush(t_bag *x) | ||
1261 | { | ||
1262 | t_bagelem *bagelem; | ||
1263 | while (bagelem = x->x_first) | ||
1264 | { | ||
1265 | outlet_float(x->x_obj.ob_outlet, bagelem->e_value); | ||
1266 | x->x_first = bagelem->e_next; | ||
1267 | freebytes(bagelem, sizeof(*bagelem)); | ||
1268 | } | ||
1269 | } | ||
1270 | |||
1271 | static void bag_clear(t_bag *x) | ||
1272 | { | ||
1273 | t_bagelem *bagelem; | ||
1274 | while (bagelem = x->x_first) | ||
1275 | { | ||
1276 | x->x_first = bagelem->e_next; | ||
1277 | freebytes(bagelem, sizeof(*bagelem)); | ||
1278 | } | ||
1279 | } | ||
1280 | |||
1281 | static void bag_setup(void) | ||
1282 | { | ||
1283 | bag_class = class_new(gensym("bag"), | ||
1284 | (t_newmethod)bag_new, (t_method)bag_clear, | ||
1285 | sizeof(t_bag), 0, 0); | ||
1286 | class_addfloat(bag_class, bag_float); | ||
1287 | class_addmethod(bag_class, (t_method)bag_flush, gensym("flush"), 0); | ||
1288 | class_addmethod(bag_class, (t_method)bag_clear, gensym("clear"), 0); | ||
1289 | } | ||
1290 | |||
1291 | void x_midi_setup(void) | ||
1292 | { | ||
1293 | midiin_setup(); | ||
1294 | midirealtimein_setup(); | ||
1295 | notein_setup(); | ||
1296 | ctlin_setup(); | ||
1297 | pgmin_setup(); | ||
1298 | bendin_setup(); | ||
1299 | touchin_setup(); | ||
1300 | polytouchin_setup(); | ||
1301 | midiclkin_setup(); | ||
1302 | midiout_setup(); | ||
1303 | noteout_setup(); | ||
1304 | ctlout_setup(); | ||
1305 | pgmout_setup(); | ||
1306 | bendout_setup(); | ||
1307 | touchout_setup(); | ||
1308 | polytouchout_setup(); | ||
1309 | makenote_setup(); | ||
1310 | stripnote_setup(); | ||
1311 | poly_setup(); | ||
1312 | bag_setup(); | ||
1313 | } | ||
1314 | /* Copyright (c) 1997-2001 Miller Puckette and others. | ||
1315 | * For information on usage and redistribution, and for a DISCLAIMER OF ALL | ||
1316 | * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ | ||
1317 | |||
1318 | /* MIDI. */ | ||
1319 | |||
1320 | #include "m_pd.h" | ||
1321 | void outmidi_noteon(int portno, int channel, int pitch, int velo); | ||
1322 | void outmidi_controlchange(int portno, int channel, int ctlno, int value); | ||
1323 | void outmidi_programchange(int portno, int channel, int value); | ||
1324 | void outmidi_pitchbend(int portno, int channel, int value); | ||
1325 | void outmidi_aftertouch(int portno, int channel, int value); | ||
1326 | void outmidi_polyaftertouch(int portno, int channel, int pitch, int value); | ||
1327 | void outmidi_mclk(int portno); | ||
1328 | |||
1329 | /* ----------------------- midiin and sysexin ------------------------- */ | ||
1330 | |||
1331 | static t_symbol *midiin_sym, *sysexin_sym; | ||
1332 | |||
1333 | static t_class *midiin_class, *sysexin_class; | ||
1334 | |||
1335 | typedef struct _midiin | ||
1336 | { | ||
1337 | t_object x_obj; | ||
1338 | t_outlet *x_outlet1; | ||
1339 | t_outlet *x_outlet2; | ||
1340 | } t_midiin; | ||
1341 | |||
1342 | static void *midiin_new( void) | ||
1343 | { | ||
1344 | t_midiin *x = (t_midiin *)pd_new(midiin_class); | ||
1345 | x->x_outlet1 = outlet_new(&x->x_obj, &s_float); | ||
1346 | x->x_outlet2 = outlet_new(&x->x_obj, &s_float); | ||
1347 | pd_bind(&x->x_obj.ob_pd, midiin_sym); | ||
1348 | #ifndef __linux__ | ||
1349 | pd_error(x, "midiin: works under Linux only"); | ||
1350 | #endif | ||
1351 | return (x); | ||
1352 | } | ||
1353 | |||
1354 | static void midiin_list(t_midiin *x, t_symbol *s, int ac, t_atom *av) | ||
1355 | { | ||
1356 | outlet_float(x->x_outlet2, atom_getfloatarg(1, ac, av) + 1); | ||
1357 | outlet_float(x->x_outlet1, atom_getfloatarg(0, ac, av)); | ||
1358 | } | ||
1359 | |||
1360 | static void midiin_free(t_midiin *x) | ||
1361 | { | ||
1362 | pd_unbind(&x->x_obj.ob_pd, midiin_sym); | ||
1363 | } | ||
1364 | |||
1365 | static void *sysexin_new( void) | ||
1366 | { | ||
1367 | t_midiin *x = (t_midiin *)pd_new(sysexin_class); | ||
1368 | x->x_outlet1 = outlet_new(&x->x_obj, &s_float); | ||
1369 | x->x_outlet2 = outlet_new(&x->x_obj, &s_float); | ||
1370 | pd_bind(&x->x_obj.ob_pd, sysexin_sym); | ||
1371 | #ifndef __linux__ | ||
1372 | pd_error(x, "sysexin: works under Linux only"); | ||
1373 | #endif | ||
1374 | return (x); | ||
1375 | } | ||
1376 | |||
1377 | static void sysexin_free(t_midiin *x) | ||
1378 | { | ||
1379 | pd_unbind(&x->x_obj.ob_pd, sysexin_sym); | ||
1380 | } | ||
1381 | |||
1382 | static void midiin_setup(void) | ||
1383 | { | ||
1384 | midiin_class = class_new(gensym("midiin"), (t_newmethod)midiin_new, | ||
1385 | (t_method)midiin_free, sizeof(t_midiin), | ||
1386 | CLASS_NOINLET, A_DEFFLOAT, 0); | ||
1387 | class_addlist(midiin_class, midiin_list); | ||
1388 | class_sethelpsymbol(midiin_class, gensym("midi")); | ||
1389 | midiin_sym = gensym("#midiin"); | ||
1390 | |||
1391 | sysexin_class = class_new(gensym("sysexin"), (t_newmethod)sysexin_new, | ||
1392 | (t_method)sysexin_free, sizeof(t_midiin), | ||
1393 | CLASS_NOINLET, A_DEFFLOAT, 0); | ||
1394 | class_addlist(sysexin_class, midiin_list); | ||
1395 | class_sethelpsymbol(sysexin_class, gensym("midi")); | ||
1396 | sysexin_sym = gensym("#sysexin"); | ||
1397 | } | ||
1398 | |||
1399 | void inmidi_byte(int portno, int byte) | ||
1400 | { | ||
1401 | t_atom at[2]; | ||
1402 | if (midiin_sym->s_thing) | ||
1403 | { | ||
1404 | SETFLOAT(at, byte); | ||
1405 | SETFLOAT(at+1, portno + 1); | ||
1406 | pd_list(midiin_sym->s_thing, 0, 2, at); | ||
1407 | } | ||
1408 | } | ||
1409 | |||
1410 | void inmidi_sysex(int portno, int byte) | ||
1411 | { | ||
1412 | t_atom at[2]; | ||
1413 | if (sysexin_sym->s_thing) | ||
1414 | { | ||
1415 | SETFLOAT(at, byte); | ||
1416 | SETFLOAT(at+1, portno + 1); | ||
1417 | pd_list(sysexin_sym->s_thing, 0, 2, at); | ||
1418 | } | ||
1419 | } | ||
1420 | |||
1421 | /* ----------------------- notein ------------------------- */ | ||
1422 | |||
1423 | static t_symbol *notein_sym; | ||
1424 | |||
1425 | static t_class *notein_class; | ||
1426 | |||
1427 | typedef struct _notein | ||
1428 | { | ||
1429 | t_object x_obj; | ||
1430 | t_float x_channel; | ||
1431 | t_outlet *x_outlet1; | ||
1432 | t_outlet *x_outlet2; | ||
1433 | t_outlet *x_outlet3; | ||
1434 | } t_notein; | ||
1435 | |||
1436 | static void *notein_new(t_floatarg f) | ||
1437 | { | ||
1438 | t_notein *x = (t_notein *)pd_new(notein_class); | ||
1439 | x->x_channel = f; | ||
1440 | x->x_outlet1 = outlet_new(&x->x_obj, &s_float); | ||
1441 | x->x_outlet2 = outlet_new(&x->x_obj, &s_float); | ||
1442 | if (f == 0) x->x_outlet3 = outlet_new(&x->x_obj, &s_float); | ||
1443 | pd_bind(&x->x_obj.ob_pd, notein_sym); | ||
1444 | return (x); | ||
1445 | } | ||
1446 | |||
1447 | static void notein_list(t_notein *x, t_symbol *s, int argc, t_atom *argv) | ||
1448 | { | ||
1449 | float pitch = atom_getfloatarg(0, argc, argv); | ||
1450 | float velo = atom_getfloatarg(1, argc, argv); | ||
1451 | float channel = atom_getfloatarg(2, argc, argv); | ||
1452 | if (x->x_channel != 0) | ||
1453 | { | ||
1454 | if (channel != x->x_channel) return; | ||
1455 | outlet_float(x->x_outlet2, velo); | ||
1456 | outlet_float(x->x_outlet1, pitch); | ||
1457 | } | ||
1458 | else | ||
1459 | { | ||
1460 | outlet_float(x->x_outlet3, channel); | ||
1461 | outlet_float(x->x_outlet2, velo); | ||
1462 | outlet_float(x->x_outlet1, pitch); | ||
1463 | } | ||
1464 | } | ||
1465 | |||
1466 | static void notein_free(t_notein *x) | ||
1467 | { | ||
1468 | pd_unbind(&x->x_obj.ob_pd, notein_sym); | ||
1469 | } | ||
1470 | |||
1471 | static void notein_setup(void) | ||
1472 | { | ||
1473 | notein_class = class_new(gensym("notein"), (t_newmethod)notein_new, | ||
1474 | (t_method)notein_free, sizeof(t_notein), CLASS_NOINLET, A_DEFFLOAT, 0); | ||
1475 | class_addlist(notein_class, notein_list); | ||
1476 | class_sethelpsymbol(notein_class, gensym("midi")); | ||
1477 | notein_sym = gensym("#notein"); | ||
1478 | } | ||
1479 | |||
1480 | void inmidi_noteon(int portno, int channel, int pitch, int velo) | ||
1481 | { | ||
1482 | if (notein_sym->s_thing) | ||
1483 | { | ||
1484 | t_atom at[3]; | ||
1485 | SETFLOAT(at, pitch); | ||
1486 | SETFLOAT(at+1, velo); | ||
1487 | SETFLOAT(at+2, (channel + (portno << 4) + 1)); | ||
1488 | pd_list(notein_sym->s_thing, &s_list, 3, at); | ||
1489 | } | ||
1490 | } | ||
1491 | |||
1492 | /* ----------------------- ctlin ------------------------- */ | ||
1493 | |||
1494 | static t_symbol *ctlin_sym; | ||
1495 | |||
1496 | static t_class *ctlin_class; | ||
1497 | |||
1498 | typedef struct _ctlin | ||
1499 | { | ||
1500 | t_object x_obj; | ||
1501 | t_float x_channel; | ||
1502 | t_float x_ctlno; | ||
1503 | t_outlet *x_outlet1; | ||
1504 | t_outlet *x_outlet2; | ||
1505 | t_outlet *x_outlet3; | ||
1506 | } t_ctlin; | ||
1507 | |||
1508 | static void *ctlin_new(t_symbol *s, int argc, t_atom *argv) | ||
1509 | { | ||
1510 | int ctlno, channel; | ||
1511 | t_ctlin *x = (t_ctlin *)pd_new(ctlin_class); | ||
1512 | if (!argc) ctlno = -1; | ||
1513 | else ctlno = atom_getfloatarg(0, argc, argv); | ||
1514 | channel = atom_getfloatarg(1, argc, argv); | ||
1515 | x->x_channel = channel; | ||
1516 | x->x_ctlno = ctlno; | ||
1517 | x->x_outlet1 = outlet_new(&x->x_obj, &s_float); | ||
1518 | if (!channel) | ||
1519 | { | ||
1520 | if (x->x_ctlno < 0) x->x_outlet2 = outlet_new(&x->x_obj, &s_float); | ||
1521 | x->x_outlet3 = outlet_new(&x->x_obj, &s_float); | ||
1522 | } | ||
1523 | pd_bind(&x->x_obj.ob_pd, ctlin_sym); | ||
1524 | return (x); | ||
1525 | } | ||
1526 | |||
1527 | static void ctlin_list(t_ctlin *x, t_symbol *s, int argc, t_atom *argv) | ||
1528 | { | ||
1529 | t_float ctlnumber = atom_getfloatarg(0, argc, argv); | ||
1530 | t_float value = atom_getfloatarg(1, argc, argv); | ||
1531 | t_float channel = atom_getfloatarg(2, argc, argv); | ||
1532 | if (x->x_ctlno >= 0 && x->x_ctlno != ctlnumber) return; | ||
1533 | if (x->x_channel > 0 && x->x_channel != channel) return; | ||
1534 | if (x->x_channel == 0) outlet_float(x->x_outlet3, channel); | ||
1535 | if (x->x_ctlno < 0) outlet_float(x->x_outlet2, ctlnumber); | ||
1536 | outlet_float(x->x_outlet1, value); | ||
1537 | } | ||
1538 | |||
1539 | static void ctlin_free(t_ctlin *x) | ||
1540 | { | ||
1541 | pd_unbind(&x->x_obj.ob_pd, ctlin_sym); | ||
1542 | } | ||
1543 | |||
1544 | static void ctlin_setup(void) | ||
1545 | { | ||
1546 | ctlin_class = class_new(gensym("ctlin"), (t_newmethod)ctlin_new, | ||
1547 | (t_method)ctlin_free, sizeof(t_ctlin), | ||
1548 | CLASS_NOINLET, A_GIMME, 0); | ||
1549 | class_addlist(ctlin_class, ctlin_list); | ||
1550 | class_sethelpsymbol(ctlin_class, gensym("midi")); | ||
1551 | ctlin_sym = gensym("#ctlin"); | ||
1552 | } | ||
1553 | |||
1554 | void inmidi_controlchange(int portno, int channel, int ctlnumber, int value) | ||
1555 | { | ||
1556 | if (ctlin_sym->s_thing) | ||
1557 | { | ||
1558 | t_atom at[3]; | ||
1559 | SETFLOAT(at, ctlnumber); | ||
1560 | SETFLOAT(at+1, value); | ||
1561 | SETFLOAT(at+2, (channel + (portno << 4) + 1)); | ||
1562 | pd_list(ctlin_sym->s_thing, &s_list, 3, at); | ||
1563 | } | ||
1564 | } | ||
1565 | |||
1566 | /* ----------------------- pgmin ------------------------- */ | ||
1567 | |||
1568 | static t_symbol *pgmin_sym; | ||
1569 | |||
1570 | static t_class *pgmin_class; | ||
1571 | |||
1572 | typedef struct _pgmin | ||
1573 | { | ||
1574 | t_object x_obj; | ||
1575 | t_float x_channel; | ||
1576 | t_outlet *x_outlet1; | ||
1577 | t_outlet *x_outlet2; | ||
1578 | } t_pgmin; | ||
1579 | |||
1580 | static void *pgmin_new(t_floatarg f) | ||
1581 | { | ||
1582 | t_pgmin *x = (t_pgmin *)pd_new(pgmin_class); | ||
1583 | x->x_channel = f; | ||
1584 | x->x_outlet1 = outlet_new(&x->x_obj, &s_float); | ||
1585 | if (f == 0) x->x_outlet2 = outlet_new(&x->x_obj, &s_float); | ||
1586 | pd_bind(&x->x_obj.ob_pd, pgmin_sym); | ||
1587 | return (x); | ||
1588 | } | ||
1589 | |||
1590 | static void pgmin_list(t_pgmin *x, t_symbol *s, int argc, t_atom *argv) | ||
1591 | { | ||
1592 | float value = atom_getfloatarg(0, argc, argv); | ||
1593 | float channel = atom_getfloatarg(1, argc, argv); | ||
1594 | if (x->x_channel != 0) | ||
1595 | { | ||
1596 | if (channel != x->x_channel) return; | ||
1597 | outlet_float(x->x_outlet1, value); | ||
1598 | } | ||
1599 | else | ||
1600 | { | ||
1601 | outlet_float(x->x_outlet2, channel); | ||
1602 | outlet_float(x->x_outlet1, value); | ||
1603 | } | ||
1604 | } | ||
1605 | |||
1606 | static void pgmin_free(t_pgmin *x) | ||
1607 | { | ||
1608 | pd_unbind(&x->x_obj.ob_pd, pgmin_sym); | ||
1609 | } | ||
1610 | |||
1611 | static void pgmin_setup(void) | ||
1612 | { | ||
1613 | pgmin_class = class_new(gensym("pgmin"), (t_newmethod)pgmin_new, | ||
1614 | (t_method)pgmin_free, sizeof(t_pgmin), | ||
1615 | CLASS_NOINLET, A_DEFFLOAT, 0); | ||
1616 | class_addlist(pgmin_class, pgmin_list); | ||
1617 | class_sethelpsymbol(pgmin_class, gensym("midi")); | ||
1618 | pgmin_sym = gensym("#pgmin"); | ||
1619 | } | ||
1620 | |||
1621 | void inmidi_programchange(int portno, int channel, int value) | ||
1622 | { | ||
1623 | if (pgmin_sym->s_thing) | ||
1624 | { | ||
1625 | t_atom at[2]; | ||
1626 | SETFLOAT(at, value + 1); | ||
1627 | SETFLOAT(at+1, (channel + (portno << 4) + 1)); | ||
1628 | pd_list(pgmin_sym->s_thing, &s_list, 2, at); | ||
1629 | } | ||
1630 | } | ||
1631 | |||
1632 | /* ----------------------- bendin ------------------------- */ | ||
1633 | |||
1634 | static t_symbol *bendin_sym; | ||
1635 | |||
1636 | static t_class *bendin_class; | ||
1637 | |||
1638 | typedef struct _bendin | ||
1639 | { | ||
1640 | t_object x_obj; | ||
1641 | t_float x_channel; | ||
1642 | t_outlet *x_outlet1; | ||
1643 | t_outlet *x_outlet2; | ||
1644 | } t_bendin; | ||
1645 | |||
1646 | static void *bendin_new(t_floatarg f) | ||
1647 | { | ||
1648 | t_bendin *x = (t_bendin *)pd_new(bendin_class); | ||
1649 | x->x_channel = f; | ||
1650 | x->x_outlet1 = outlet_new(&x->x_obj, &s_float); | ||
1651 | if (f == 0) x->x_outlet2 = outlet_new(&x->x_obj, &s_float); | ||
1652 | pd_bind(&x->x_obj.ob_pd, bendin_sym); | ||
1653 | return (x); | ||
1654 | } | ||
1655 | |||
1656 | static void bendin_list(t_bendin *x, t_symbol *s, int argc, t_atom *argv) | ||
1657 | { | ||
1658 | t_float value = atom_getfloatarg(0, argc, argv); | ||
1659 | t_float channel = atom_getfloatarg(1, argc, argv); | ||
1660 | if (x->x_channel != 0) | ||
1661 | { | ||
1662 | if (channel != x->x_channel) return; | ||
1663 | outlet_float(x->x_outlet1, value); | ||
1664 | } | ||
1665 | else | ||
1666 | { | ||
1667 | outlet_float(x->x_outlet2, channel); | ||
1668 | outlet_float(x->x_outlet1, value); | ||
1669 | } | ||
1670 | } | ||
1671 | |||
1672 | static void bendin_free(t_bendin *x) | ||
1673 | { | ||
1674 | pd_unbind(&x->x_obj.ob_pd, bendin_sym); | ||
1675 | } | ||
1676 | |||
1677 | static void bendin_setup(void) | ||
1678 | { | ||
1679 | bendin_class = class_new(gensym("bendin"), (t_newmethod)bendin_new, | ||
1680 | (t_method)bendin_free, sizeof(t_bendin), CLASS_NOINLET, A_DEFFLOAT, 0); | ||
1681 | class_addlist(bendin_class, bendin_list); | ||
1682 | class_sethelpsymbol(bendin_class, gensym("midi")); | ||
1683 | bendin_sym = gensym("#bendin"); | ||
1684 | } | ||
1685 | |||
1686 | void inmidi_pitchbend(int portno, int channel, int value) | ||
1687 | { | ||
1688 | if (bendin_sym->s_thing) | ||
1689 | { | ||
1690 | t_atom at[2]; | ||
1691 | SETFLOAT(at, value); | ||
1692 | SETFLOAT(at+1, (channel + (portno << 4) + 1)); | ||
1693 | pd_list(bendin_sym->s_thing, &s_list, 2, at); | ||
1694 | } | ||
1695 | } | ||
1696 | |||
1697 | /* ----------------------- touchin ------------------------- */ | ||
1698 | |||
1699 | static t_symbol *touchin_sym; | ||
1700 | |||
1701 | static t_class *touchin_class; | ||
1702 | |||
1703 | typedef struct _touchin | ||
1704 | { | ||
1705 | t_object x_obj; | ||
1706 | t_float x_channel; | ||
1707 | t_outlet *x_outlet1; | ||
1708 | t_outlet *x_outlet2; | ||
1709 | } t_touchin; | ||
1710 | |||
1711 | static void *touchin_new(t_floatarg f) | ||
1712 | { | ||
1713 | t_touchin *x = (t_touchin *)pd_new(touchin_class); | ||
1714 | x->x_channel = f; | ||
1715 | x->x_outlet1 = outlet_new(&x->x_obj, &s_float); | ||
1716 | if (f == 0) x->x_outlet2 = outlet_new(&x->x_obj, &s_float); | ||
1717 | pd_bind(&x->x_obj.ob_pd, touchin_sym); | ||
1718 | return (x); | ||
1719 | } | ||
1720 | |||
1721 | static void touchin_list(t_touchin *x, t_symbol *s, int argc, t_atom *argv) | ||
1722 | { | ||
1723 | t_float value = atom_getfloatarg(0, argc, argv); | ||
1724 | t_float channel = atom_getfloatarg(1, argc, argv); | ||
1725 | if (x->x_channel) | ||
1726 | { | ||
1727 | if (channel != x->x_channel) return; | ||
1728 | outlet_float(x->x_outlet1, value); | ||
1729 | } | ||
1730 | else | ||
1731 | { | ||
1732 | outlet_float(x->x_outlet2, channel); | ||
1733 | outlet_float(x->x_outlet1, value); | ||
1734 | } | ||
1735 | } | ||
1736 | |||
1737 | static void touchin_free(t_touchin *x) | ||
1738 | { | ||
1739 | pd_unbind(&x->x_obj.ob_pd, touchin_sym); | ||
1740 | } | ||
1741 | |||
1742 | static void touchin_setup(void) | ||
1743 | { | ||
1744 | touchin_class = class_new(gensym("touchin"), (t_newmethod)touchin_new, | ||
1745 | (t_method)touchin_free, sizeof(t_touchin), | ||
1746 | CLASS_NOINLET, A_DEFFLOAT, 0); | ||
1747 | class_addlist(touchin_class, touchin_list); | ||
1748 | class_sethelpsymbol(touchin_class, gensym("midi")); | ||
1749 | touchin_sym = gensym("#touchin"); | ||
1750 | } | ||
1751 | |||
1752 | void inmidi_aftertouch(int portno, int channel, int value) | ||
1753 | { | ||
1754 | if (touchin_sym->s_thing) | ||
1755 | { | ||
1756 | t_atom at[2]; | ||
1757 | SETFLOAT(at, value); | ||
1758 | SETFLOAT(at+1, (channel + (portno << 4) + 1)); | ||
1759 | pd_list(touchin_sym->s_thing, &s_list, 2, at); | ||
1760 | } | ||
1761 | } | ||
1762 | |||
1763 | /* ----------------------- polytouchin ------------------------- */ | ||
1764 | |||
1765 | static t_symbol *polytouchin_sym; | ||
1766 | |||
1767 | static t_class *polytouchin_class; | ||
1768 | |||
1769 | typedef struct _polytouchin | ||
1770 | { | ||
1771 | t_object x_obj; | ||
1772 | t_float x_channel; | ||
1773 | t_outlet *x_outlet1; | ||
1774 | t_outlet *x_outlet2; | ||
1775 | t_outlet *x_outlet3; | ||
1776 | } t_polytouchin; | ||
1777 | |||
1778 | static void *polytouchin_new(t_floatarg f) | ||
1779 | { | ||
1780 | t_polytouchin *x = (t_polytouchin *)pd_new(polytouchin_class); | ||
1781 | x->x_channel = f; | ||
1782 | x->x_outlet1 = outlet_new(&x->x_obj, &s_float); | ||
1783 | x->x_outlet2 = outlet_new(&x->x_obj, &s_float); | ||
1784 | if (f == 0) x->x_outlet3 = outlet_new(&x->x_obj, &s_float); | ||
1785 | pd_bind(&x->x_obj.ob_pd, polytouchin_sym); | ||
1786 | return (x); | ||
1787 | } | ||
1788 | |||
1789 | static void polytouchin_list(t_polytouchin *x, t_symbol *s, int argc, | ||
1790 | t_atom *argv) | ||
1791 | { | ||
1792 | t_float pitch = atom_getfloatarg(0, argc, argv); | ||
1793 | t_float value = atom_getfloatarg(1, argc, argv); | ||
1794 | t_float channel = atom_getfloatarg(2, argc, argv); | ||
1795 | if (x->x_channel != 0) | ||
1796 | { | ||
1797 | if (channel != x->x_channel) return; | ||
1798 | outlet_float(x->x_outlet2, pitch); | ||
1799 | outlet_float(x->x_outlet1, value); | ||
1800 | } | ||
1801 | else | ||
1802 | { | ||
1803 | outlet_float(x->x_outlet3, channel); | ||
1804 | outlet_float(x->x_outlet2, pitch); | ||
1805 | outlet_float(x->x_outlet1, value); | ||
1806 | } | ||
1807 | } | ||
1808 | |||
1809 | static void polytouchin_free(t_polytouchin *x) | ||
1810 | { | ||
1811 | pd_unbind(&x->x_obj.ob_pd, polytouchin_sym); | ||
1812 | } | ||
1813 | |||
1814 | static void polytouchin_setup(void) | ||
1815 | { | ||
1816 | polytouchin_class = class_new(gensym("polytouchin"), | ||
1817 | (t_newmethod)polytouchin_new, (t_method)polytouchin_free, | ||
1818 | sizeof(t_polytouchin), CLASS_NOINLET, A_DEFFLOAT, 0); | ||
1819 | class_addlist(polytouchin_class, polytouchin_list); | ||
1820 | class_sethelpsymbol(polytouchin_class, gensym("midi")); | ||
1821 | polytouchin_sym = gensym("#polytouchin"); | ||
1822 | } | ||
1823 | |||
1824 | void inmidi_polyaftertouch(int portno, int channel, int pitch, int value) | ||
1825 | { | ||
1826 | if (polytouchin_sym->s_thing) | ||
1827 | { | ||
1828 | t_atom at[3]; | ||
1829 | SETFLOAT(at, pitch); | ||
1830 | SETFLOAT(at+1, value); | ||
1831 | SETFLOAT(at+2, (channel + (portno << 4) + 1)); | ||
1832 | pd_list(polytouchin_sym->s_thing, &s_list, 3, at); | ||
1833 | } | ||
1834 | } | ||
1835 | |||
1836 | /*----------------------- midiclkin--(midi F8 message )---------------------*/ | ||
1837 | static t_symbol *midiclkin_sym; | ||
1838 | |||
1839 | static t_class *midiclkin_class; | ||
1840 | |||
1841 | |||
1842 | typedef struct _midiclkin | ||
1843 | { | ||
1844 | t_object x_obj; | ||
1845 | t_outlet *x_outlet1; | ||
1846 | t_outlet *x_outlet2; | ||
1847 | } t_midiclkin; | ||
1848 | |||
1849 | static void *midiclkin_new(t_floatarg f) | ||
1850 | { | ||
1851 | t_midiclkin *x = (t_midiclkin *)pd_new(midiclkin_class); | ||
1852 | x->x_outlet1 = outlet_new(&x->x_obj, &s_float); | ||
1853 | x->x_outlet2 = outlet_new(&x->x_obj, &s_float); | ||
1854 | pd_bind(&x->x_obj.ob_pd, midiclkin_sym); | ||
1855 | return (x); | ||
1856 | } | ||
1857 | |||
1858 | static void midiclkin_list(t_midiclkin *x, t_symbol *s, int argc, t_atom *argv) | ||
1859 | { | ||
1860 | float value = atom_getfloatarg(0, argc, argv); | ||
1861 | float count = atom_getfloatarg(1, argc, argv); | ||
1862 | outlet_float(x->x_outlet2, count); | ||
1863 | outlet_float(x->x_outlet1, value); | ||
1864 | } | ||
1865 | |||
1866 | static void midiclkin_free(t_midiclkin *x) | ||
1867 | { | ||
1868 | pd_unbind(&x->x_obj.ob_pd, midiclkin_sym); | ||
1869 | } | ||
1870 | |||
1871 | static void midiclkin_setup(void) | ||
1872 | { | ||
1873 | midiclkin_class = class_new(gensym("midiclkin"), | ||
1874 | (t_newmethod)midiclkin_new, (t_method)midiclkin_free, | ||
1875 | sizeof(t_midiclkin), CLASS_NOINLET, A_DEFFLOAT, 0); | ||
1876 | class_addlist(midiclkin_class, midiclkin_list); | ||
1877 | class_sethelpsymbol(midiclkin_class, gensym("midi")); | ||
1878 | midiclkin_sym = gensym("#midiclkin"); | ||
1879 | } | ||
1880 | |||
1881 | void inmidi_clk(double timing) | ||
1882 | { | ||
1883 | |||
1884 | static float prev = 0; | ||
1885 | static float count = 0; | ||
1886 | float cur,diff; | ||
1887 | |||
1888 | if (midiclkin_sym->s_thing) | ||
1889 | { | ||
1890 | t_atom at[2]; | ||
1891 | diff =timing - prev; | ||
1892 | count++; | ||
1893 | |||
1894 | if (count == 3) | ||
1895 | { /* 24 count per quoter note */ | ||
1896 | SETFLOAT(at, 1 ); | ||
1897 | count = 0; | ||
1898 | } | ||
1899 | else SETFLOAT(at, 0); | ||
1900 | |||
1901 | SETFLOAT(at+1, diff); | ||
1902 | pd_list(midiclkin_sym->s_thing, &s_list, 2, at); | ||
1903 | prev = timing; | ||
1904 | } | ||
1905 | } | ||
1906 | |||
1907 | /*----------midirealtimein (midi FA,FB,FC,FF message )-----------------*/ | ||
1908 | |||
1909 | static t_symbol *midirealtimein_sym; | ||
1910 | |||
1911 | static t_class *midirealtimein_class; | ||
1912 | |||
1913 | typedef struct _midirealtimein | ||
1914 | { | ||
1915 | t_object x_obj; | ||
1916 | t_outlet *x_outlet1; | ||
1917 | t_outlet *x_outlet2; | ||
1918 | } t_midirealtimein; | ||
1919 | |||
1920 | static void *midirealtimein_new( void) | ||
1921 | { | ||
1922 | t_midirealtimein *x = (t_midirealtimein *)pd_new(midirealtimein_class); | ||
1923 | x->x_outlet1 = outlet_new(&x->x_obj, &s_float); | ||
1924 | x->x_outlet2 = outlet_new(&x->x_obj, &s_float); | ||
1925 | pd_bind(&x->x_obj.ob_pd, midirealtimein_sym); | ||
1926 | #ifndef MSW | ||
1927 | pd_error(x, "midirealtimein: works under MSW only"); | ||
1928 | #endif | ||
1929 | return (x); | ||
1930 | } | ||
1931 | |||
1932 | static void midirealtimein_list(t_midirealtimein *x, t_symbol *s, | ||
1933 | int argc, t_atom *argv) | ||
1934 | { | ||
1935 | float portno = atom_getfloatarg(0, argc, argv); | ||
1936 | float byte = atom_getfloatarg(1, argc, argv); | ||
1937 | |||
1938 | outlet_float(x->x_outlet2, portno); | ||
1939 | outlet_float(x->x_outlet1, byte); | ||
1940 | } | ||
1941 | |||
1942 | static void midirealtimein_free(t_midirealtimein *x) | ||
1943 | { | ||
1944 | pd_unbind(&x->x_obj.ob_pd, midirealtimein_sym); | ||
1945 | } | ||
1946 | |||
1947 | static void midirealtimein_setup(void) | ||
1948 | { | ||
1949 | midirealtimein_class = class_new(gensym("midirealtimein"), | ||
1950 | (t_newmethod)midirealtimein_new, (t_method)midirealtimein_free, | ||
1951 | sizeof(t_midirealtimein), CLASS_NOINLET, A_DEFFLOAT, 0); | ||
1952 | class_addlist(midirealtimein_class, midirealtimein_list); | ||
1953 | class_sethelpsymbol(midirealtimein_class, gensym("midi")); | ||
1954 | midirealtimein_sym = gensym("#midirealtimein"); | ||
1955 | } | ||
1956 | |||
1957 | void inmidi_realtimein(int portno, int SysMsg) | ||
1958 | { | ||
1959 | if (midirealtimein_sym->s_thing) | ||
1960 | { | ||
1961 | t_atom at[2]; | ||
1962 | SETFLOAT(at, portno); | ||
1963 | SETFLOAT(at+1, SysMsg); | ||
1964 | pd_list(midirealtimein_sym->s_thing, &s_list, 1, at); | ||
1965 | } | ||
1966 | } | ||
1967 | |||
1968 | /* -------------------------- midiout -------------------------- */ | ||
1969 | |||
1970 | static t_class *midiout_class; | ||
1971 | |||
1972 | void sys_putmidibyte(int portno, int byte); | ||
1973 | |||
1974 | typedef struct _midiout | ||
1975 | { | ||
1976 | t_object x_obj; | ||
1977 | t_float x_portno; | ||
1978 | } t_midiout; | ||
1979 | |||
1980 | static void *midiout_new(t_floatarg portno) | ||
1981 | { | ||
1982 | t_midiout *x = (t_midiout *)pd_new(midiout_class); | ||
1983 | if (portno <= 0) portno = 1; | ||
1984 | x->x_portno = portno; | ||
1985 | floatinlet_new(&x->x_obj, &x->x_portno); | ||
1986 | #ifdef __irix__ | ||
1987 | post("midiout: unimplemented in IRIX"); | ||
1988 | #endif | ||
1989 | return (x); | ||
1990 | } | ||
1991 | |||
1992 | static void midiout_float(t_midiout *x, t_floatarg f) | ||
1993 | { | ||
1994 | sys_putmidibyte(x->x_portno - 1, f); | ||
1995 | } | ||
1996 | |||
1997 | static void midiout_setup(void) | ||
1998 | { | ||
1999 | midiout_class = class_new(gensym("midiout"), (t_newmethod)midiout_new, 0, | ||
2000 | sizeof(t_midiout), 0, A_DEFFLOAT, A_DEFFLOAT, 0); | ||
2001 | class_addfloat(midiout_class, midiout_float); | ||
2002 | class_sethelpsymbol(midiout_class, gensym("midi")); | ||
2003 | } | ||
2004 | |||
2005 | /* -------------------------- noteout -------------------------- */ | ||
2006 | |||
2007 | static t_class *noteout_class; | ||
2008 | |||
2009 | typedef struct _noteout | ||
2010 | { | ||
2011 | t_object x_obj; | ||
2012 | t_float x_velo; | ||
2013 | t_float x_channel; | ||
2014 | } t_noteout; | ||
2015 | |||
2016 | static void *noteout_new(t_floatarg channel) | ||
2017 | { | ||
2018 | t_noteout *x = (t_noteout *)pd_new(noteout_class); | ||
2019 | x->x_velo = 0; | ||
2020 | if (channel < 1) channel = 1; | ||
2021 | x->x_channel = channel; | ||
2022 | floatinlet_new(&x->x_obj, &x->x_velo); | ||
2023 | floatinlet_new(&x->x_obj, &x->x_channel); | ||
2024 | return (x); | ||
2025 | } | ||
2026 | |||
2027 | static void noteout_float(t_noteout *x, t_float f) | ||
2028 | { | ||
2029 | int binchan = x->x_channel - 1; | ||
2030 | if (binchan < 0) | ||
2031 | binchan = 0; | ||
2032 | outmidi_noteon((binchan >> 4), | ||
2033 | (binchan & 15), (int)f, (int)x->x_velo); | ||
2034 | } | ||
2035 | |||
2036 | static void noteout_setup(void) | ||
2037 | { | ||
2038 | noteout_class = class_new(gensym("noteout"), (t_newmethod)noteout_new, 0, | ||
2039 | sizeof(t_noteout), 0, A_DEFFLOAT, 0); | ||
2040 | class_addfloat(noteout_class, noteout_float); | ||
2041 | class_sethelpsymbol(noteout_class, gensym("midi")); | ||
2042 | } | ||
2043 | |||
2044 | |||
2045 | /* -------------------------- ctlout -------------------------- */ | ||
2046 | |||
2047 | static t_class *ctlout_class; | ||
2048 | |||
2049 | typedef struct _ctlout | ||
2050 | { | ||
2051 | t_object x_obj; | ||
2052 | t_float x_ctl; | ||
2053 | t_float x_channel; | ||
2054 | } t_ctlout; | ||
2055 | |||
2056 | static void *ctlout_new(t_floatarg ctl, t_floatarg channel) | ||
2057 | { | ||
2058 | t_ctlout *x = (t_ctlout *)pd_new(ctlout_class); | ||
2059 | x->x_ctl = ctl; | ||
2060 | if (channel <= 0) channel = 1; | ||
2061 | x->x_channel = channel; | ||
2062 | floatinlet_new(&x->x_obj, &x->x_ctl); | ||
2063 | floatinlet_new(&x->x_obj, &x->x_channel); | ||
2064 | return (x); | ||
2065 | } | ||
2066 | |||
2067 | static void ctlout_float(t_ctlout *x, t_float f) | ||
2068 | { | ||
2069 | int binchan = x->x_channel - 1; | ||
2070 | if (binchan < 0) | ||
2071 | binchan = 0; | ||
2072 | outmidi_controlchange((binchan >> 4), | ||
2073 | (binchan & 15), (int)(x->x_ctl), (int)f); | ||
2074 | } | ||
2075 | |||
2076 | static void ctlout_setup(void) | ||
2077 | { | ||
2078 | ctlout_class = class_new(gensym("ctlout"), (t_newmethod)ctlout_new, 0, | ||
2079 | sizeof(t_ctlout), 0, A_DEFFLOAT, A_DEFFLOAT, 0); | ||
2080 | class_addfloat(ctlout_class, ctlout_float); | ||
2081 | class_sethelpsymbol(ctlout_class, gensym("midi")); | ||
2082 | } | ||
2083 | |||
2084 | |||
2085 | /* -------------------------- pgmout -------------------------- */ | ||
2086 | |||
2087 | static t_class *pgmout_class; | ||
2088 | |||
2089 | typedef struct _pgmout | ||
2090 | { | ||
2091 | t_object x_obj; | ||
2092 | t_float x_channel; | ||
2093 | } t_pgmout; | ||
2094 | |||
2095 | static void *pgmout_new(t_floatarg channel) | ||
2096 | { | ||
2097 | t_pgmout *x = (t_pgmout *)pd_new(pgmout_class); | ||
2098 | if (channel <= 0) channel = 1; | ||
2099 | x->x_channel = channel; | ||
2100 | floatinlet_new(&x->x_obj, &x->x_channel); | ||
2101 | return (x); | ||
2102 | } | ||
2103 | |||
2104 | static void pgmout_float(t_pgmout *x, t_floatarg f) | ||
2105 | { | ||
2106 | int binchan = x->x_channel - 1; | ||
2107 | int n = f - 1; | ||
2108 | if (binchan < 0) | ||
2109 | binchan = 0; | ||
2110 | if (n < 0) n = 0; | ||
2111 | else if (n > 127) n = 127; | ||
2112 | outmidi_programchange((binchan >> 4), | ||
2113 | (binchan & 15), n); | ||
2114 | } | ||
2115 | |||
2116 | static void pgmout_setup(void) | ||
2117 | { | ||
2118 | pgmout_class = class_new(gensym("pgmout"), (t_newmethod)pgmout_new, 0, | ||
2119 | sizeof(t_pgmout), 0, A_DEFFLOAT, 0); | ||
2120 | class_addfloat(pgmout_class, pgmout_float); | ||
2121 | class_sethelpsymbol(pgmout_class, gensym("midi")); | ||
2122 | } | ||
2123 | |||
2124 | |||
2125 | /* -------------------------- bendout -------------------------- */ | ||
2126 | |||
2127 | static t_class *bendout_class; | ||
2128 | |||
2129 | typedef struct _bendout | ||
2130 | { | ||
2131 | t_object x_obj; | ||
2132 | t_float x_channel; | ||
2133 | } t_bendout; | ||
2134 | |||
2135 | static void *bendout_new(t_floatarg channel) | ||
2136 | { | ||
2137 | t_bendout *x = (t_bendout *)pd_new(bendout_class); | ||
2138 | if (channel <= 0) channel = 1; | ||
2139 | x->x_channel = channel; | ||
2140 | floatinlet_new(&x->x_obj, &x->x_channel); | ||
2141 | return (x); | ||
2142 | } | ||
2143 | |||
2144 | static void bendout_float(t_bendout *x, t_float f) | ||
2145 | { | ||
2146 | int binchan = x->x_channel - 1; | ||
2147 | int n = (int)f + 8192; | ||
2148 | if (binchan < 0) | ||
2149 | binchan = 0; | ||
2150 | outmidi_pitchbend((binchan >> 4), (binchan & 15), n); | ||
2151 | } | ||
2152 | |||
2153 | static void bendout_setup(void) | ||
2154 | { | ||
2155 | bendout_class = class_new(gensym("bendout"), (t_newmethod)bendout_new, 0, | ||
2156 | sizeof(t_bendout), 0, A_DEFFLOAT, 0); | ||
2157 | class_addfloat(bendout_class, bendout_float); | ||
2158 | class_sethelpsymbol(bendout_class, gensym("midi")); | ||
2159 | } | ||
2160 | |||
2161 | /* -------------------------- touch -------------------------- */ | ||
2162 | |||
2163 | static t_class *touchout_class; | ||
2164 | |||
2165 | typedef struct _touchout | ||
2166 | { | ||
2167 | t_object x_obj; | ||
2168 | t_float x_channel; | ||
2169 | } t_touchout; | ||
2170 | |||
2171 | static void *touchout_new(t_floatarg channel) | ||
2172 | { | ||
2173 | t_touchout *x = (t_touchout *)pd_new(touchout_class); | ||
2174 | if (channel <= 0) channel = 1; | ||
2175 | x->x_channel = channel; | ||
2176 | floatinlet_new(&x->x_obj, &x->x_channel); | ||
2177 | return (x); | ||
2178 | } | ||
2179 | |||
2180 | static void touchout_float(t_touchout *x, t_float f) | ||
2181 | { | ||
2182 | int binchan = x->x_channel - 1; | ||
2183 | if (binchan < 0) | ||
2184 | binchan = 0; | ||
2185 | outmidi_aftertouch((binchan >> 4), (binchan & 15), (int)f); | ||
2186 | } | ||
2187 | |||
2188 | static void touchout_setup(void) | ||
2189 | { | ||
2190 | touchout_class = class_new(gensym("touchout"), (t_newmethod)touchout_new, 0, | ||
2191 | sizeof(t_touchout), 0, A_DEFFLOAT, 0); | ||
2192 | class_addfloat(touchout_class, touchout_float); | ||
2193 | class_sethelpsymbol(touchout_class, gensym("midi")); | ||
2194 | } | ||
2195 | |||
2196 | /* -------------------------- polytouch -------------------------- */ | ||
2197 | |||
2198 | static t_class *polytouchout_class; | ||
2199 | |||
2200 | typedef struct _polytouchout | ||
2201 | { | ||
2202 | t_object x_obj; | ||
2203 | t_float x_channel; | ||
2204 | t_float x_pitch; | ||
2205 | } t_polytouchout; | ||
2206 | |||
2207 | static void *polytouchout_new(t_floatarg channel) | ||
2208 | { | ||
2209 | t_polytouchout *x = (t_polytouchout *)pd_new(polytouchout_class); | ||
2210 | if (channel <= 0) channel = 1; | ||
2211 | x->x_channel = channel; | ||
2212 | x->x_pitch = 0; | ||
2213 | floatinlet_new(&x->x_obj, &x->x_pitch); | ||
2214 | floatinlet_new(&x->x_obj, &x->x_channel); | ||
2215 | return (x); | ||
2216 | } | ||
2217 | |||
2218 | static void polytouchout_float(t_polytouchout *x, t_float n) | ||
2219 | { | ||
2220 | int binchan = x->x_channel - 1; | ||
2221 | if (binchan < 0) | ||
2222 | binchan = 0; | ||
2223 | outmidi_polyaftertouch((binchan >> 4), (binchan & 15), x->x_pitch, n); | ||
2224 | } | ||
2225 | |||
2226 | static void polytouchout_setup(void) | ||
2227 | { | ||
2228 | polytouchout_class = class_new(gensym("polytouchout"), | ||
2229 | (t_newmethod)polytouchout_new, 0, | ||
2230 | sizeof(t_polytouchout), 0, A_DEFFLOAT, 0); | ||
2231 | class_addfloat(polytouchout_class, polytouchout_float); | ||
2232 | class_sethelpsymbol(polytouchout_class, gensym("midi")); | ||
2233 | } | ||
2234 | |||
2235 | /* -------------------------- makenote -------------------------- */ | ||
2236 | |||
2237 | static t_class *makenote_class; | ||
2238 | |||
2239 | typedef struct _hang | ||
2240 | { | ||
2241 | t_clock *h_clock; | ||
2242 | struct _hang *h_next; | ||
2243 | t_float h_pitch; | ||
2244 | struct _makenote *h_owner; | ||
2245 | } t_hang; | ||
2246 | |||
2247 | typedef struct _makenote | ||
2248 | { | ||
2249 | t_object x_obj; | ||
2250 | t_float x_velo; | ||
2251 | t_float x_dur; | ||
2252 | t_outlet *x_pitchout; | ||
2253 | t_outlet *x_velout; | ||
2254 | t_hang *x_hang; | ||
2255 | } t_makenote; | ||
2256 | |||
2257 | static void *makenote_new(t_floatarg velo, t_floatarg dur) | ||
2258 | { | ||
2259 | t_makenote *x = (t_makenote *)pd_new(makenote_class); | ||
2260 | x->x_velo = velo; | ||
2261 | x->x_dur = dur; | ||
2262 | floatinlet_new(&x->x_obj, &x->x_velo); | ||
2263 | floatinlet_new(&x->x_obj, &x->x_dur); | ||
2264 | x->x_pitchout = outlet_new(&x->x_obj, &s_float); | ||
2265 | x->x_velout = outlet_new(&x->x_obj, &s_float); | ||
2266 | x->x_hang = 0; | ||
2267 | return (x); | ||
2268 | } | ||
2269 | |||
2270 | static void makenote_tick(t_hang *hang) | ||
2271 | { | ||
2272 | t_makenote *x = hang->h_owner; | ||
2273 | t_hang *h2, *h3; | ||
2274 | outlet_float(x->x_velout, 0); | ||
2275 | outlet_float(x->x_pitchout, hang->h_pitch); | ||
2276 | if (x->x_hang == hang) x->x_hang = hang->h_next; | ||
2277 | else for (h2 = x->x_hang; h3 = h2->h_next; h2 = h3) | ||
2278 | { | ||
2279 | if (h3 == hang) | ||
2280 | { | ||
2281 | h2->h_next = h3->h_next; | ||
2282 | break; | ||
2283 | } | ||
2284 | } | ||
2285 | clock_free(hang->h_clock); | ||
2286 | freebytes(hang, sizeof(*hang)); | ||
2287 | } | ||
2288 | |||
2289 | static void makenote_float(t_makenote *x, t_float f) | ||
2290 | { | ||
2291 | t_hang *hang; | ||
2292 | if (!x->x_velo) return; | ||
2293 | outlet_float(x->x_velout, x->x_velo); | ||
2294 | outlet_float(x->x_pitchout, f); | ||
2295 | hang = (t_hang *)getbytes(sizeof *hang); | ||
2296 | hang->h_next = x->x_hang; | ||
2297 | x->x_hang = hang; | ||
2298 | hang->h_pitch = f; | ||
2299 | hang->h_owner = x; | ||
2300 | hang->h_clock = clock_new(hang, (t_method)makenote_tick); | ||
2301 | clock_delay(hang->h_clock, (x->x_dur >= 0 ? x->x_dur : 0)); | ||
2302 | } | ||
2303 | |||
2304 | static void makenote_stop(t_makenote *x) | ||
2305 | { | ||
2306 | t_hang *hang; | ||
2307 | while (hang = x->x_hang) | ||
2308 | { | ||
2309 | outlet_float(x->x_velout, 0); | ||
2310 | outlet_float(x->x_pitchout, hang->h_pitch); | ||
2311 | x->x_hang = hang->h_next; | ||
2312 | clock_free(hang->h_clock); | ||
2313 | freebytes(hang, sizeof(*hang)); | ||
2314 | } | ||
2315 | } | ||
2316 | |||
2317 | static void makenote_clear(t_makenote *x) | ||
2318 | { | ||
2319 | t_hang *hang; | ||
2320 | while (hang = x->x_hang) | ||
2321 | { | ||
2322 | x->x_hang = hang->h_next; | ||
2323 | clock_free(hang->h_clock); | ||
2324 | freebytes(hang, sizeof(*hang)); | ||
2325 | } | ||
2326 | } | ||
2327 | |||
2328 | static void makenote_setup(void) | ||
2329 | { | ||
2330 | makenote_class = class_new(gensym("makenote"), | ||
2331 | (t_newmethod)makenote_new, (t_method)makenote_clear, | ||
2332 | sizeof(t_makenote), 0, A_DEFFLOAT, A_DEFFLOAT, 0); | ||
2333 | class_addfloat(makenote_class, makenote_float); | ||
2334 | class_addmethod(makenote_class, (t_method)makenote_stop, gensym("stop"), | ||
2335 | 0); | ||
2336 | class_addmethod(makenote_class, (t_method)makenote_clear, gensym("clear"), | ||
2337 | 0); | ||
2338 | } | ||
2339 | |||
2340 | /* -------------------------- stripnote -------------------------- */ | ||
2341 | |||
2342 | static t_class *stripnote_class; | ||
2343 | |||
2344 | typedef struct _stripnote | ||
2345 | { | ||
2346 | t_object x_obj; | ||
2347 | t_float x_velo; | ||
2348 | t_outlet *x_pitchout; | ||
2349 | t_outlet *x_velout; | ||
2350 | } t_stripnote; | ||
2351 | |||
2352 | static void *stripnote_new(void ) | ||
2353 | { | ||
2354 | t_stripnote *x = (t_stripnote *)pd_new(stripnote_class); | ||
2355 | floatinlet_new(&x->x_obj, &x->x_velo); | ||
2356 | x->x_pitchout = outlet_new(&x->x_obj, &s_float); | ||
2357 | x->x_velout = outlet_new(&x->x_obj, &s_float); | ||
2358 | return (x); | ||
2359 | } | ||
2360 | |||
2361 | static void stripnote_float(t_stripnote *x, t_float f) | ||
2362 | { | ||
2363 | t_hang *hang; | ||
2364 | if (!x->x_velo) return; | ||
2365 | outlet_float(x->x_velout, x->x_velo); | ||
2366 | outlet_float(x->x_pitchout, f); | ||
2367 | } | ||
2368 | |||
2369 | static void stripnote_setup(void) | ||
2370 | { | ||
2371 | stripnote_class = class_new(gensym("stripnote"), | ||
2372 | (t_newmethod)stripnote_new, 0, sizeof(t_stripnote), 0, 0); | ||
2373 | class_addfloat(stripnote_class, stripnote_float); | ||
2374 | } | ||
2375 | |||
2376 | /* -------------------------- poly -------------------------- */ | ||
2377 | |||
2378 | static t_class *poly_class; | ||
2379 | |||
2380 | typedef struct voice | ||
2381 | { | ||
2382 | float v_pitch; | ||
2383 | int v_used; | ||
2384 | unsigned long v_serial; | ||
2385 | } t_voice; | ||
2386 | |||
2387 | typedef struct poly | ||
2388 | { | ||
2389 | t_object x_obj; | ||
2390 | int x_n; | ||
2391 | t_voice *x_vec; | ||
2392 | float x_vel; | ||
2393 | t_outlet *x_pitchout; | ||
2394 | t_outlet *x_velout; | ||
2395 | unsigned long x_serial; | ||
2396 | int x_steal; | ||
2397 | } t_poly; | ||
2398 | |||
2399 | static void *poly_new(float fnvoice, float fsteal) | ||
2400 | { | ||
2401 | int i, n = fnvoice; | ||
2402 | t_poly *x = (t_poly *)pd_new(poly_class); | ||
2403 | t_voice *v; | ||
2404 | if (n < 1) n = 1; | ||
2405 | x->x_n = n; | ||
2406 | x->x_vec = (t_voice *)getbytes(n * sizeof(*x->x_vec)); | ||
2407 | for (v = x->x_vec, i = n; i--; v++) | ||
2408 | v->v_pitch = v->v_used = v->v_serial = 0; | ||
2409 | x->x_vel = 0; | ||
2410 | x->x_steal = (fsteal != 0); | ||
2411 | floatinlet_new(&x->x_obj, &x->x_vel); | ||
2412 | outlet_new(&x->x_obj, &s_float); | ||
2413 | x->x_pitchout = outlet_new(&x->x_obj, &s_float); | ||
2414 | x->x_velout = outlet_new(&x->x_obj, &s_float); | ||
2415 | x->x_serial = 0; | ||
2416 | return (x); | ||
2417 | } | ||
2418 | |||
2419 | static void poly_float(t_poly *x, t_float f) | ||
2420 | { | ||
2421 | int i; | ||
2422 | t_voice *v; | ||
2423 | t_voice *firston, *firstoff; | ||
2424 | unsigned int serialon, serialoff, onindex = 0, offindex = 0; | ||
2425 | if (x->x_vel > 0) | ||
2426 | { | ||
2427 | /* note on. Look for a vacant voice */ | ||
2428 | for (v = x->x_vec, i = 0, firston = firstoff = 0, | ||
2429 | serialon = serialoff = 0xffffffff; i < x->x_n; v++, i++) | ||
2430 | { | ||
2431 | if (v->v_used && v->v_serial < serialon) | ||
2432 | firston = v, serialon = v->v_serial, onindex = i; | ||
2433 | else if (!v->v_used && v->v_serial < serialoff) | ||
2434 | firstoff = v, serialoff = v->v_serial, offindex = i; | ||
2435 | } | ||
2436 | if (firstoff) | ||
2437 | { | ||
2438 | outlet_float(x->x_velout, x->x_vel); | ||
2439 | outlet_float(x->x_pitchout, firstoff->v_pitch = f); | ||
2440 | outlet_float(x->x_obj.ob_outlet, offindex+1); | ||
2441 | firstoff->v_used = 1; | ||
2442 | firstoff->v_serial = x->x_serial++; | ||
2443 | } | ||
2444 | /* if none, steal one */ | ||
2445 | else if (firston && x->x_steal) | ||
2446 | { | ||
2447 | outlet_float(x->x_velout, 0); | ||
2448 | outlet_float(x->x_pitchout, firston->v_pitch); | ||
2449 | outlet_float(x->x_obj.ob_outlet, onindex+1); | ||
2450 | outlet_float(x->x_velout, x->x_vel); | ||
2451 | outlet_float(x->x_pitchout, firston->v_pitch = f); | ||
2452 | outlet_float(x->x_obj.ob_outlet, onindex+1); | ||
2453 | firston->v_serial = x->x_serial++; | ||
2454 | } | ||
2455 | } | ||
2456 | else /* note off. Turn off oldest match */ | ||
2457 | { | ||
2458 | for (v = x->x_vec, i = 0, firston = 0, serialon = 0xffffffff; | ||
2459 | i < x->x_n; v++, i++) | ||
2460 | if (v->v_used && v->v_pitch == f && v->v_serial < serialon) | ||
2461 | firston = v, serialon = v->v_serial, onindex = i; | ||
2462 | if (firston) | ||
2463 | { | ||
2464 | firston->v_used = 0; | ||
2465 | firston->v_serial = x->x_serial++; | ||
2466 | outlet_float(x->x_velout, 0); | ||
2467 | outlet_float(x->x_pitchout, firston->v_pitch); | ||
2468 | outlet_float(x->x_obj.ob_outlet, onindex+1); | ||
2469 | } | ||
2470 | } | ||
2471 | } | ||
2472 | |||
2473 | static void poly_stop(t_poly *x) | ||
2474 | { | ||
2475 | int i; | ||
2476 | t_voice *v; | ||
2477 | for (i = 0, v = x->x_vec; i < x->x_n; i++, v++) | ||
2478 | if (v->v_used) | ||
2479 | { | ||
2480 | outlet_float(x->x_velout, 0L); | ||
2481 | outlet_float(x->x_pitchout, v->v_pitch); | ||
2482 | outlet_float(x->x_obj.ob_outlet, i+1); | ||
2483 | v->v_used = 0; | ||
2484 | v->v_serial = x->x_serial++; | ||
2485 | } | ||
2486 | } | ||
2487 | |||
2488 | static void poly_clear(t_poly *x) | ||
2489 | { | ||
2490 | int i; | ||
2491 | t_voice *v; | ||
2492 | for (v = x->x_vec, i = x->x_n; i--; v++) v->v_used = v->v_serial = 0; | ||
2493 | } | ||
2494 | |||
2495 | static void poly_free(t_poly *x) | ||
2496 | { | ||
2497 | freebytes(x->x_vec, x->x_n * sizeof (*x->x_vec)); | ||
2498 | } | ||
2499 | |||
2500 | static void poly_setup(void) | ||
2501 | { | ||
2502 | poly_class = class_new(gensym("poly"), | ||
2503 | (t_newmethod)poly_new, (t_method)poly_clear, | ||
2504 | sizeof(t_poly), 0, A_DEFFLOAT, A_DEFFLOAT, 0); | ||
2505 | class_addfloat(poly_class, poly_float); | ||
2506 | class_addmethod(poly_class, (t_method)poly_stop, gensym("stop"), 0); | ||
2507 | class_addmethod(poly_class, (t_method)poly_clear, gensym("clear"), 0); | ||
2508 | } | ||
2509 | |||
2510 | /* -------------------------- bag -------------------------- */ | ||
2511 | |||
2512 | static t_class *bag_class; | ||
2513 | |||
2514 | typedef struct _bagelem | ||
2515 | { | ||
2516 | struct _bagelem *e_next; | ||
2517 | t_float e_value; | ||
2518 | } t_bagelem; | ||
2519 | |||
2520 | typedef struct _bag | ||
2521 | { | ||
2522 | t_object x_obj; | ||
2523 | t_float x_velo; | ||
2524 | t_bagelem *x_first; | ||
2525 | } t_bag; | ||
2526 | |||
2527 | static void *bag_new(void ) | ||
2528 | { | ||
2529 | t_bag *x = (t_bag *)pd_new(bag_class); | ||
2530 | x->x_velo = 0; | ||
2531 | floatinlet_new(&x->x_obj, &x->x_velo); | ||
2532 | outlet_new(&x->x_obj, &s_float); | ||
2533 | x->x_first = 0; | ||
2534 | return (x); | ||
2535 | } | ||
2536 | |||
2537 | static void bag_float(t_bag *x, t_float f) | ||
2538 | { | ||
2539 | t_bagelem *bagelem, *e2, *e3; | ||
2540 | if (x->x_velo != 0) | ||
2541 | { | ||
2542 | bagelem = (t_bagelem *)getbytes(sizeof *bagelem); | ||
2543 | bagelem->e_next = 0; | ||
2544 | bagelem->e_value = f; | ||
2545 | if (!x->x_first) x->x_first = bagelem; | ||
2546 | else /* LATER replace with a faster algorithm */ | ||
2547 | { | ||
2548 | for (e2 = x->x_first; e3 = e2->e_next; e2 = e3) | ||
2549 | ; | ||
2550 | e2->e_next = bagelem; | ||
2551 | } | ||
2552 | } | ||
2553 | else | ||
2554 | { | ||
2555 | if (!x->x_first) return; | ||
2556 | if (x->x_first->e_value == f) | ||
2557 | { | ||
2558 | bagelem = x->x_first; | ||
2559 | x->x_first = x->x_first->e_next; | ||
2560 | freebytes(bagelem, sizeof(*bagelem)); | ||
2561 | return; | ||
2562 | } | ||
2563 | for (e2 = x->x_first; e3 = e2->e_next; e2 = e3) | ||
2564 | if (e3->e_value == f) | ||
2565 | { | ||
2566 | e2->e_next = e3->e_next; | ||
2567 | freebytes(e3, sizeof(*e3)); | ||
2568 | return; | ||
2569 | } | ||
2570 | } | ||
2571 | } | ||
2572 | |||
2573 | static void bag_flush(t_bag *x) | ||
2574 | { | ||
2575 | t_bagelem *bagelem; | ||
2576 | while (bagelem = x->x_first) | ||
2577 | { | ||
2578 | outlet_float(x->x_obj.ob_outlet, bagelem->e_value); | ||
2579 | x->x_first = bagelem->e_next; | ||
2580 | freebytes(bagelem, sizeof(*bagelem)); | ||
2581 | } | ||
2582 | } | ||
2583 | |||
2584 | static void bag_clear(t_bag *x) | ||
2585 | { | ||
2586 | t_bagelem *bagelem; | ||
2587 | while (bagelem = x->x_first) | ||
2588 | { | ||
2589 | x->x_first = bagelem->e_next; | ||
2590 | freebytes(bagelem, sizeof(*bagelem)); | ||
2591 | } | ||
2592 | } | ||
2593 | |||
2594 | static void bag_setup(void) | ||
2595 | { | ||
2596 | bag_class = class_new(gensym("bag"), | ||
2597 | (t_newmethod)bag_new, (t_method)bag_clear, | ||
2598 | sizeof(t_bag), 0, 0); | ||
2599 | class_addfloat(bag_class, bag_float); | ||
2600 | class_addmethod(bag_class, (t_method)bag_flush, gensym("flush"), 0); | ||
2601 | class_addmethod(bag_class, (t_method)bag_clear, gensym("clear"), 0); | ||
2602 | } | ||
2603 | |||
2604 | void x_midi_setup(void) | ||
2605 | { | ||
2606 | midiin_setup(); | ||
2607 | midirealtimein_setup(); | ||
2608 | notein_setup(); | ||
2609 | ctlin_setup(); | ||
2610 | pgmin_setup(); | ||
2611 | bendin_setup(); | ||
2612 | touchin_setup(); | ||
2613 | polytouchin_setup(); | ||
2614 | midiclkin_setup(); | ||
2615 | midiout_setup(); | ||
2616 | noteout_setup(); | ||
2617 | ctlout_setup(); | ||
2618 | pgmout_setup(); | ||
2619 | bendout_setup(); | ||
2620 | touchout_setup(); | ||
2621 | polytouchout_setup(); | ||
2622 | makenote_setup(); | ||
2623 | stripnote_setup(); | ||
2624 | poly_setup(); | ||
2625 | bag_setup(); | ||
2626 | } | ||