1 /*
2 midiops.c:
3
4 Copyright (C) 1995 Barry Vercoe, Gabriel Maldonado,
5 Istvan Varga, John ffitch
6
7 This file is part of Csound.
8
9 The Csound Library is free software; you can redistribute it
10 and/or modify it under the terms of the GNU Lesser General Public
11 License as published by the Free Software Foundation; either
12 version 2.1 of the License, or (at your option) any later version.
13
14 Csound is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU Lesser General Public License for more details.
18
19 You should have received a copy of the GNU Lesser General Public
20 License along with Csound; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
22 02110-1301 USA
23 */
24
25 #include "csoundCore.h" /* MIDIOPS.C */
26 #include "midiops.h"
27 #include <math.h>
28 #include <time.h>
29 #include "namedins.h" /* IV - Oct 31 2002 */
30
31 #define dv127 (FL(1.0)/FL(127.0))
32
33 extern int32_t m_chinsno(CSOUND *csound, int32_t chan,
34 int32_t insno, int32_t reset_ctls);
35
36 #define MIDI_VALUE(m,field) ((m != (MCHNBLK *) NULL) ? m->field : FL(0.0))
37
38 /*
39 * m (=m_chnbp) can easily be NULL (the only place it gets set, as
40 * of 3.484, is in MIDIinsert) so we should check for validity
41 * [added by nicb@axnet.it]
42 */
43
44 /* This line has reverted to checking the null pointer as the code in oload
45 * does leaves it null if there is no chanel. The correct fix is to fix that
46 * code so the test is not dynamic, but until I understand it.... */
47 #define pitchbend_value(m) MIDI_VALUE(m,pchbend)
48
49 #define MGLOB(x) (((CSOUND*)csound)->midiGlobals->x)
50
51 int32_t midibset(CSOUND*, MIDIKMB*);
52
53 /* IV - Oct 31 2002: modified to allow named instruments */
54
massign_p(CSOUND * csound,MASSIGN * p)55 int32_t massign_p(CSOUND *csound, MASSIGN *p)
56 {
57 int32_t chnl = (int32_t)(*p->chnl + FL(0.5));
58 int32_t resetCtls;
59 int32_t retval = OK;
60
61 resetCtls = (*p->iresetctls == FL(0.0) ? 0 : 1);
62 if (--chnl >= 0)
63 retval = m_chinsno(csound, chnl, (int32_t) *p->insno, resetCtls);
64 else {
65 for (chnl = 0; chnl < 16; chnl++) {
66 if (m_chinsno(csound, chnl, (int32_t) *p->insno, resetCtls) != OK)
67 retval = NOTOK;
68 }
69 }
70 return retval;
71 }
72
massign_S(CSOUND * csound,MASSIGNS * p)73 int32_t massign_S(CSOUND *csound, MASSIGNS *p)
74 {
75 int32_t chnl = (int32_t)(*p->chnl + FL(0.5));
76 int32_t instno = 0L;
77 int32_t resetCtls;
78 int32_t retval = OK;
79
80 if (UNLIKELY((instno = strarg2insno(csound, p->insno->data, 1)) <= 0L))
81 return NOTOK;
82
83 resetCtls = (*p->iresetctls == FL(0.0) ? 0 : 1);
84 if (--chnl >= 0)
85 retval = m_chinsno(csound, chnl, (int32_t) instno, resetCtls);
86 else {
87 for (chnl = 0; chnl < 16; chnl++) {
88 if (m_chinsno(csound, chnl, (int32_t) instno, resetCtls) != OK)
89 retval = NOTOK;
90 }
91 }
92 return retval;
93 }
94
95
ctrlinit(CSOUND * csound,CTLINIT * p)96 int32_t ctrlinit(CSOUND *csound, CTLINIT *p)
97 {
98 int16 chnl = (int16)(*p->chnl - FL(0.5));
99 int16 nargs = p->INOCOUNT;
100 if (UNLIKELY((nargs & 0x1) == 0)) {
101 return csound->InitError(csound, Str("uneven ctrl pairs"));
102 }
103 else {
104 MCHNBLK *chn;
105 MYFLT **argp = p->ctrls;
106 int16 ctlno, nctls = nargs >> 1;
107 chn = csound->m_chnbp[chnl];
108 do {
109 MYFLT val;
110 ctlno = (int16)**argp++;
111 if (UNLIKELY(ctlno < 0 || ctlno > 127)) {
112 return csound->InitError(csound, Str("illegal ctrl no"));
113 }
114 val = **argp++;
115 if (val < FL(0.0) || val > FL(127.0))
116 return csound->InitError(csound, Str("Value out of range [0,127]\n"));
117 chn->ctl_val[ctlno] = val;
118 } while (--nctls);
119 return OK;
120 }
121 }
122
notnum(CSOUND * csound,MIDIKMB * p)123 int32_t notnum(CSOUND *csound, MIDIKMB *p) /* valid only at I-time */
124 {
125 *p->r = csound->curip->m_pitch;
126 return OK;
127 }
128
129 /* cpstmid by G.Maldonado */
cpstmid(CSOUND * csound,CPSTABLE * p)130 int32_t cpstmid(CSOUND *csound, CPSTABLE *p)
131 {
132 FUNC *ftp;
133 MYFLT *func;
134 int32_t notenum = csound->curip->m_pitch;
135 int32_t grade;
136 int32_t numgrades;
137 int32_t basekeymidi;
138 MYFLT basefreq, factor, interval;
139
140 if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->tablenum)) == NULL)) {
141 return csound->InitError(csound, Str("cpstabm: invalid modulator table"));
142 }
143 func = ftp->ftable;
144 numgrades = (int32_t)*func++;
145 interval = *func++;
146 basefreq = *func++;
147 basekeymidi = (int32_t)*func++;
148
149 if (notenum < basekeymidi) {
150 notenum = basekeymidi - notenum;
151 grade = (numgrades-(notenum % numgrades)) % numgrades;
152 factor = - (MYFLT)(int32_t)((notenum+numgrades-1) / numgrades) ;
153 }
154 else {
155 notenum = notenum - basekeymidi;
156 grade = notenum % numgrades;
157 factor = (MYFLT)(int32_t)(notenum / numgrades);
158 }
159 factor = POWER(interval, factor);
160 *p->r = func[grade] * factor * basefreq;
161 return OK;
162 }
163
veloc(CSOUND * csound,MIDIMAP * p)164 int32_t veloc(CSOUND *csound, MIDIMAP *p) /* valid only at I-time */
165 {
166 *p->r = *p->ilo + csound->curip->m_veloc*(*p->ihi - *p->ilo) * dv127;
167 return OK;
168 }
169
pchmidi(CSOUND * csound,MIDIKMB * p)170 int32_t pchmidi(CSOUND *csound, MIDIKMB *p)
171 {
172 IGN(csound);
173 INSDS *lcurip = p->h.insdshead;
174 double fract, oct, ioct;
175 oct = lcurip->m_pitch / 12.0 + 3.0;
176 fract = modf(oct, &ioct);
177 fract *= 0.12;
178 *p->r = (MYFLT)(ioct + fract);
179 return OK;
180 }
181
pchmidib(CSOUND * csound,MIDIKMB * p)182 int32_t pchmidib(CSOUND *csound, MIDIKMB *p)
183 {
184 INSDS *lcurip = p->h.insdshead;
185 double fract, oct, ioct;
186 MCHNBLK *xxx = csound->curip->m_chnbp;
187 MYFLT bend = pitchbend_value(xxx);
188 oct = (lcurip->m_pitch + (bend * p->scale)) / FL(12.0) + FL(3.0);
189 fract = modf(oct, &ioct);
190 fract *= 0.12;
191 *p->r = (MYFLT)(ioct + fract);
192 return OK;
193 }
194
pchmidib_i(CSOUND * csound,MIDIKMB * p)195 int32_t pchmidib_i(CSOUND *csound, MIDIKMB *p)
196 {
197 midibset(csound, p);
198 pchmidib(csound, p);
199 return OK;
200 }
201
octmidi(CSOUND * csound,MIDIKMB * p)202 int32_t octmidi(CSOUND *csound, MIDIKMB *p)
203 {
204 IGN(csound);
205 INSDS *lcurip = p->h.insdshead;
206 *p->r = lcurip->m_pitch / FL(12.0) + FL(3.0);
207 return OK;
208 }
209
octmidib(CSOUND * csound,MIDIKMB * p)210 int32_t octmidib(CSOUND *csound, MIDIKMB *p)
211 {
212 IGN(csound);
213 INSDS *lcurip = p->h.insdshead;
214 *p->r = (lcurip->m_pitch + (pitchbend_value(lcurip->m_chnbp) *
215 p->scale)) / FL(12.0) + FL(3.0);
216 return OK;
217 }
218
octmidib_i(CSOUND * csound,MIDIKMB * p)219 int32_t octmidib_i(CSOUND *csound, MIDIKMB *p)
220 {
221 midibset(csound, p);
222 octmidib(csound, p);
223 return OK;
224 }
225
cpsmidi(CSOUND * csound,MIDIKMB * p)226 int32_t cpsmidi(CSOUND *csound, MIDIKMB *p)
227 {
228 INSDS *lcurip = p->h.insdshead;
229 int32_t loct;
230 /* loct = (int64_t)(((lcurip->m_pitch +
231 * pitchbend_value(lcurip->m_chnbp) * p->iscal)/ 12.0f + 3.0f) * OCTRES);
232 */
233 loct = (int32_t)((lcurip->m_pitch/ FL(12.0) + FL(3.0)) * OCTRES);
234 *p->r = CPSOCTL(loct);
235 return OK;
236 }
237
icpsmidib(CSOUND * csound,MIDIKMB * p)238 int32_t icpsmidib(CSOUND *csound, MIDIKMB *p)
239 {
240 INSDS *lcurip = p->h.insdshead;
241 int32_t loct;
242 MYFLT bend = pitchbend_value(lcurip->m_chnbp);
243 p->prvbend = bend;
244 loct = (int32_t)(((lcurip->m_pitch +
245 bend * p->scale) / FL(12.0) + FL(3.0)) * OCTRES);
246 *p->r = CPSOCTL(loct);
247 return OK;
248 }
249
icpsmidib_i(CSOUND * csound,MIDIKMB * p)250 int32_t icpsmidib_i(CSOUND *csound, MIDIKMB *p)
251 {
252 midibset(csound, p);
253 icpsmidib(csound, p);
254 return OK;
255 }
256
kcpsmidib(CSOUND * csound,MIDIKMB * p)257 int32_t kcpsmidib(CSOUND *csound, MIDIKMB *p)
258 {
259 INSDS *lcurip = p->h.insdshead;
260 MYFLT bend = pitchbend_value(lcurip->m_chnbp);
261
262 if (bend == p->prvbend || lcurip->relesing)
263 *p->r = p->prvout;
264 else {
265 int32_t loct;
266 p->prvbend = bend;
267 loct = (int32_t)(((lcurip->m_pitch +
268 bend * p->scale) / FL(12.0) + FL(3.0)) * OCTRES);
269 *p->r = p->prvout = CPSOCTL(loct);
270 }
271 return OK;
272 }
273
ampmidi(CSOUND * csound,MIDIAMP * p)274 int32_t ampmidi(CSOUND *csound, MIDIAMP *p) /* convert midi veloc to amplitude */
275 { /* valid only at I-time */
276 MYFLT amp;
277 int32_t fno;
278 FUNC *ftp;
279
280 amp = csound->curip->m_veloc / FL(128.0); /* amp = normalised veloc */
281 if ((fno = (int32_t)*p->ifn) > 0) { /* if valid ftable, */
282 if (UNLIKELY((ftp = csound->FTnp2Finde(csound, p->ifn)) == NULL))
283 return NOTOK; /* use amp as index */
284 amp = *(ftp->ftable + (int32_t)(amp * ftp->flen));
285 }
286 *p->r = amp * *p->imax; /* now scale the output */
287 return OK;
288 }
289
290 /* MWB 2/11/97 New optional field to set pitch bend range
291 I also changed each of the xxxmidib opcodes, adding * p->scale */
midibset(CSOUND * csound,MIDIKMB * p)292 int32_t midibset(CSOUND *csound, MIDIKMB *p)
293 {
294 MCHNBLK *chn;
295 IGN(csound);
296 chn = p->h.insdshead->m_chnbp;
297 if (*p->iscal > FL(0.0))
298 p->scale = *p->iscal;
299 else if (chn != NULL)
300 p->scale = chn->pbensens;
301 else
302 p->scale = FL(2.0);
303 /* Start from sane position */
304 if (chn != NULL)
305 p->prvbend = chn->pchbend;
306 else
307 p->prvbend = FL(0.0);
308 return OK;
309 }
310
aftset(CSOUND * csound,MIDIKMAP * p)311 int32_t aftset(CSOUND *csound, MIDIKMAP *p)
312 {
313 IGN(csound);
314 p->lo = *p->ilo;
315 p->scale = (*p->ihi - p->lo) * dv127;
316 return OK;
317 }
318
aftouch(CSOUND * csound,MIDIKMAP * p)319 int32_t aftouch(CSOUND *csound, MIDIKMAP *p)
320 {
321 IGN(csound);
322 INSDS *lcurip = p->h.insdshead;
323 *p->r = p->lo + MIDI_VALUE(lcurip->m_chnbp, aftouch) * p->scale;
324 return OK;
325 }
326
imidictl(CSOUND * csound,MIDICTL * p)327 int32_t imidictl(CSOUND *csound, MIDICTL *p)
328 {
329 int32_t ctlno;
330 if (UNLIKELY((ctlno = (int32_t)*p->ictlno) < 0 || ctlno > 127))
331 return csound->InitError(csound, Str("illegal controller number"));
332 else *p->r = MIDI_VALUE(csound->curip->m_chnbp, ctl_val[ctlno])
333 * (*p->ihi - *p->ilo) * dv127 + *p->ilo;
334 return OK;
335 }
336
mctlset(CSOUND * csound,MIDICTL * p)337 int32_t mctlset(CSOUND *csound, MIDICTL *p)
338 {
339 int32_t ctlno;
340 if (UNLIKELY((ctlno = (int32_t)*p->ictlno) < 0 || ctlno > 127))
341 return csound->InitError(csound, Str("illegal controller number"));
342 else {
343 p->ctlno = ctlno;
344 p->scale = (*p->ihi - *p->ilo) * dv127;
345 p->lo = *p->ilo;
346 }
347 return OK;
348 }
349
midictl(CSOUND * csound,MIDICTL * p)350 int32_t midictl(CSOUND *csound, MIDICTL *p)
351 {
352 IGN(csound);
353 INSDS *lcurip = p->h.insdshead;
354 *p->r = MIDI_VALUE(lcurip->m_chnbp, ctl_val[p->ctlno]) * p->scale + p->lo;
355 return OK;
356 }
357
imidiaft(CSOUND * csound,MIDICTL * p)358 int32_t imidiaft(CSOUND *csound, MIDICTL *p)
359 {
360 int32_t ctlno;
361 if (UNLIKELY((ctlno = (int32_t)*p->ictlno) < 0 || ctlno > 127))
362 return csound->InitError(csound, Str("illegal controller number"));
363 else *p->r = MIDI_VALUE(csound->curip->m_chnbp, polyaft[ctlno])
364 * (*p->ihi - *p->ilo) * dv127 + *p->ilo;
365 return OK;
366 }
367
maftset(CSOUND * csound,MIDICTL * p)368 int32_t maftset(CSOUND *csound, MIDICTL *p)
369 {
370 int32_t ctlno;
371 if (UNLIKELY((ctlno = (int32_t)*p->ictlno) < 0 || ctlno > 127))
372 return csound->InitError(csound, Str("illegal controller number"));
373 else {
374 p->ctlno = ctlno;
375 p->scale = (*p->ihi - *p->ilo) * dv127;
376 p->lo = *p->ilo;
377 }
378 return OK;
379 }
380
midiaft(CSOUND * csound,MIDICTL * p)381 int32_t midiaft(CSOUND *csound, MIDICTL *p)
382 {
383 IGN(csound);
384 INSDS *lcurip = p->h.insdshead;
385 *p->r = MIDI_VALUE(lcurip->m_chnbp, polyaft[p->ctlno]) * p->scale + p->lo;
386 return OK;
387 }
388
389 /* midichn opcode - get MIDI channel number or 0 for score notes */
390 /* written by Istvan Varga, May 2002 */
391
midichn(CSOUND * csound,MIDICHN * p)392 int32_t midichn(CSOUND *csound, MIDICHN *p)
393 {
394 *(p->ichn) = (MYFLT) (csound->GetMidiChannelNumber(p) + 1);
395 return OK;
396 }
397
398 /* pgmassign - assign MIDI program to instrument */
399
pgmassign_(CSOUND * csound,PGMASSIGN * p,int32_t instname)400 int32_t pgmassign_(CSOUND *csound, PGMASSIGN *p, int32_t instname)
401 {
402 int32_t pgm, ins, chn;
403
404 chn = (int32_t)(*p->ichn + 0.5);
405 if (UNLIKELY(chn < 0 || chn > 16))
406 return csound->InitError(csound, Str("illegal channel number"));
407 /* IV - Oct 31 2002: allow named instruments */
408 if (instname || csound->ISSTRCOD(*p->inst)) {
409 MYFLT buf[128];
410 csound->strarg2name(csound, (char*) buf, p->inst, "", 1);
411 ins = (int32_t)strarg2insno(csound, buf, 1);
412 }
413 else
414 ins = (int32_t)(*(p->inst) + FL(0.5));
415 if (*(p->ipgm) < FL(0.5)) { /* program <= 0: assign all pgms */
416 if (!chn) { /* on all channels */
417 for (chn = 0; chn < 16; chn++)
418 for (pgm = 0; pgm < 128; pgm++)
419 csound->m_chnbp[chn]->pgm2ins[pgm] = ins;
420 }
421 else { /* or selected channel only */
422 chn--;
423 for (pgm = 0; pgm < 128; pgm++)
424 csound->m_chnbp[chn]->pgm2ins[pgm] = ins;
425 }
426 }
427 else { /* program > 0: assign selected pgm */
428 pgm = (int32_t)(*(p->ipgm) - FL(0.5));
429 if (UNLIKELY(pgm < 0 || pgm > 127)) {
430 return csound->InitError(csound, Str("pgmassign: invalid program number"));
431 }
432 if (!chn) { /* on all channels */
433 for (chn = 0; chn < 16; chn++)
434 csound->m_chnbp[chn]->pgm2ins[pgm] = ins;
435 }
436 else { /* or selected channel only */
437 chn--;
438 csound->m_chnbp[chn]->pgm2ins[pgm] = ins;
439 }
440 }
441 return OK;
442 }
443
pgmassign_S(CSOUND * csound,PGMASSIGN * p)444 int32_t pgmassign_S(CSOUND *csound, PGMASSIGN *p) {
445 return pgmassign_(csound,p,1);
446 }
447
pgmassign(CSOUND * csound,PGMASSIGN * p)448 int32_t pgmassign(CSOUND *csound, PGMASSIGN *p) {
449 return pgmassign_(csound,p,0);
450 }
451
ichanctl(CSOUND * csound,CHANCTL * p)452 int32_t ichanctl(CSOUND *csound, CHANCTL *p)
453 {
454 int32_t ctlno, chan = (int32_t)(*p->ichano - FL(1.0));
455 if (UNLIKELY(chan < 0 || chan > 15 || csound->m_chnbp[chan] == NULL))
456 return csound->InitError(csound, Str("illegal channel number"));
457 if (UNLIKELY((ctlno = (int32_t)*p->ictlno) < 0 || ctlno > 127))
458 return csound->InitError(csound, Str("illegal controller number"));
459 else *p->r = csound->m_chnbp[chan]->ctl_val[ctlno] * (*p->ihi - *p->ilo)
460 * dv127 + *p->ilo;
461 return OK;
462 }
463
chctlset(CSOUND * csound,CHANCTL * p)464 int32_t chctlset(CSOUND *csound, CHANCTL *p)
465 {
466 int32_t ctlno, chan = (int32_t)(*p->ichano - FL(1.0));
467 if (UNLIKELY(chan < 0 || chan > 15 || csound->m_chnbp[chan] == NULL)) {
468 return csound->InitError(csound, Str("illegal channel number"));
469 }
470 p->chano = chan;
471 if (UNLIKELY((ctlno = (int32_t)*p->ictlno) < 0 || ctlno > 127)) {
472 return csound->InitError(csound, Str("illegal controller number"));
473 }
474 else {
475 p->ctlno = ctlno;
476 p->scale = (*p->ihi - *p->ilo) * dv127;
477 p->lo = *p->ilo;
478 }
479 return OK;
480 }
481
chanctl(CSOUND * csound,CHANCTL * p)482 int32_t chanctl(CSOUND *csound, CHANCTL *p)
483 {
484 *p->r = csound->m_chnbp[p->chano]->ctl_val[p->ctlno] * p->scale + p->lo;
485 return OK;
486 }
487
ipchbend(CSOUND * csound,MIDIMAP * p)488 int32_t ipchbend(CSOUND *csound, MIDIMAP *p)
489 {
490 IGN(csound);
491 *p->r = *p->ilo + (*p->ihi - *p->ilo) *
492 pitchbend_value(p->h.insdshead->m_chnbp);
493 return OK;
494 }
495
kbndset(CSOUND * csound,MIDIKMAP * p)496 int32_t kbndset(CSOUND *csound, MIDIKMAP *p)
497 {
498 IGN(csound);
499 p->lo = *p->ilo;
500 p->scale = *p->ihi - *p->ilo;
501 return OK;
502 }
503
kpchbend(CSOUND * csound,MIDIKMAP * p)504 int32_t kpchbend(CSOUND *csound, MIDIKMAP *p)
505 {
506 IGN(csound);
507 INSDS *lcurip = p->h.insdshead;
508 *p->r = p->lo + pitchbend_value(lcurip->m_chnbp) * p->scale;
509 return OK;
510 }
511
midiin_set(CSOUND * csound,MIDIIN * p)512 int32_t midiin_set(CSOUND *csound, MIDIIN *p)
513 {
514 p->local_buf_index = MGLOB(MIDIINbufIndex) & MIDIINBUFMSK;
515 return OK;
516 }
517
midiin(CSOUND * csound,MIDIIN * p)518 int32_t midiin(CSOUND *csound, MIDIIN *p)
519 {
520 unsigned char *temp; /* IV - Nov 30 2002 */
521 if (p->local_buf_index != MGLOB(MIDIINbufIndex)) {
522 temp = &(MGLOB(MIDIINbuffer2)[p->local_buf_index++].bData[0]);
523 p->local_buf_index &= MIDIINBUFMSK;
524 *p->status = (MYFLT) *temp; //(*temp & (unsigned char) 0xf0);
525 *p->chan = (MYFLT) *++temp; //((*temp & 0x0f) + 1);
526 *p->data1 = (MYFLT) *++temp;
527 *p->data2 = (MYFLT) *++temp;
528 }
529 else *p->status = FL(0.0);
530 return OK;
531 }
532
pgmin_set(CSOUND * csound,PGMIN * p)533 int32_t pgmin_set(CSOUND *csound, PGMIN *p)
534 {
535 p->local_buf_index = MGLOB(MIDIINbufIndex) & MIDIINBUFMSK;
536 p->watch =(int32_t)*p->ochan;
537 return OK;
538 }
539
pgmin(CSOUND * csound,PGMIN * p)540 int32_t pgmin(CSOUND *csound, PGMIN *p)
541 {
542 unsigned char *temp;
543 if (p->local_buf_index != MGLOB(MIDIINbufIndex)) {
544 int32_t st,ch,d1;
545 temp = &(MGLOB(MIDIINbuffer2)[p->local_buf_index++].bData[0]);
546 st = *temp & (unsigned char) 0xf0;
547 ch = (*temp & 0x0f) + 1;
548 d1 = *++temp;
549 /* d2 = *++temp; */
550 if (st == 0xC0 && (p->watch==0 || p->watch==ch)) {
551 *p->pgm = (MYFLT)1+d1;
552 *p->chn = (MYFLT)ch;
553 }
554 else {
555 *p->pgm = FL(-1.0);
556 *p->chn = FL(0.0);
557 }
558 p->local_buf_index &= MIDIINBUFMSK;
559 }
560 else {
561 *p->pgm = FL(-1.0);
562 *p->chn = FL(0.0);
563 }
564 return OK;
565 }
566
ctlin_set(CSOUND * csound,CTLIN * p)567 int32_t ctlin_set(CSOUND *csound, CTLIN *p)
568 {
569 p->local_buf_index = MGLOB(MIDIINbufIndex) & MIDIINBUFMSK;
570 p->watch1 =(int32_t)*p->ochan;
571 p->watch2 =(int32_t)*p->onum;
572 return OK;
573 }
574
ctlin(CSOUND * csound,CTLIN * p)575 int32_t ctlin(CSOUND *csound, CTLIN *p)
576 {
577 unsigned char *temp;
578 if (p->local_buf_index != MGLOB(MIDIINbufIndex)) {
579 int32_t st,ch,d1,d2;
580 temp = &(MGLOB(MIDIINbuffer2)[p->local_buf_index++].bData[0]);
581 st = *temp & (unsigned char) 0xf0;
582 ch = (*temp & 0x0f) + 1;
583 d1 = *++temp;
584 d2 = *++temp;
585 if (st == 0xB0 &&
586 (p->watch1==0 || p->watch1==ch) &&
587 (p->watch2==0 || p->watch2==d2)) {
588 *p->data = (MYFLT)d1;
589 *p->numb = (MYFLT)d2;
590 *p->chn = (MYFLT)ch;
591 }
592 else {
593 *p->data = FL(-1.0);
594 *p->numb = FL(-1.0);
595 *p->chn = FL(0.0);
596 }
597 p->local_buf_index &= MIDIINBUFMSK;
598 }
599 else {
600 *p->data = FL(-1.0);
601 *p->numb = FL(-1.0);
602 *p->chn = FL(0.0);
603 }
604 return OK;
605
606 }
607
608
609 /* MIDIARP by Rory Walsh, 2016
610 */
611
midiarp_set(CSOUND * csound,MIDIARP * p)612 int32_t midiarp_set(CSOUND *csound, MIDIARP *p)
613 /* MIDI Arp - Jan 2017 - RW */
614 {
615 int32_t cnt;
616 srand(time(NULL));
617 p->flag=1, *p->arpMode=0, p->direction=2, p->noteIndex=9;
618 p->maxNumNotes=10, p->noteCnt=0, p->status=0, p->chan=0;
619 p->data1=0, p->data2=0;
620
621 p->local_buf_index = MGLOB(MIDIINbufIndex) & MIDIINBUFMSK;
622
623 for (cnt=0;cnt<10;cnt++)
624 p->notes[cnt] = 0;
625
626 return OK;
627 }
628
sort_notes(int32_t notes[],int32_t n)629 void sort_notes(int32_t notes[], int32_t n)
630 {
631 int32_t j,i,tmp;
632 for (i = 0; i < n; ++i) {
633 for (j = i + 1; j < n; ++j) {
634 if (notes[i] > notes[j]) {
635 tmp = notes[i];
636 notes[i] = notes[j];
637 notes[j] = tmp;
638 }
639 }
640 }
641 }
642
zeroNoteFromArray(int32_t notes[],int32_t noteNumber,int32_t size)643 void zeroNoteFromArray(int32_t notes[], int32_t noteNumber, int32_t size)
644 {
645 int32_t i;
646 for (i=0;i<size;i++) {
647 if (notes[i]==noteNumber)
648 notes[i]=0;
649 }
650 }
651
metroCounter(MIDIARP * p)652 int32_t metroCounter(MIDIARP *p)
653 {
654 double phs = p->curphs;
655 if (phs == 0.0 && p->flag) {
656 p->metroTick = FL(1.0);
657 p->flag = 0;
658 }
659 else if ((phs += *p->arpRate * CS_ONEDKR) >= 1.0) {
660 p->metroTick = FL(1.0);
661 phs -= 1.0;
662 p->flag = 0;
663 }
664 else
665 p->metroTick = FL(0.0);
666
667 p->curphs = phs;
668 return p->metroTick;
669 }
670
671
midiarp(CSOUND * csound,MIDIARP * p)672 int32_t midiarp(CSOUND *csound, MIDIARP *p)
673 {
674 int32_t i=0;
675 unsigned char *temp;
676 int32_t arpmode = (int32_t)*p->arpMode;
677
678 if (p->local_buf_index != MGLOB(MIDIINbufIndex))
679 {
680 temp = &(MGLOB(MIDIINbuffer2)[p->local_buf_index++].bData[0]);
681 p->local_buf_index &= MIDIINBUFMSK;
682 p->status = (MYFLT) (*temp & (unsigned char) 0xf0);
683 p->chan = (MYFLT) ((*temp & 0x0f) + 1);
684 p->data1 = (MYFLT) *++temp;
685 p->data2 = (MYFLT) *++temp;
686
687 if (p->status==144 && p->data2>0) {
688 p->notes[p->noteCnt] = p->data1;
689
690 for (i = 0 ; i < p->maxNumNotes ; i++)
691 p->sortedNotes[i] = p->notes[i];
692
693 p->noteCnt = (p->noteCnt>p->maxNumNotes-1 ?
694 p->maxNumNotes-1 : p->noteCnt+1);
695 sort_notes(p->sortedNotes, 10);
696
697 }
698 else if (p->status==128 || (p->status==144 && p->data2==0)) {
699 zeroNoteFromArray(p->notes, p->data1, p->maxNumNotes);
700
701 for (i = 0 ; i < p->maxNumNotes ; i++)
702 p->sortedNotes[i] = p->notes[i];
703
704 p->noteCnt = (p->noteCnt<0 ? 0 : p->noteCnt-1);
705 sort_notes(p->sortedNotes, p->maxNumNotes);
706 }
707 }
708 else p->status = FL(0.0);
709
710 if (p->noteCnt != 0) {
711 // only when some note/s are pressed
712 *p->counter = metroCounter(p);
713 if (*p->counter == 1) {
714
715 if (p->noteIndex<p->maxNumNotes && p->sortedNotes[p->noteIndex]!=0)
716 *p->noteOut = p->sortedNotes[p->noteIndex];
717
718 if (arpmode==0) {
719 //up and down pattern
720 if (p->direction>0) {
721 p->noteIndex = (p->noteIndex < p->maxNumNotes-1
722 ? p->noteIndex+1 : p->maxNumNotes - p->noteCnt);
723 if (p->noteIndex==p->maxNumNotes-1)
724 p->direction = -2;
725 }
726 else {
727 p->noteIndex = (p->noteIndex > p->maxNumNotes - p->noteCnt
728 ? p->noteIndex-1 : p->maxNumNotes-1);
729 if (p->noteIndex==p->maxNumNotes-p->noteCnt)
730 p->direction = 2;
731
732 }
733 }
734 else if (arpmode==1) {
735 //up only pattern
736 p->noteIndex = (p->noteIndex < p->maxNumNotes-1
737 ? p->noteIndex+1 : p->maxNumNotes - p->noteCnt);
738 }
739 else if (arpmode==2) {
740 //down only pattern
741 p->noteIndex = (p->noteIndex > p->maxNumNotes - p->noteCnt
742 ? p->noteIndex-1 : p->maxNumNotes-1);
743 }
744 else if (arpmode==3) {
745 //random pattern
746 int32_t randIndex = ((rand() % 100)/100.f)*(p->noteCnt);
747 p->noteIndex = p->maxNumNotes-randIndex-1;
748 }
749 else{
750 csound->Message(csound,
751 Str("Invalid arp mode selected:"
752 " %d. Valid modes are 0, 1, 2, and 3\n"),
753 arpmode);
754 }
755 }
756 }
757
758 return OK;
759 }
760