1 /*
2 insert.c:
3
4 Copyright (C) 1991, 1997, 1999, 2002, 2005
5 Barry Vercoe, Istvan Varga, John ffitch,
6 Gabriel Maldonado, matt ingalls
7
8 This file is part of Csound.
9
10 The Csound Library is free software; you can redistribute it
11 and/or modify it under the terms of the GNU Lesser General Public
12 License as published by the Free Software Foundation; either
13 version 2.1 of the License, or (at your option) any later version.
14
15 Csound is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU Lesser General Public License for more details.
19
20 You should have received a copy of the GNU Lesser General Public
21 License along with Csound; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
23 02110-1301 USA
24 */
25
26 #include "csoundCore.h" /* INSERT.C */
27 #include "oload.h"
28 #include "insert.h" /* for goto's */
29 #include "aops.h" /* for cond's */
30 #include "midiops.h"
31 #include "namedins.h" /* IV - Oct 31 2002 */
32 #include "pstream.h"
33 #include "interlocks.h"
34 #include "csound_type_system.h"
35 #include "csound_standard_types.h"
36 #include <inttypes.h>
37
38 static void showallocs(CSOUND *);
39 static void deact(CSOUND *, INSDS *);
40 static void schedofftim(CSOUND *, INSDS *);
41 void beatexpire(CSOUND *, double);
42 void timexpire(CSOUND *, double);
43 static void instance(CSOUND *, int);
44 extern int argsRequired(char* argString);
45 static int insert_midi(CSOUND *csound, int insno, MCHNBLK *chn,
46 MEVENT *mep);
47 static int insert_event(CSOUND *csound, int insno, EVTBLK *newevtp);
48
print_messages(CSOUND * csound,int attr,const char * str)49 static void print_messages(CSOUND *csound, int attr, const char *str){
50 #if defined(WIN32)
51 switch (attr & CSOUNDMSG_TYPE_MASK) {
52 case CSOUNDMSG_ERROR:
53 case CSOUNDMSG_WARNING:
54 case CSOUNDMSG_REALTIME:
55 fprintf(stderr, str);
56 break;
57 default:
58 fprintf(stdout, str);
59 }
60 #else
61 FILE *fp = stderr;
62 if ((attr & CSOUNDMSG_TYPE_MASK) == CSOUNDMSG_STDOUT)
63 fp = stdout;
64 if (!attr || !csound->enableMsgAttr) {
65 fprintf(fp, "%s", str);
66 return;
67 }
68 if ((attr & CSOUNDMSG_TYPE_MASK) == CSOUNDMSG_ORCH)
69 if (attr & CSOUNDMSG_BG_COLOR_MASK)
70 fprintf(fp, "\033[4%cm", ((attr & 0x70) >> 4) + '0');
71 if (attr & CSOUNDMSG_FG_ATTR_MASK) {
72 if (attr & CSOUNDMSG_FG_BOLD)
73 fprintf(fp, "\033[1m");
74 if (attr & CSOUNDMSG_FG_UNDERLINE)
75 fprintf(fp, "\033[4m");
76 }
77 if (attr & CSOUNDMSG_FG_COLOR_MASK)
78 fprintf(fp, "\033[3%cm", (attr & 7) + '0');
79 fprintf(fp, "%s", str);
80 fprintf(fp, "\033[m");
81 #endif
82 }
83
84 #define QUEUESIZ 64
85
message_string_enqueue(CSOUND * csound,int attr,const char * str)86 static void message_string_enqueue(CSOUND *csound, int attr,
87 const char *str) {
88 unsigned long wp = csound->message_string_queue_wp;
89 csound->message_string_queue[wp].attr = attr;
90 strNcpy(csound->message_string_queue[wp].str, str, MAX_MESSAGE_STR);
91 //csound->message_string_queue[wp].str[MAX_MESSAGE_STR-1] = '\0';
92 csound->message_string_queue_wp = wp + 1 < QUEUESIZ ? wp + 1 : 0;
93 ATOMIC_INCR(csound->message_string_queue_items);
94 }
95
no_op(CSOUND * csound,int attr,const char * format,va_list args)96 static void no_op(CSOUND *csound, int attr,
97 const char *format, va_list args) {
98 IGN(csound);
99 IGN(attr);
100 IGN(format);
101 IGN(args);
102 };
103
104
105 /* do init pass for this instr */
init_pass(CSOUND * csound,INSDS * ip)106 static int init_pass(CSOUND *csound, INSDS *ip) {
107 int error = 0;
108 if(csound->oparms->realtime)
109 csoundLockMutex(csound->init_pass_threadlock);
110 csound->curip = ip;
111 csound->ids = (OPDS *)ip;
112 csound->mode = 1;
113 while (error == 0 && (csound->ids = csound->ids->nxti) != NULL) {
114 csound->op = csound->ids->optext->t.oentry->opname;
115 if (UNLIKELY(csound->oparms->odebug))
116 csound->Message(csound, "init %s:\n", csound->op);
117 error = (*csound->ids->iopadr)(csound, csound->ids);
118 }
119 csound->mode = 0;
120 if(csound->oparms->realtime)
121 csoundUnlockMutex(csound->init_pass_threadlock);
122 return error;
123 }
124
125 int rireturn(CSOUND *csound, void *p);
126 /* do reinit pass */
reinit_pass(CSOUND * csound,INSDS * ip,OPDS * ids)127 static int reinit_pass(CSOUND *csound, INSDS *ip, OPDS *ids) {
128 int error = 0;
129 if(csound->oparms->realtime) {
130 csoundLockMutex(csound->init_pass_threadlock);
131 }
132 csound->curip = ip;
133 csound->ids = ids;
134 csound->mode = 1;
135 while (error == 0 && (csound->ids = csound->ids->nxti) != NULL &&
136 (csound->ids->iopadr != (SUBR) rireturn)){
137 csound->op = csound->ids->optext->t.oentry->opname;
138 if (UNLIKELY(csound->oparms->odebug))
139 csound->Message(csound, "reinit %s:\n", csound->op);
140 error = (*csound->ids->iopadr)(csound, csound->ids);
141 }
142 csound->mode = 0;
143
144 ATOMIC_SET8(ip->actflg, 1);
145 csound->reinitflag = ip->reinitflag = 0;
146 if(csound->oparms->realtime)
147 csoundUnlockMutex(csound->init_pass_threadlock);
148 return error;
149 }
150
151
152 /*
153 * creates a thread to process instance allocations
154 */
event_insert_thread(void * p)155 uintptr_t event_insert_thread(void *p) {
156 CSOUND *csound = (CSOUND *) p;
157 ALLOC_DATA *inst = csound->alloc_queue;
158 float wakeup = (1000*csound->ksmps/csound->esr);
159 unsigned long rp = 0, items, rpm = 0;
160 message_string_queue_t *mess = NULL;
161 void (*csoundMessageStringCallback)(CSOUND *csound,
162 int attr,
163 const char *str) = NULL;
164 void (*csoundMessageCallback)(CSOUND *csound,
165 int attr,
166 const char *format,
167 va_list args)
168 = csound->csoundMessageCallback_;
169 if(csound->oparms_.msglevel){
170 if(csound->message_string_queue == NULL)
171 csound->message_string_queue = (message_string_queue_t *)
172 csound->Calloc(csound, QUEUESIZ*sizeof(message_string_queue_t));
173 mess = csound->message_string_queue;
174 if(csound->csoundMessageStringCallback)
175 csoundMessageStringCallback = csound->csoundMessageStringCallback;
176 else csoundMessageStringCallback = print_messages;
177 csoundSetMessageStringCallback(csound, message_string_enqueue);
178 } else {
179 csoundSetMessageCallback(csound, no_op);
180 }
181
182 while(csound->event_insert_loop) {
183 // get the value of items_to_alloc
184 items = ATOMIC_GET(csound->alloc_queue_items);
185 if(items == 0)
186 csoundSleep((int) ((int) wakeup > 0 ? wakeup : 1));
187 else while(items) {
188 if (inst[rp].type == 3) {
189 INSDS *ip = inst[rp].ip;
190 OPDS *ids = inst[rp].ids;
191 csoundSpinLock(&csound->alloc_spinlock);
192 reinit_pass(csound, ip, ids);
193 csoundSpinUnLock(&csound->alloc_spinlock);
194 ATOMIC_SET(ip->init_done, 1);
195 }
196 if (inst[rp].type == 2) {
197 INSDS *ip = inst[rp].ip;
198 ATOMIC_SET(ip->init_done, 0);
199 csoundSpinLock(&csound->alloc_spinlock);
200 init_pass(csound, ip);
201 csoundSpinUnLock(&csound->alloc_spinlock);
202 ATOMIC_SET(ip->init_done, 1);
203 }
204 if(inst[rp].type == 1) {
205 csoundSpinLock(&csound->alloc_spinlock);
206 insert_midi(csound, inst[rp].insno, inst[rp].chn, &inst[rp].mep);
207 csoundSpinUnLock(&csound->alloc_spinlock);
208 }
209 if(inst[rp].type == 0) {
210 csoundSpinLock(&csound->alloc_spinlock);
211 insert_event(csound, inst[rp].insno, &inst[rp].blk);
212 csoundSpinUnLock(&csound->alloc_spinlock);
213 }
214 // decrement the value of items_to_alloc
215 ATOMIC_DECR(csound->alloc_queue_items);
216 items--;
217 rp = rp + 1 < MAX_ALLOC_QUEUE ? rp + 1 : 0;
218 }
219 items = ATOMIC_GET(csound->message_string_queue_items);
220 while(items) {
221 if(mess != NULL)
222 csoundMessageStringCallback(csound, mess[rpm].attr, mess[rpm].str);
223 ATOMIC_DECR(csound->message_string_queue_items);
224 items--;
225 rpm = rpm + 1 < QUEUESIZ ? rpm + 1 : 0;
226 }
227
228 }
229
230 csoundSetMessageCallback(csound, csoundMessageCallback);
231 return (uintptr_t) NULL;
232 }
233
init0(CSOUND * csound)234 int init0(CSOUND *csound)
235 {
236 INSTRTXT *tp = csound->engineState.instrtxtp[0];
237 INSDS *ip;
238
239 instance(csound, 0); /* allocate instr 0 */
240 csound->curip = ip = tp->act_instance;
241 tp->act_instance = ip->nxtact;
242 csound->ids = (OPDS*) ip;
243 tp->active++;
244 ip->actflg++;
245 ip->ksmps = csound->ksmps;
246 ip->ekr = csound->ekr;
247 ip->kcounter = csound->kcounter;
248 ip->onedksmps = csound->onedksmps;
249 ip->onedkr = csound->onedkr;
250 ip->kicvt = csound->kicvt;
251 csound->inerrcnt = 0;
252 csound->mode = 1;
253 while ((csound->ids = csound->ids->nxti) != NULL) {
254 csound->op = csound->ids->optext->t.oentry->opname;
255 (*csound->ids->iopadr)(csound, csound->ids); /* run all i-code */
256 }
257 csound->mode = 0;
258 return csound->inerrcnt; /* return errcnt */
259 }
260
putop(CSOUND * csound,TEXT * tp)261 static void putop(CSOUND *csound, TEXT *tp)
262 {
263 int n, nn;
264
265 if ((n = tp->outlist->count) != 0) {
266 nn = 0;
267 while (n--)
268 csound->Message(csound, "%s\t", tp->outlist->arg[nn++]);
269 }
270 else
271 csound->Message(csound, "\t");
272 csound->Message(csound, "%s\t", tp->opcod);
273 if ((n = tp->inlist->count) != 0) {
274 nn = 0;
275 while (n--)
276 csound->Message(csound, "%s\t", tp->inlist->arg[nn++]);
277 }
278 csound->Message(csound, "\n");
279 }
280
set_xtratim(CSOUND * csound,INSDS * ip)281 static void set_xtratim(CSOUND *csound, INSDS *ip)
282 {
283 if (UNLIKELY(ip->relesing))
284 return;
285 ip->offtim = (csound->icurTime +
286 ip->ksmps * (double) ip->xtratim)/csound->esr;
287 ip->offbet = csound->curBeat + (csound->curBeat_inc * (double) ip->xtratim);
288 ip->relesing = 1;
289 csound->engineState.instrtxtp[ip->insno]->pending_release++;
290 }
291
292 /* insert an instr copy into active list */
293 /* then run an init pass */
insert(CSOUND * csound,int insno,EVTBLK * newevtp)294 int insert(CSOUND *csound, int insno, EVTBLK *newevtp) {
295
296 if(csound->oparms->realtime) {
297 unsigned long wp = csound->alloc_queue_wp;
298 csound->alloc_queue[wp].insno = insno;
299 csound->alloc_queue[wp].blk = *newevtp;
300 csound->alloc_queue[wp].type = 0;
301 csound->alloc_queue_wp = wp + 1 < MAX_ALLOC_QUEUE ? wp + 1 : 0;
302 ATOMIC_INCR(csound->alloc_queue_items);
303 return 0;
304 }
305 else return insert_event(csound, insno, newevtp);
306 }
307
insert_event(CSOUND * csound,int insno,EVTBLK * newevtp)308 int insert_event(CSOUND *csound, int insno, EVTBLK *newevtp)
309 {
310 INSTRTXT *tp;
311 INSDS *ip, *prvp, *nxtp;
312 OPARMS *O = csound->oparms;
313 CS_VAR_MEM *pfields = NULL; /* *** was uninitialised *** */
314 int tie=0, i;
315 int n, error = 0;
316 MYFLT *flp, *fep;
317
318 if (UNLIKELY(csound->advanceCnt))
319 return 0;
320 if (UNLIKELY(O->odebug)) {
321 char *name = csound->engineState.instrtxtp[insno]->insname;
322 if (UNLIKELY(name))
323 csound->Message(csound, Str("activating instr %s at %"PRIi64"\n"),
324 name, csound->icurTime);
325 else
326 csound->Message(csound, Str("activating instr %d at %"PRIi64"\n"),
327 insno, csound->icurTime);
328 }
329 csound->inerrcnt = 0;
330
331
332 tp = csound->engineState.instrtxtp[insno];
333 if (UNLIKELY(tp->muted == 0)) {
334 char *name = csound->engineState.instrtxtp[insno]->insname;
335 if (UNLIKELY(name))
336 csound->Warning(csound, Str("Instrument %s muted\n"), name);
337 else
338 csound->Warning(csound, Str("Instrument %d muted\n"), insno);
339 return 0;
340 }
341 if (tp->cpuload > FL(0.0)) {
342 csound->cpu_power_busy += tp->cpuload;
343 /* if there is no more cpu processing time*/
344 if (UNLIKELY(csound->cpu_power_busy > FL(100.0))) {
345 csound->cpu_power_busy -= tp->cpuload;
346 csoundWarning(csound, Str("cannot allocate last note because "
347 "it exceeds 100%% of cpu time"));
348 return(0);
349 }
350 }
351 if (UNLIKELY(tp->maxalloc > 0 && tp->active >= tp->maxalloc)) {
352 csoundWarning(csound, Str("cannot allocate last note because it exceeds "
353 "instr maxalloc"));
354 return(0);
355 }
356 /* if find this insno, active, with indef (tie) & matching p1 */
357 for (ip = tp->instance; ip != NULL; ip = ip->nxtinstance) {
358 if (ip->actflg && ip->offtim < 0.0 && ip->p1.value == newevtp->p[1]) {
359 csound->tieflag++;
360 ip->tieflag = 1;
361 tie = 1;
362 /* goto init; */ /* continue that event */
363 break;
364 }
365 }
366
367 if(!tie) {
368 /* alloc new dspace if needed */
369 if (tp->act_instance == NULL || tp->isNew) {
370 if (UNLIKELY(O->msglevel & RNGEMSG)) {
371 char *name = csound->engineState.instrtxtp[insno]->insname;
372 if (UNLIKELY(name))
373 csound->Message(csound, Str("new alloc for instr %s:\n"), name);
374 else
375 csound->Message(csound, Str("new alloc for instr %d:\n"), insno);
376 }
377 instance(csound, insno);
378 tp->isNew=0;
379 }
380
381 /* pop from free instance chain */
382 if (UNLIKELY(csound->oparms->odebug))
383 csoundMessage(csound, "insert(): tp->act_instance = %p\n", tp->act_instance);
384 ip = tp->act_instance;
385 ATOMIC_SET(ip->init_done, 0);
386 tp->act_instance = ip->nxtact;
387 ip->insno = (int16) insno;
388 ip->ksmps = csound->ksmps;
389 ip->ekr = csound->ekr;
390 ip->kcounter = csound->kcounter;
391 ip->onedksmps = csound->onedksmps;
392 ip->onedkr = csound->onedkr;
393 ip->kicvt = csound->kicvt;
394 ip->pds = NULL;
395 /* Add an active instrument */
396 tp->active++;
397 tp->instcnt++;
398 csound->dag_changed++; /* Need to remake DAG */
399 nxtp = &(csound->actanchor); /* now splice into activ lst */
400 while ((prvp = nxtp) && (nxtp = prvp->nxtact) != NULL) {
401 if (nxtp->insno > insno ||
402 (nxtp->insno == insno && nxtp->p1.value > newevtp->p[1])) {
403 nxtp->prvact = ip;
404 break;
405 }
406 }
407 ip->nxtact = nxtp;
408 ip->prvact = prvp;
409 prvp->nxtact = ip;
410 ip->tieflag = 0;
411 ip->actflg++; /* and mark the instr active */
412 }
413
414
415 /* init: */
416 pfields = (CS_VAR_MEM*)&ip->p0;
417 if (tp->psetdata) {
418 int i;
419 CS_VAR_MEM* pfields = (CS_VAR_MEM*) &ip->p0;
420 MYFLT *pdat = tp->psetdata + 2;
421 int32 nn = tp->pmax - 2; /* put cur vals in pflds */
422
423 for (i = 0; i < nn; i++) {
424 CS_VAR_MEM* pfield = (pfields + i + 3);
425 pfield->value = *(pdat + i);
426 }
427 }
428 n = tp->pmax;
429 if (UNLIKELY((tp->nocheckpcnt == 0) &&
430 n != newevtp->pcnt &&
431 !tp->psetdata)) {
432 char *name = csound->engineState.instrtxtp[insno]->insname;
433 if (UNLIKELY(name))
434 csoundWarning(csound, Str("instr %s uses %d p-fields but is given %d"),
435 name, n, newevtp->pcnt);
436 else
437 csoundWarning(csound, Str("instr %d uses %d p-fields but is given %d"),
438 insno, n, newevtp->pcnt);
439 }
440 if (newevtp->p3orig >= FL(0.0))
441 ip->offbet = csound->beatOffs
442 + (double) newevtp->p2orig + (double) newevtp->p3orig;
443 else
444 ip->offbet = -1.0;
445 flp = &ip->p1.value;
446 fep = &newevtp->p[0];
447
448 if (UNLIKELY(O->odebug))
449 csound->Message(csound, "psave beg at %p\n", (void*) flp);
450 if (n > newevtp->pcnt) n = newevtp->pcnt; /* IV - Oct 20 2002 */
451 for (i = 1; i < n + 1; i++) {
452 CS_VAR_MEM* pfield = pfields + i;
453 pfield->varType = (CS_TYPE*)&CS_VAR_TYPE_P;
454 pfield->value = fep[i];
455 }
456 if (n < tp->pmax && tp->psetdata==NULL) {
457 for (i = 0; i < tp->pmax - n; i++) {
458 CS_VAR_MEM* pfield = pfields + i + n + 1;
459 pfield->varType = (CS_TYPE*)&CS_VAR_TYPE_P;
460 pfield->value = 0;
461 }
462 }
463 if (UNLIKELY(O->odebug))
464 csound->Message(csound, " ending at %p\n", (void*) flp);
465
466 if (O->Beatmode)
467 ip->p2.value = (MYFLT) (csound->icurTime/csound->esr - csound->timeOffs);
468 ip->offtim = (double) ip->p3.value; /* & duplicate p3 for now */
469 ip->m_chnbp = (MCHNBLK*) NULL;
470 ip->xtratim = 0;
471 ip->relesing = 0;
472 ip->m_sust = 0;
473 ip->nxtolap = NULL;
474 ip->opcod_iobufs = NULL;
475 ip->strarg = newevtp->strarg; /* copy strarg so it does not get lost */
476
477 // current event needs to be reset here
478 csound->init_event = newevtp;
479 error = init_pass(csound, ip);
480 if(error == 0)
481 ATOMIC_SET(ip->init_done, 1);
482 if (UNLIKELY(csound->inerrcnt || ip->p3.value == FL(0.0))) {
483 xturnoff_now(csound, ip);
484 return csound->inerrcnt;
485 }
486
487 /* new code for sample-accurate timing, not for tied notes */
488 if (O->sampleAccurate && !tie) {
489 int64_t start_time_samps, start_time_kcycles;
490 double duration_samps;
491 start_time_samps = (int64_t) (ip->p2.value * csound->esr);
492 duration_samps = ip->p3.value * csound->esr;
493 start_time_kcycles = start_time_samps/csound->ksmps;
494 ip->ksmps_offset = start_time_samps - start_time_kcycles*csound->ksmps;
495 /* with no p3 or xtratim values, can't set the sample accur duration */
496 if (ip->p3.value > 0 && ip->xtratim == 0 ){
497 int tmp = ((int)duration_samps+ip->ksmps_offset)%csound->ksmps;
498 if (tmp != 0)ip->no_end = csound->ksmps - tmp; else ip->no_end = 0;
499 //ip->no_end = (csound->ksmps -
500 // ((int)duration_samps+ip->ksmps_offset)%csound->ksmps)%csound->ksmps;
501 /* the ksmps_no_end field is initially 0, set to no_end in the last
502 perf cycle */
503 // printf("*** duration_samps %d ip->ksmps_offset %d csound->ksmps %d ==> %d\n",
504 // (int)duration_samps, ip->ksmps_offset, csound->ksmps, ip->no_end);
505 }
506 else ip->no_end = 0;
507 ip->ksmps_no_end = 0;
508 }
509 else {
510 /* ksmps_offset = */
511 ip->ksmps_offset = 0;
512 ip->ksmps_no_end = 0;
513 ip->no_end = 0;
514 }
515
516 #ifdef BETA
517 if (UNLIKELY(O->odebug))
518 csound->Message(csound, "In insert: %d %lf %lf\n",
519 __LINE__, ip->p3.value, ip->offtim); /* *********** */
520 #endif
521 if (ip->p3.value > FL(0.0) && ip->offtim > 0.0) { /* if still finite time, */
522 double p2 = (double) ip->p2.value + csound->timeOffs;
523 ip->offtim = p2 + (double) ip->p3.value;
524 if (O->sampleAccurate && !tie &&
525 ip->p3.value > 0 &&
526 ip->xtratim == 0) /* ceil for sample-accurate ending */
527 ip->offtim = CEIL(ip->offtim*csound->ekr) / csound->ekr;
528 else /* normal : round */
529 ip->offtim = FLOOR(ip->offtim * csound->ekr +0.5)/csound->ekr;
530 if (O->Beatmode) {
531 p2 = ((p2*csound->esr - csound->icurTime) / csound->ibeatTime)
532 + csound->curBeat;
533 ip->offbet = p2 + ((double) ip->p3.value*csound->esr / csound->ibeatTime);
534 }
535 #ifdef BETA
536 if (UNLIKELY(O->odebug))
537 csound->Message(csound,
538 "Calling schedofftim line %d; offtime= %lf (%lf)\n",
539 __LINE__, ip->offtim, ip->offtim*csound->ekr);
540 #endif
541 if(csound->oparms->realtime) // compensate for possible late starts
542 {
543 double p2 = (double) ip->p2.value + csound->timeOffs;
544 ip->offtim += (csound->icurTime/csound->esr - p2);
545 }
546 //printf("%lf\n", );
547 schedofftim(csound, ip); /* put in turnoff list */
548 }
549 else {
550 ip->offbet = -1.0;
551 ip->offtim = -1.0; /* else mark indef */
552 }
553 if (UNLIKELY(O->odebug)) {
554 char *name = csound->engineState.instrtxtp[insno]->insname;
555 if (UNLIKELY(name))
556 csound->Message(csound, Str("instr %s now active:\n"), name);
557 else
558 csound->Message(csound, Str("instr %d now active:\n"), insno);
559 showallocs(csound);
560 }
561 if (newevtp->pinstance != NULL) {
562 *((MYFLT *)newevtp->pinstance) = (MYFLT) ((uintptr_t) ip);
563 }
564 return 0;
565 }
566
567
568 /* insert a MIDI instr copy into active list */
569 /* then run an init pass */
MIDIinsert(CSOUND * csound,int insno,MCHNBLK * chn,MEVENT * mep)570 int MIDIinsert(CSOUND *csound, int insno, MCHNBLK *chn, MEVENT *mep) {
571
572 if(csound->oparms->realtime) {
573 unsigned long wp = csound->alloc_queue_wp;
574 csound->alloc_queue[wp].insno = insno;
575 csound->alloc_queue[wp].chn = chn;
576 csound->alloc_queue[wp].mep = *mep;
577 csound->alloc_queue[wp].type = 1;
578 csound->alloc_queue_wp = wp + 1 < MAX_ALLOC_QUEUE ? wp + 1 : 0;
579 ATOMIC_INCR(csound->alloc_queue_items);
580 return 0;
581 }
582 else return insert_midi(csound, insno, chn, mep);
583
584 }
585
insert_midi(CSOUND * csound,int insno,MCHNBLK * chn,MEVENT * mep)586 int insert_midi(CSOUND *csound, int insno, MCHNBLK *chn, MEVENT *mep)
587 {
588 INSTRTXT *tp;
589 INSDS *ip, **ipp, *prvp, *nxtp;
590 OPARMS *O = csound->oparms;
591 CS_VAR_MEM *pfields;
592 EVTBLK *evt;
593 int pmax = 0, error = 0;
594
595 if (UNLIKELY(csound->advanceCnt))
596 return 0;
597 if (UNLIKELY(insno <= 0 || csound->engineState.instrtxtp[insno]->muted == 0))
598 return 0; /* muted */
599
600 tp = csound->engineState.instrtxtp[insno];
601 if (tp->cpuload > FL(0.0)) {
602 csound->cpu_power_busy += tp->cpuload;
603 if (UNLIKELY(csound->cpu_power_busy > FL(100.0))) {
604 /* if there is no more cpu time */
605 csound->cpu_power_busy -= tp->cpuload;
606 csoundWarning(csound, Str("cannot allocate last note because "
607 "it exceeds 100%% of cpu time"));
608 return(0);
609 }
610 }
611 if (UNLIKELY(tp->maxalloc > 0 && tp->active >= tp->maxalloc)) {
612 csoundWarning(csound, Str("cannot allocate last note because it exceeds "
613 "instr maxalloc"));
614 return(0);
615 }
616 tp->active++;
617 tp->instcnt++;
618 csound->dag_changed++; /* Need to remake DAG */
619 if (UNLIKELY(O->odebug)) {
620 char *name = csound->engineState.instrtxtp[insno]->insname;
621 if (UNLIKELY(name))
622 csound->Message(csound, Str("MIDI activating instr %s\n"), name);
623 else
624 csound->Message(csound, Str("MIDI activating instr %d\n"), insno);
625 }
626 csound->inerrcnt = 0;
627 ipp = &chn->kinsptr[mep->dat1]; /* key insptr ptr */
628 /* alloc new dspace if needed */
629 if (tp->act_instance == NULL || tp->isNew) {
630 if (UNLIKELY(O->msglevel & RNGEMSG)) {
631 char *name = csound->engineState.instrtxtp[insno]->insname;
632 if (UNLIKELY(name))
633 csound->Message(csound, Str("new MIDI alloc for instr %s:\n"), name);
634 else
635 csound->Message(csound, Str("new MIDI alloc for instr %d:\n"), insno);
636 }
637 instance(csound, insno);
638 tp->isNew = 0;
639 }
640 /* pop from free instance chain */
641 ip = tp->act_instance;
642 ATOMIC_SET(ip->init_done, 0);
643 tp->act_instance = ip->nxtact;
644 ip->insno = (int16) insno;
645
646 if (UNLIKELY(O->odebug))
647 csound->Message(csound, "Now %d active instr %d\n", tp->active, insno);
648 if (UNLIKELY((prvp = *ipp) != NULL)) { /* if key currently activ */
649 csoundWarning(csound,
650 Str("MIDI note overlaps with key %d on same channel"),
651 (int) mep->dat1);
652 while (prvp->nxtolap != NULL) /* append to overlap list */
653 prvp = prvp->nxtolap;
654 prvp->nxtolap = ip;
655 }
656 else
657 *ipp = ip;
658 /* of overlapping notes, the one that was turned on first will be */
659 /* turned off first as well */
660 ip->nxtolap = NULL;
661
662 nxtp = &(csound->actanchor); /* now splice into activ lst */
663 while ((prvp = nxtp) && (nxtp = prvp->nxtact) != NULL) {
664 if (nxtp->insno > insno) {
665 nxtp->prvact = ip;
666 break;
667 }
668 }
669 ip->nxtact = nxtp;
670 ip->prvact = prvp;
671 prvp->nxtact = ip;
672 ip->actflg++; /* and mark the instr active */
673 ip->m_chnbp = chn; /* rec address of chnl ctrl blk */
674 ip->m_pitch = (unsigned char) mep->dat1; /* rec MIDI data */
675 ip->m_veloc = (unsigned char) mep->dat2;
676 ip->xtratim = 0;
677 ip->m_sust = 0;
678 ip->relesing = 0;
679 ip->offbet = -1.0;
680 ip->offtim = -1.0; /* set indef duration */
681 ip->opcod_iobufs = NULL; /* IV - Sep 8 2002: */
682 ip->p1.value = (MYFLT) insno; /* set these required p-fields */
683 ip->p2.value = (MYFLT) (csound->icurTime/csound->esr - csound->timeOffs);
684 ip->p3.value = FL(-1.0);
685 ip->ksmps = csound->ksmps;
686 ip->ekr = csound->ekr;
687 ip->kcounter = csound->kcounter;
688 ip->onedksmps = csound->onedksmps;
689 ip->onedkr = csound->onedkr;
690 ip->kicvt = csound->kicvt;
691 ip->pds = NULL;
692 pfields = (CS_VAR_MEM*)&ip->p0;
693
694 if (tp->psetdata != NULL) {
695 int i;
696 MYFLT *pdat = tp->psetdata + 2;
697 int32 nn = tp->pmax - 2; /* put cur vals in pflds */
698
699 for (i = 0; i < nn; i++) {
700 CS_VAR_MEM* pfield = (pfields + i + 3);
701 pfield->value = *(pdat + i);
702 }
703 pmax = tp->pmax;
704 }
705
706
707 /* MIDI channel message note on routing overrides pset: */
708
709 if (O->midiKey) {
710 int pfield_index = O->midiKey;
711 CS_VAR_MEM* pfield = (pfields + pfield_index);
712 MYFLT value = (MYFLT) ip->m_pitch;
713 pfield->value = value;
714
715 if (UNLIKELY(O->msglevel & WARNMSG)) {
716 csound->Message(csound, " midiKey: pfield: %3d value: %3d\n",
717 pfield_index, (int) pfield->value);
718 }
719 if (pmax < pfield_index) pmax = pfield_index;
720 }
721 else if (O->midiKeyCps) {
722 int pfield_index = O->midiKeyCps;
723 CS_VAR_MEM* pfield = (pfields + pfield_index);
724 MYFLT value = (MYFLT) ip->m_pitch;
725 value = value / FL(12.0) + FL(3.0);
726 value = value * OCTRES;
727 value = (MYFLT) CPSOCTL((int32) value);
728 pfield->value = value;
729
730 if (UNLIKELY(O->msglevel & WARNMSG)) {
731 csound->Message(csound, " midiKeyCps: pfield: %3d value: %3d\n",
732 pfield_index, (int) pfield->value);
733 }
734 if (pmax < pfield_index) pmax = pfield_index;
735 }
736 else if (O->midiKeyOct) {
737 int pfield_index = O->midiKeyOct;
738 CS_VAR_MEM* pfield = (pfields + pfield_index);
739 MYFLT value = (MYFLT) ip->m_pitch;
740 value = value / FL(12.0) + FL(3.0);
741 pfield->value = value;
742 if (UNLIKELY(O->msglevel & WARNMSG)) {
743 csound->Message(csound, " midiKeyOct: pfield: %3d value: %3d\n",
744 pfield_index, (int) pfield->value);
745 }
746 if (pmax < pfield_index) pmax = pfield_index;
747 }
748 else if (O->midiKeyPch) {
749 int pfield_index = O->midiKeyPch;
750 CS_VAR_MEM* pfield = (pfields + pfield_index);
751 MYFLT value = (MYFLT) ip->m_pitch;
752 double octave = 0;
753 double fraction = 0.0;
754 value = value / FL(12.0) + FL(3.0);
755 fraction = modf(value, &octave);
756 fraction *= 0.12;
757 value = octave + fraction;
758 pfield->value = value;
759 if (UNLIKELY(O->msglevel & WARNMSG)) {
760 csound->Message(csound, " midiKeyPch: pfield: %3d value: %3d\n",
761 pfield_index, (int) pfield->value);
762 }
763 if (pmax < pfield_index) pmax = pfield_index;
764 }
765 if (O->midiVelocity) {
766 int pfield_index = O->midiVelocity;
767 CS_VAR_MEM* pfield = (pfields + pfield_index);
768 MYFLT value = (MYFLT) ip->m_veloc;
769 pfield->value = value;
770 if (UNLIKELY(O->msglevel & WARNMSG)) {
771 csound->Message(csound, " midiVelocity: pfield: %3d value: %3d\n",
772 pfield_index, (int) pfield->value);
773 }
774 if (pmax < pfield_index) pmax = pfield_index;
775 }
776 else if (O->midiVelocityAmp) {
777 int pfield_index = O->midiVelocityAmp;
778 CS_VAR_MEM* pfield = (pfields + pfield_index);
779 MYFLT value = (MYFLT) ip->m_veloc;
780 value = value * value / FL(16239.0);
781 value = value * csound->e0dbfs;
782 pfield->value = value;
783 if (UNLIKELY(O->msglevel & WARNMSG)) {
784 csound->Message(csound, " midiVelocityAmp: pfield: %3d value: %.3f\n",
785 pfield_index, pfield->value);
786 }
787 if (pmax < pfield_index) pmax = pfield_index;
788 }
789 if (pmax > 0) {
790 int i;
791 if (csound->currevent == NULL) {
792 evt = (EVTBLK *) csound->Calloc(csound, sizeof(EVTBLK));
793 csound->currevent = evt;
794 }
795 else evt = csound->currevent;
796 evt->pcnt = pmax+1;
797 for (i =0; i < evt->pcnt; i++) {
798 evt->p[i] = pfields[i].value;
799 }
800 }
801
802 csound->init_event = csound->currevent;
803 error = init_pass(csound, ip);
804 if(error == 0)
805 ATOMIC_SET(ip->init_done, 1);
806
807 if (UNLIKELY(csound->inerrcnt)) {
808 xturnoff_now(csound, ip);
809 return csound->inerrcnt;
810 }
811 ip->tieflag = ip->reinitflag = 0;
812 csound->tieflag = csound->reinitflag = 0;
813
814 if (UNLIKELY(O->odebug)) {
815 char *name = csound->engineState.instrtxtp[insno]->insname;
816 if (UNLIKELY(name))
817 csound->Message(csound, Str("instr %s now active:\n"), name);
818 else
819 csound->Message(csound, Str("instr %d now active:\n"), insno);
820 showallocs(csound);
821 }
822 return 0;
823 }
824
showallocs(CSOUND * csound)825 static void showallocs(CSOUND *csound) /* debugging aid */
826 {
827 INSTRTXT *txtp;
828 INSDS *p;
829
830 csound->Message(csound, "insno\tinstanc\tnxtinst\tprvinst\tnxtact\t"
831 "prvact\tnxtoff\tactflg\tofftim\n");
832 for (txtp = &(csound->engineState.instxtanchor);
833 txtp != NULL;
834 txtp = txtp->nxtinstxt)
835
836 if ((p = txtp->instance) != NULL) {
837 /*
838 * On Alpha, we print pointers as pointers. heh 981101
839 * and now on all platforms (JPff)
840 */
841 do {
842 csound->Message(csound, "%d\t%p\t%p\t%p\t%p\t%p\t%p\t%d\t%3.1f\n",
843 (int) p->insno, (void*) p,
844 (void*) p->nxtinstance, (void*) p->prvinstance,
845 (void*) p->nxtact, (void*) p->prvact,
846 (void*) p->nxtoff, p->actflg, p->offtim);
847 } while ((p = p->nxtinstance) != NULL);
848 }
849 }
850
schedofftim(CSOUND * csound,INSDS * ip)851 static void schedofftim(CSOUND *csound, INSDS *ip)
852 { /* put an active instr into offtime list */
853 INSDS *prvp, *nxtp; /* called by insert() & midioff + xtratim */
854
855 if ((nxtp = csound->frstoff) == NULL ||
856 nxtp->offtim > ip->offtim) { /* set into */
857 csound->frstoff = ip; /* firstoff chain */
858 ip->nxtoff = nxtp;
859 /* IV - Feb 24 2006: check if this note already needs to be turned off */
860 /* the following comparisons must match those in sensevents() */
861 #ifdef BETA
862 if (UNLIKELY(csound->oparms->odebug))
863 csound->Message(csound,"schedofftim: %lf %lf %f\n",
864 ip->offtim, csound->icurTime/csound->esr,
865 csound->curTime_inc);
866
867 #endif
868 if (csound->oparms_.Beatmode) {
869 double tval = csound->curBeat + (0.505 * csound->curBeat_inc);
870 if (ip->offbet <= tval) beatexpire(csound, tval);
871 }
872 else {
873 double tval = (csound->icurTime + (0.505 * csound->ksmps))/csound->esr;
874 if (ip->offtim <= tval) timexpire(csound, tval);
875 }
876 #ifdef BETA
877 if (UNLIKELY(csound->oparms->odebug))
878 csound->Message(csound,"schedofftim: %lf %lf %lf\n", ip->offtim,
879 (csound->icurTime + (0.505 * csound->ksmps))/csound->esr,
880 csound->ekr*((csound->icurTime +
881 (0.505 * csound->ksmps))/csound->esr));
882 #endif
883 }
884 else {
885 while ((prvp = nxtp)
886 && (nxtp = nxtp->nxtoff) != NULL
887 && ip->offtim >= nxtp->offtim);
888 prvp->nxtoff = ip;
889 ip->nxtoff = nxtp;
890 }
891 }
892
893 /* csound.c */
894 extern int csoundDeinitialiseOpcodes(CSOUND *csound, INSDS *ip);
895 int useropcd(CSOUND *, UOPCODE*);
896
deact(CSOUND * csound,INSDS * ip)897 static void deact(CSOUND *csound, INSDS *ip)
898 { /* unlink single instr from activ chain */
899 INSDS *nxtp; /* and mark it inactive */
900 /* close any files in fd chain */
901
902 if (ip->nxtd != NULL)
903 csoundDeinitialiseOpcodes(csound, ip);
904 /* remove an active instrument */
905 csound->engineState.instrtxtp[ip->insno]->active--;
906 if (ip->xtratim > 0)
907 csound->engineState.instrtxtp[ip->insno]->pending_release--;
908 csound->cpu_power_busy -= csound->engineState.instrtxtp[ip->insno]->cpuload;
909 /* IV - Sep 8 2002: free subinstr instances */
910 /* that would otherwise result in a memory leak */
911 if (ip->opcod_deact) {
912 UOPCODE *p = (UOPCODE*) ip->opcod_deact; /* IV - Oct 26 2002 */
913 deact(csound, p->ip); /* deactivate */
914 p->ip = NULL;
915 /* IV - Oct 26 2002: set perf routine to "not initialised" */
916 p->h.opadr = (SUBR) useropcd;
917 ip->opcod_deact = NULL;
918 }
919 if (ip->subins_deact) {
920 deact(csound, ((SUBINST*) ip->subins_deact)->ip); /* IV - Oct 24 2002 */
921 ((SUBINST*) ip->subins_deact)->ip = NULL;
922 ip->subins_deact = NULL;
923 }
924 if (UNLIKELY(csound->oparms->odebug)) {
925 char *name = csound->engineState.instrtxtp[ip->insno]->insname;
926 if (UNLIKELY(name))
927 csound->Message(csound, Str("removed instance of instr %s\n"), name);
928 else
929 csound->Message(csound, Str("removed instance of instr %d\n"), ip->insno);
930 }
931 /* IV - Oct 24 2002: ip->prvact may be NULL, so need to check */
932 if (ip->prvact && (nxtp = ip->prvact->nxtact = ip->nxtact) != NULL)
933 nxtp->prvact = ip->prvact;
934 ip->actflg = 0;
935 /* link into free instance chain */
936 /* This also destroys ip->nxtact causing loops */
937 if (csound->engineState.instrtxtp[ip->insno] == ip->instr){
938 ip->nxtact = csound->engineState.instrtxtp[ip->insno]->act_instance;
939 csound->engineState.instrtxtp[ip->insno]->act_instance = ip;
940 }
941 if (ip->fdchp != NULL)
942 fdchclose(csound, ip);
943 csound->dag_changed++;
944 }
945
946
kill_instance(CSOUND * csound,KILLOP * p)947 int kill_instance(CSOUND *csound, KILLOP *p) {
948 if (LIKELY(*p->inst)) xturnoff(csound, (INSDS *) ((uintptr_t)*p->inst));
949 else csound->Warning(csound, Str("instance not valid\n"));
950 return OK;
951 }
952
953 /* Turn off a particular insalloc, also remove from list of active */
954 /* MIDI notes. Allows for releasing if ip->xtratim > 0. */
955
xturnoff(CSOUND * csound,INSDS * ip)956 void xturnoff(CSOUND *csound, INSDS *ip) /* turnoff a particular insalloc */
957 { /* called by inexclus on ctrl 111 */
958 MCHNBLK *chn;
959
960 if (UNLIKELY(ip->relesing))
961 return; /* already releasing: nothing to do */
962
963 chn = ip->m_chnbp;
964 if (chn != NULL) { /* if this was a MIDI note */
965 INSDS *prvip;
966 prvip = chn->kinsptr[ip->m_pitch]; /* remov from activ lst */
967 if (ip->m_sust && chn->ksuscnt)
968 chn->ksuscnt--;
969 ip->m_sust = 0; /* force turnoff even if sustaining */
970 if (prvip != NULL) {
971 if (prvip == ip)
972 chn->kinsptr[ip->m_pitch] = ip->nxtolap;
973 else {
974 while (prvip != NULL && prvip->nxtolap != ip)
975 prvip = prvip->nxtolap;
976 if (prvip != NULL)
977 prvip->nxtolap = ip->nxtolap;
978 }
979 }
980 }
981 /* remove from schedoff chain first if finite duration */
982 if (csound->frstoff != NULL && ip->offtim >= 0.0) {
983 INSDS *prvip;
984 prvip = csound->frstoff;
985 if (prvip == ip)
986 csound->frstoff = ip->nxtoff;
987 else {
988 while (prvip != NULL && prvip->nxtoff != ip)
989 prvip = prvip->nxtoff;
990 if (prvip != NULL)
991 prvip->nxtoff = ip->nxtoff;
992 }
993 }
994 /* if extra time needed: schedoff at new time */
995 if (ip->xtratim > 0) {
996 set_xtratim(csound, ip);
997 #ifdef BETA
998 if (UNLIKELY(csound->oparms->odebug))
999 csound->Message(csound, "Calling schedofftim line %d\n", __LINE__);
1000 #endif
1001 schedofftim(csound, ip);
1002 }
1003 else {
1004 /* no extra time needed: deactivate immediately */
1005 deact(csound, ip);
1006 csound->dag_changed++; /* Need to remake DAG */
1007 }
1008 }
1009
1010 /* Turn off instrument instance immediately, without releasing. */
1011 /* Removes alloc from list of active MIDI notes. */
xturnoff_now(CSOUND * csound,INSDS * ip)1012 void xturnoff_now(CSOUND *csound, INSDS *ip)
1013 {
1014 ip->xtratim = 0;
1015 ip->relesing = 0;
1016 xturnoff(csound, ip);
1017 }
1018
1019 extern void free_instrtxt(CSOUND *csound, INSTRTXT *instrtxt);
1020
1021
free_instr_var_memory(CSOUND * csound,INSDS * ip)1022 void free_instr_var_memory(CSOUND* csound, INSDS* ip) {
1023 INSTRTXT* instrDef = ip->instr;
1024 CS_VAR_POOL* pool = instrDef->varPool;
1025 CS_VARIABLE* current = pool->head;
1026
1027 while (current != NULL) {
1028 CS_TYPE* varType = current->varType;
1029 if (varType->freeVariableMemory != NULL) {
1030 varType->freeVariableMemory(csound,
1031 ip->lclbas + current->memBlockIndex);
1032 }
1033 current = current->next;
1034 }
1035 }
1036
orcompact(CSOUND * csound)1037 void orcompact(CSOUND *csound) /* free all inactive instr spaces */
1038 {
1039 INSTRTXT *txtp;
1040 INSDS *ip, *nxtip, *prvip, **prvnxtloc;
1041 int cnt = 0;
1042 for (txtp = &(csound->engineState.instxtanchor);
1043 txtp != NULL; txtp = txtp->nxtinstxt) {
1044 if ((ip = txtp->instance) != NULL) { /* if instance exists */
1045
1046 prvip = NULL;
1047 prvnxtloc = &txtp->instance;
1048 do {
1049 if (!ip->actflg) {
1050 cnt++;
1051 if (ip->opcod_iobufs && ip->insno > csound->engineState.maxinsno)
1052 csound->Free(csound, ip->opcod_iobufs); /* IV - Nov 10 2002 */
1053 if (ip->fdchp != NULL)
1054 fdchclose(csound, ip);
1055 if (ip->auxchp != NULL)
1056 auxchfree(csound, ip);
1057 free_instr_var_memory(csound, ip);
1058 if ((nxtip = ip->nxtinstance) != NULL)
1059 nxtip->prvinstance = prvip;
1060 *prvnxtloc = nxtip;
1061 csound->Free(csound, (char *)ip);
1062 }
1063 else {
1064 prvip = ip;
1065 prvnxtloc = &ip->nxtinstance;
1066 }
1067 }
1068 while ((ip = *prvnxtloc) != NULL);
1069 }
1070
1071 /* IV - Oct 31 2002 */
1072 if (!txtp->instance)
1073 txtp->lst_instance = NULL; /* find last alloc */
1074 else {
1075 ip = txtp->instance;
1076 while (ip->nxtinstance) ip = ip->nxtinstance;
1077 txtp->lst_instance = ip;
1078 }
1079
1080 txtp->act_instance = NULL; /* no free instances */
1081 }
1082 /* check current items in deadpool to see if they need deleting */
1083 {
1084 int i;
1085 for (i=0; i < csound->dead_instr_no; i++) {
1086 if (csound->dead_instr_pool[i] != NULL) {
1087 INSDS *active = csound->dead_instr_pool[i]->instance;
1088 while (active != NULL) {
1089 if (active->actflg) {
1090 // add_to_deadpool(csound,csound->dead_instr_pool[i]);
1091 break;
1092 }
1093 active = active->nxtinstance;
1094 }
1095 /* no active instances */
1096 if (active == NULL) {
1097 free_instrtxt(csound, csound->dead_instr_pool[i]);
1098 csound->dead_instr_pool[i] = NULL;
1099 }
1100 }
1101 }
1102 }
1103 if (UNLIKELY(cnt))
1104 csound->Message(csound, Str("inactive allocs returned to freespace\n"));
1105 }
1106
infoff(CSOUND * csound,MYFLT p1)1107 void infoff(CSOUND *csound, MYFLT p1) /* turn off an indef copy of instr p1 */
1108 { /* called by musmon */
1109 INSDS *ip;
1110 int insno;
1111
1112 insno = (int) p1;
1113 if (LIKELY((ip = (csound->engineState.instrtxtp[insno])->instance) != NULL)) {
1114 do {
1115 if (ip->insno == insno /* if find the insno */
1116 && ip->actflg /* active */
1117 && ip->offtim < 0.0 /* but indef, VL: currently this condition
1118 cannot be removed, as it breaks turning
1119 off extratime instances */
1120 && ip->p1.value == p1) {
1121 if (UNLIKELY(csound->oparms->odebug))
1122 csound->Message(csound, "turning off inf copy of instr %d\n",
1123 insno);
1124 xturnoff(csound, ip);
1125 return; /* turn it off */
1126 }
1127 } while ((ip = ip->nxtinstance) != NULL);
1128 }
1129 csound->Message(csound,
1130 Str("could not find playing instr %f\n"),
1131 p1);
1132 }
1133
1134 void do_baktrace(CSOUND *, uint64_t);
1135
csoundInitError(CSOUND * csound,const char * s,...)1136 int csoundInitError(CSOUND *csound, const char *s, ...)
1137 {
1138 va_list args;
1139 INSDS *ip;
1140 char buf[512];
1141
1142 /* RWD: need this! */
1143 if (UNLIKELY(csound->ids == NULL)) {
1144 va_start(args, s);
1145 csoundErrMsgV(csound, Str("\nINIT ERROR: "), s, args);
1146 va_end(args);
1147 csound->LongJmp(csound, 1);
1148 }
1149 if (csound->mode != 1)
1150 csound->Message(csound, Str("InitError in wrong mode %d\n"), csound->mode);
1151 /* IV - Oct 16 2002: check for subinstr and user opcode */
1152 ip = csound->ids->insdshead;
1153 if (ip->opcod_iobufs) {
1154 OPCODINFO *op = ((OPCOD_IOBUFS*) ip->opcod_iobufs)->opcode_info;
1155 /* find top level instrument instance */
1156 do {
1157 ip = ((OPCOD_IOBUFS*) ip->opcod_iobufs)->parent_ip;
1158 } while (ip->opcod_iobufs);
1159 if (op)
1160 snprintf(buf, 512, Str("INIT ERROR in instr %d (opcode %s) line %d: "),
1161 ip->insno, op->name, csound->ids->optext->t.linenum);
1162 else
1163 snprintf(buf, 512, Str("INIT ERROR in instr %d (subinstr %d) line %d: "),
1164 ip->insno, csound->ids->insdshead->insno,
1165 csound->ids->optext->t.linenum);
1166 }
1167 else
1168 snprintf(buf, 512, Str("INIT ERROR in instr %d (opcode %s) line %d: "),
1169 ip->insno, csound->op, csound->ids->optext->t.linenum);
1170 va_start(args, s);
1171 csoundErrMsgV(csound, buf, s, args);
1172 va_end(args);
1173 do_baktrace(csound, csound->ids->optext->t.locn);
1174 putop(csound, &(csound->ids->optext->t));
1175 return ++(csound->inerrcnt);
1176 }
1177
csoundPerfError(CSOUND * csound,OPDS * h,const char * s,...)1178 int csoundPerfError(CSOUND *csound, OPDS *h, const char *s, ...)
1179 {
1180 va_list args;
1181 char buf[512];
1182 INSDS *ip = h->insdshead;
1183 TEXT t = h->optext->t;
1184 if (csound->mode != 2)
1185 csound->Message(csound, Str("PerfError in wrong mode %d\n"), csound->mode);
1186 if (ip->opcod_iobufs) {
1187 OPCODINFO *op = ((OPCOD_IOBUFS*) ip->opcod_iobufs)->opcode_info;
1188 /* find top level instrument instance */
1189 do {
1190 ip = ((OPCOD_IOBUFS*) ip->opcod_iobufs)->parent_ip;
1191 } while (ip->opcod_iobufs);
1192 if (op)
1193 snprintf(buf, 512, Str("PERF ERROR in instr %d (opcode %s) line %d: "),
1194 ip->insno, op->name, t.linenum);
1195 else
1196 snprintf(buf, 512, Str("PERF ERROR in instr %d (subinstr %d) line %d: "),
1197 ip->insno, ip->insno, t.linenum);
1198 }
1199 else
1200 snprintf(buf, 512, Str("PERF ERROR in instr %d (opcode %s) line %d: "),
1201 ip->insno, csound->op, t.linenum);
1202 va_start(args, s);
1203 csoundErrMsgV(csound, buf, s, args);
1204 va_end(args);
1205 do_baktrace(csound, t.locn);
1206 if (ip->pds)
1207 putop(csound, &(ip->pds->optext->t));
1208 csoundMessage(csound, Str(" note aborted\n"));
1209 csound->perferrcnt++;
1210 xturnoff_now((CSOUND*) csound, ip); /* rm ins fr actlist */
1211 return csound->perferrcnt; /* contin from there */
1212 }
1213
subinstrset_(CSOUND * csound,SUBINST * p,int instno)1214 int subinstrset_(CSOUND *csound, SUBINST *p, int instno)
1215 {
1216 OPDS *saved_ids = csound->ids;
1217 INSDS *saved_curip = csound->curip;
1218 CS_VAR_MEM *pfield;
1219 int n, init_op, inarg_ofs;
1220 INSDS *pip = p->h.insdshead;
1221
1222 init_op = (p->h.opadr == NULL ? 1 : 0);
1223 inarg_ofs = (init_op ? 0 : SUBINSTNUMOUTS);
1224 if (UNLIKELY(instno < 0)) return NOTOK;
1225 /* IV - Oct 9 2002: need this check */
1226 if (UNLIKELY(!init_op && p->OUTOCOUNT > csound->nchnls)) {
1227 return csoundInitError(csound, Str("subinstr: number of output "
1228 "args greater than nchnls"));
1229 }
1230 /* IV - Oct 9 2002: copied this code from useropcdset() to fix some bugs */
1231 if (!(pip->reinitflag | pip->tieflag) || p->ip == NULL) {
1232 /* get instance */
1233 if (csound->engineState.instrtxtp[instno]->act_instance == NULL)
1234 instance(csound, instno);
1235 p->ip = csound->engineState.instrtxtp[instno]->act_instance;
1236 csound->engineState.instrtxtp[instno]->act_instance = p->ip->nxtact;
1237 p->ip->insno = (int16) instno;
1238 p->ip->actflg++; /* and mark the instr active */
1239 csound->engineState.instrtxtp[instno]->active++;
1240 csound->engineState.instrtxtp[instno]->instcnt++;
1241 p->ip->p1.value = (MYFLT) instno;
1242 /* VL 21-10-16: iobufs are not used here and
1243 are causing trouble elsewhere. Commenting
1244 it out */
1245 /* p->ip->opcod_iobufs = (void*) &p->buf; */
1246 /* link into deact chain */
1247 p->ip->subins_deact = saved_curip->subins_deact;
1248 p->ip->opcod_deact = NULL;
1249 saved_curip->subins_deact = (void*) p;
1250 p->parent_ip = p->buf.parent_ip = saved_curip;
1251 }
1252
1253 p->ip->ksmps = CS_KSMPS;
1254 p->ip->kcounter = CS_KCNT;
1255 p->ip->ekr = CS_EKR;
1256 p->ip->onedkr = CS_ONEDKR;
1257 p->ip->onedksmps = CS_ONEDKSMPS;
1258 p->ip->kicvt = CS_KICVT;
1259
1260 /* copy parameters from this instrument into our subinstrument */
1261 p->ip->xtratim = saved_curip->xtratim;
1262 p->ip->m_sust = 0;
1263 p->ip->relesing = saved_curip->relesing;
1264 p->ip->offbet = saved_curip->offbet;
1265 p->ip->offtim = saved_curip->offtim;
1266 p->ip->nxtolap = NULL;
1267 p->ip->p2 = saved_curip->p2;
1268 p->ip->p3 = saved_curip->p3;
1269 p->ip->ksmps = CS_KSMPS;
1270
1271 /* IV - Oct 31 2002 */
1272 p->ip->m_chnbp = saved_curip->m_chnbp;
1273 p->ip->m_pitch = saved_curip->m_pitch;
1274 p->ip->m_veloc = saved_curip->m_veloc;
1275
1276 p->ip->ksmps_offset = saved_curip->ksmps_offset;
1277 p->ip->ksmps_no_end = saved_curip->ksmps_no_end;
1278 p->ip->tieflag = saved_curip->tieflag;
1279 p->ip->reinitflag = saved_curip->reinitflag;
1280
1281 /* copy remainder of pfields */
1282 pfield = (CS_VAR_MEM*)&p->ip->p3;
1283 /* by default all inputs are i-rate mapped to p-fields */
1284 if (UNLIKELY(p->INOCOUNT >
1285 (unsigned int)(csound->engineState.instrtxtp[instno]->pmax + 1)))
1286 return csoundInitError(csound, Str("subinstr: too many p-fields"));
1287 union {
1288 MYFLT d;
1289 int32 i;
1290 } ch;
1291 int str_cnt = 0, len = 0;
1292 char *argstr;
1293 for (n = 1; (unsigned int) n < p->INOCOUNT; n++){
1294 if (IS_STR_ARG(p->ar[inarg_ofs + n])) {
1295 ch.d = SSTRCOD;
1296 ch.i = str_cnt & 0xffff;
1297 (pfield + n)->value = ch.d;
1298 argstr = ((STRINGDAT *)p->ar[inarg_ofs + n])->data;
1299 if (str_cnt == 0)
1300 p->ip->strarg = csound->Calloc(csound, strlen(argstr)+1);
1301 else
1302 p->ip->strarg = csound->ReAlloc(csound, p->ip->strarg,
1303 len+strlen(argstr)+1);
1304 strcpy(p->ip->strarg + len, argstr);
1305 len += strlen(argstr)+1;
1306 str_cnt++;
1307 }
1308 else (pfield + n)->value = *p->ar[inarg_ofs + n];
1309 }
1310 /* allocate memory for a temporary store of spout buffers */
1311 if (!init_op && !(pip->reinitflag | pip->tieflag))
1312 csoundAuxAlloc(csound,
1313 (int32) csound->nspout * sizeof(MYFLT), &p->saved_spout);
1314
1315 /* do init pass for this instr */
1316 csound->curip = p->ip; /* **** NEW *** */
1317 p->ip->init_done = 0;
1318 csound->ids = (OPDS *)p->ip;
1319 csound->mode = 1;
1320 while ((csound->ids = csound->ids->nxti) != NULL) {
1321 csound->op = csound->ids->optext->t.oentry->opname;
1322 (*csound->ids->iopadr)(csound, csound->ids);
1323 }
1324 csound->mode = 0;
1325 p->ip->init_done = 1;
1326 /* copy length related parameters back to caller instr */
1327 saved_curip->xtratim = csound->curip->xtratim;
1328 saved_curip->relesing = csound->curip->relesing;
1329 saved_curip->offbet = csound->curip->offbet;
1330 saved_curip->offtim = csound->curip->offtim;
1331 saved_curip->p3 = csound->curip->p3;
1332
1333 /* restore globals */
1334 csound->ids = saved_ids;
1335 csound->curip = saved_curip;
1336 return OK;
1337 }
1338
subinstrset_S(CSOUND * csound,SUBINST * p)1339 int subinstrset_S(CSOUND *csound, SUBINST *p){
1340 int instno, init_op, inarg_ofs;
1341 /* check if we are using subinstrinit or subinstr */
1342 init_op = (p->h.opadr == NULL ? 1 : 0);
1343 inarg_ofs = (init_op ? 0 : SUBINSTNUMOUTS);
1344 instno = strarg2insno(csound, ((STRINGDAT *)p->ar[inarg_ofs])->data, 1);
1345 if (UNLIKELY(instno==NOT_AN_INSTRUMENT)) instno = -1;
1346 return subinstrset_(csound,p,instno);
1347 }
1348
1349
subinstrset(CSOUND * csound,SUBINST * p)1350 int subinstrset(CSOUND *csound, SUBINST *p){
1351 int instno, init_op, inarg_ofs;
1352 /* check if we are using subinstrinit or subinstr */
1353 init_op = (p->h.opadr == NULL ? 1 : 0);
1354 inarg_ofs = (init_op ? 0 : SUBINSTNUMOUTS);
1355 instno = (int) *(p->ar[inarg_ofs]);
1356 return subinstrset_(csound,p,instno);
1357 }
1358
1359 /* IV - Sep 8 2002: new functions for user defined opcodes (based */
1360 /* on Matt J. Ingalls' subinstruments, but mostly rewritten) */
1361
1362 /*
1363 UDOs now use the local ksmps stored in lcurip->ksmps
1364 all the other dependent parameters are calculated in relation to
1365 this.
1366
1367 lcurip->ksmps is set to the caller ksmps (CS_KSMPS), unless a new
1368 local ksmps is used, in which case it is set to that value.
1369 If local ksmps differs from CS_KSMPS, we set useropcd1() to
1370 deal with the perf-time code. Otherwise useropcd2() is used.
1371
1372 For recursive calls when the local ksmps is set to differ from
1373 the calling instrument ksmps, the top-level call
1374 will use useropcd1(), whereas all the other recursive calls
1375 will use useropdc2(), since their local ksmps will be the same
1376 as the caller.
1377
1378 Also in case of a local ksmps that differs from the caller,
1379 the local kcounter value, obtained from the caller is
1380 scaled to denote the correct kcount in terms of local
1381 kcycles.
1382
1383 */
1384 int useropcd1(CSOUND *, UOPCODE*), useropcd2(CSOUND *, UOPCODE*);
1385
useropcdset(CSOUND * csound,UOPCODE * p)1386 int useropcdset(CSOUND *csound, UOPCODE *p)
1387 {
1388 OPDS *saved_ids = csound->ids;
1389 INSDS *parent_ip = csound->curip, *lcurip;
1390 INSTRTXT *tp;
1391 unsigned int instno;
1392 unsigned int pcnt;
1393 unsigned int i, n;
1394 OPCODINFO *inm;
1395 OPCOD_IOBUFS *buf = NULL;
1396 MYFLT ksmps_scale;
1397 unsigned int local_ksmps;
1398 /* default ksmps */
1399 local_ksmps = CS_KSMPS;
1400 ksmps_scale = 1;
1401 /* look up the 'fake' instr number, and opcode name */
1402 inm = (OPCODINFO*) p->h.optext->t.oentry->useropinfo;
1403 instno = inm->instno;
1404 tp = csound->engineState.instrtxtp[instno];
1405 if (tp == NULL)
1406 return csound->InitError(csound, Str("Cannot find instr %d (UDO %s)\n"),
1407 instno, inm->name);
1408 /* set local ksmps if defined by user */
1409 n = p->OUTOCOUNT + p->INCOUNT - 1;
1410
1411 if (*(p->ar[n]) != FL(0.0)) {
1412 i = (unsigned int) *(p->ar[n]);
1413 if (UNLIKELY(i < 1 || i > csound->ksmps ||
1414 ((CS_KSMPS / i) * i) != CS_KSMPS)) {
1415 return csoundInitError(csound, Str("%s: invalid local ksmps value: %d"),
1416 inm->name, i);
1417 }
1418 local_ksmps = i;
1419 }
1420
1421 if (!p->ip) {
1422
1423 /* search for already allocated, but not active instance */
1424 /* if none was found, allocate a new instance */
1425 tp = csound->engineState.instrtxtp[instno];
1426 if (tp == NULL) {
1427 return csound->InitError(csound, Str("Cannot find instr %d (UDO %s)\n"),
1428 instno, inm->name);
1429 }
1430 if (!tp->act_instance)
1431 instance(csound, instno);
1432 lcurip = tp->act_instance; /* use free instance, and */
1433 tp->act_instance = lcurip->nxtact; /* remove from chain */
1434 if (lcurip->opcod_iobufs==NULL)
1435 return csound->InitError(csound, "Broken redefinition of UDO %d (UDO %s)\n",
1436 instno, inm->name);
1437 lcurip->actflg++; /* and mark the instr active */
1438 tp->active++;
1439 tp->instcnt++;
1440 /* link into deact chain */
1441 lcurip->opcod_deact = parent_ip->opcod_deact;
1442 lcurip->subins_deact = NULL;
1443 parent_ip->opcod_deact = (void*) p;
1444 p->ip = lcurip;
1445 /* IV - Nov 10 2002: set up pointers to I/O buffers */
1446 buf = p->buf = (OPCOD_IOBUFS*) lcurip->opcod_iobufs;
1447 buf->opcode_info = inm;
1448 /* initialise perf time address lists */
1449 /* **** Could be a memset **** */
1450 buf->iobufp_ptrs[0] = buf->iobufp_ptrs[1] = NULL;
1451 buf->iobufp_ptrs[2] = buf->iobufp_ptrs[3] = NULL;
1452 buf->iobufp_ptrs[4] = buf->iobufp_ptrs[5] = NULL;
1453 buf->iobufp_ptrs[6] = buf->iobufp_ptrs[7] = NULL;
1454 buf->iobufp_ptrs[8] = buf->iobufp_ptrs[9] = NULL;
1455 buf->iobufp_ptrs[10] = buf->iobufp_ptrs[11] = NULL;
1456 /* store parameters of input and output channels, and parent ip */
1457 buf->uopcode_struct = (void*) p;
1458 buf->parent_ip = p->parent_ip = parent_ip;
1459 }
1460
1461 /* copy parameters from the caller instrument into our subinstrument */
1462 lcurip = p->ip;
1463
1464 /* set the local ksmps values */
1465 if (local_ksmps != CS_KSMPS) {
1466 /* this is the case when p->ip->ksmps != p->h.insdshead->ksmps */
1467 lcurip->ksmps = local_ksmps;
1468 ksmps_scale = CS_KSMPS / local_ksmps;
1469 lcurip->onedksmps = FL(1.0) / (MYFLT) local_ksmps;
1470 lcurip->ekr = csound->esr / (MYFLT) local_ksmps;
1471 lcurip->onedkr = FL(1.0) / lcurip->ekr;
1472 lcurip->kicvt = (MYFLT) FMAXLEN /lcurip->ekr;
1473 lcurip->kcounter *= ksmps_scale;
1474 } else {
1475 lcurip->ksmps = CS_KSMPS;
1476 lcurip->kcounter = CS_KCNT;
1477 lcurip->ekr = CS_EKR;
1478 lcurip->onedkr = CS_ONEDKR;
1479 lcurip->onedksmps = CS_ONEDKSMPS;
1480 lcurip->kicvt = CS_KICVT;
1481 }
1482
1483 /* VL 13-12-13 */
1484 /* this sets ksmps and kr local variables */
1485 /* create local ksmps variable and init with ksmps */
1486 if (lcurip->lclbas != NULL) {
1487 CS_VARIABLE *var =
1488 csoundFindVariableWithName(csound, lcurip->instr->varPool, "ksmps");
1489 *((MYFLT *)(var->memBlockIndex + lcurip->lclbas)) = lcurip->ksmps;
1490 /* same for kr */
1491 var =
1492 csoundFindVariableWithName(csound, lcurip->instr->varPool, "kr");
1493 *((MYFLT *)(var->memBlockIndex + lcurip->lclbas)) = lcurip->ekr;
1494 }
1495
1496 lcurip->m_chnbp = parent_ip->m_chnbp; /* MIDI parameters */
1497 lcurip->m_pitch = parent_ip->m_pitch;
1498 lcurip->m_veloc = parent_ip->m_veloc;
1499 lcurip->xtratim = parent_ip->xtratim * ksmps_scale;
1500 lcurip->m_sust = 0;
1501 lcurip->relesing = parent_ip->relesing;
1502 lcurip->offbet = parent_ip->offbet;
1503 lcurip->offtim = parent_ip->offtim;
1504 lcurip->nxtolap = NULL;
1505 lcurip->ksmps_offset = parent_ip->ksmps_offset;
1506 lcurip->ksmps_no_end = parent_ip->ksmps_no_end;
1507 lcurip->tieflag = parent_ip->tieflag;
1508 lcurip->reinitflag = parent_ip->reinitflag;
1509 /* copy all p-fields, including p1 (will this work ?) */
1510 if (tp->pmax > 3) { /* requested number of p-fields */
1511 n = tp->pmax; pcnt = 0;
1512 while (pcnt < n) {
1513 if ((i = csound->engineState.instrtxtp[parent_ip->insno]->pmax) > pcnt) {
1514 if (i > n) i = n;
1515 /* copy next block of p-fields */
1516 memcpy(&(lcurip->p1) + pcnt, &(parent_ip->p1) + pcnt,
1517 (size_t) ((i - pcnt) * sizeof(CS_VAR_MEM)));
1518 pcnt = i;
1519 }
1520 /* top level instr reached */
1521 if (parent_ip->opcod_iobufs == NULL) break;
1522 parent_ip = ((OPCOD_IOBUFS*) parent_ip->opcod_iobufs)->parent_ip;
1523 }
1524 }
1525 else
1526 memcpy(&(lcurip->p1), &(parent_ip->p1), 3 * sizeof(CS_VAR_MEM));
1527
1528
1529 /* do init pass for this instr */
1530 csound->curip = lcurip;
1531 csound->ids = (OPDS *) (lcurip->nxti);
1532 ATOMIC_SET(p->ip->init_done, 0);
1533 csound->mode = 1;
1534 while (csound->ids != NULL) {
1535 csound->op = csound->ids->optext->t.oentry->opname;
1536 (*csound->ids->iopadr)(csound, csound->ids);
1537 csound->ids = csound->ids->nxti;
1538 }
1539 csound->mode = 0;
1540 ATOMIC_SET(p->ip->init_done, 1);
1541 /* copy length related parameters back to caller instr */
1542 parent_ip->relesing = lcurip->relesing;
1543 parent_ip->offbet = lcurip->offbet;
1544 parent_ip->offtim = lcurip->offtim;
1545 parent_ip->p3 = lcurip->p3;
1546 local_ksmps = lcurip->ksmps;
1547
1548 /* restore globals */
1549 csound->ids = saved_ids;
1550 csound->curip = parent_ip;
1551
1552 /* select perf routine and scale xtratim accordingly */
1553 if (local_ksmps != CS_KSMPS) {
1554 ksmps_scale = CS_KSMPS / local_ksmps;
1555 parent_ip->xtratim = lcurip->xtratim / ksmps_scale;
1556 p->h.opadr = (SUBR) useropcd1;
1557 }
1558 else {
1559 parent_ip->xtratim = lcurip->xtratim;
1560 p->h.opadr = (SUBR) useropcd2;
1561 }
1562 if (UNLIKELY(csound->oparms->odebug))
1563 csound->Message(csound, "EXTRATIM=> cur(%p): %d, parent(%p): %d\n",
1564 lcurip, lcurip->xtratim, parent_ip, parent_ip->xtratim);
1565 return OK;
1566 }
1567
1568 /* IV - Sep 17 2002: dummy user opcode function for not initialised case */
1569
useropcd(CSOUND * csound,UOPCODE * p)1570 int useropcd(CSOUND *csound, UOPCODE *p)
1571 {
1572
1573 if (UNLIKELY(p->h.nxtp))
1574 return csoundPerfError(csound, &(p->h), Str("%s: not initialised"),
1575 p->h.optext->t.opcod);
1576 else
1577 return OK;
1578 }
1579
1580 /* IV - Sep 1 2002: new opcodes: xin, xout */
1581
xinset(CSOUND * csound,XIN * p)1582 int xinset(CSOUND *csound, XIN *p)
1583 {
1584 OPCOD_IOBUFS *buf;
1585 OPCODINFO *inm;
1586 MYFLT **bufs, **tmp;
1587 int i;
1588 CS_VARIABLE* current;
1589
1590 (void) csound;
1591 buf = (OPCOD_IOBUFS*) p->h.insdshead->opcod_iobufs;
1592 inm = buf->opcode_info;
1593 bufs = ((UOPCODE*) buf->uopcode_struct)->ar + inm->outchns;
1594 tmp = buf->iobufp_ptrs; // this is used to record the UDO's internal vars
1595 // for copying at perf-time
1596 current = inm->in_arg_pool->head;
1597
1598 for (i = 0; i < inm->inchns; i++) {
1599 void* in = (void*)bufs[i];
1600 void* out = (void*)p->args[i];
1601 tmp[i + inm->outchns] = out;
1602 current->varType->copyValue(csound, out, in);
1603 current = current->next;
1604 }
1605
1606 return OK;
1607 }
1608
xoutset(CSOUND * csound,XOUT * p)1609 int xoutset(CSOUND *csound, XOUT *p)
1610 {
1611 OPCOD_IOBUFS *buf;
1612 OPCODINFO *inm;
1613 MYFLT **bufs, **tmp;
1614 CS_VARIABLE* current;
1615 int i;
1616
1617 (void) csound;
1618 buf = (OPCOD_IOBUFS*) p->h.insdshead->opcod_iobufs;
1619 inm = buf->opcode_info;
1620 bufs = ((UOPCODE*) buf->uopcode_struct)->ar;
1621 tmp = buf->iobufp_ptrs; // this is used to record the UDO's internal vars
1622 // for copying at perf-time
1623 current = inm->out_arg_pool->head;
1624
1625 for (i = 0; i < inm->outchns; i++) {
1626 void* in = (void*)p->args[i];
1627 void* out = (void*)bufs[i];
1628 tmp[i] = in;
1629 // DO NOT COPY K or A or F vars
1630 if (csoundGetTypeForArg(in) != &CS_VAR_TYPE_K &&
1631 csoundGetTypeForArg(in) != &CS_VAR_TYPE_F &&
1632 csoundGetTypeForArg(in) != &CS_VAR_TYPE_A)
1633 current->varType->copyValue(csound, out, in);
1634 current = current->next;
1635 }
1636
1637 return OK;
1638 }
1639
1640 /* IV - Sep 8 2002: new opcode: setksmps */
1641
1642 /*
1643 This opcode sets the local ksmps for an instrument
1644 it can be used on any instrument with the implementation
1645 of a mechanism to perform at local ksmps (in kperf etc)
1646 */
1647 //#include "typetabl.h"
1648 #include "csound_standard_types.h"
setksmpsset(CSOUND * csound,SETKSMPS * p)1649 int setksmpsset(CSOUND *csound, SETKSMPS *p)
1650 {
1651
1652 unsigned int l_ksmps, n;
1653
1654 l_ksmps = (unsigned int) *(p->i_ksmps);
1655 if (!l_ksmps) return OK; /* zero: do not change */
1656 if (UNLIKELY(l_ksmps < 1 || l_ksmps > CS_KSMPS ||
1657 ((CS_KSMPS / l_ksmps) * l_ksmps != CS_KSMPS))) {
1658 return csoundInitError(csound,
1659 Str("setksmps: invalid ksmps value: %d, original: %d"),
1660 l_ksmps, CS_KSMPS);
1661 }
1662
1663 n = CS_KSMPS / l_ksmps;
1664 p->h.insdshead->xtratim *= n;
1665 CS_KSMPS = l_ksmps;
1666 CS_ONEDKSMPS = FL(1.0) / (MYFLT) CS_KSMPS;
1667 CS_EKR = csound->esr / (MYFLT) CS_KSMPS;
1668 CS_ONEDKR = FL(1.0) / CS_EKR;
1669 CS_KICVT = (MYFLT) FMAXLEN / CS_EKR;
1670 CS_KCNT *= n;
1671
1672 /* VL 13-12-13 */
1673 /* this sets ksmps and kr local variables */
1674 /* lookup local ksmps variable and init with ksmps */
1675 INSTRTXT *ip = p->h.insdshead->instr;
1676 CS_VARIABLE *var =
1677 csoundFindVariableWithName(csound, ip->varPool, "ksmps");
1678 MYFLT *varmem = p->h.insdshead->lclbas + var->memBlockIndex;
1679 *varmem = CS_KSMPS;
1680
1681 /* same for kr */
1682 var =
1683 csoundFindVariableWithName(csound, ip->varPool, "kr");
1684 varmem = p->h.insdshead->lclbas + var->memBlockIndex;
1685 *varmem = CS_EKR;
1686
1687 return OK;
1688 }
1689
1690 /* IV - Oct 16 2002: nstrnum opcode (returns the instrument number of a */
1691 /* named instrument) */
1692
nstrnumset(CSOUND * csound,NSTRNUM * p)1693 int nstrnumset(CSOUND *csound, NSTRNUM *p)
1694 {
1695 /* IV - Oct 31 2002 */
1696 int res = strarg2insno(csound, p->iname, 0);
1697 if (UNLIKELY(res == NOT_AN_INSTRUMENT)) {
1698 *p->i_insno = -FL(1.0); return NOTOK;
1699 }
1700 else {
1701 *p->i_insno = (MYFLT)res; return OK;
1702 }
1703 }
1704
nstrnumset_S(CSOUND * csound,NSTRNUM * p)1705 int nstrnumset_S(CSOUND *csound, NSTRNUM *p)
1706 {
1707 /* IV - Oct 31 2002 */
1708 int res = strarg2insno(csound, ((STRINGDAT *)p->iname)->data, 1);
1709 if (UNLIKELY(res == NOT_AN_INSTRUMENT)) {
1710 *p->i_insno = -FL(1.0); return NOTOK;
1711 }
1712 else {
1713 *p->i_insno = (MYFLT)res; return OK;
1714 }
1715 }
1716
nstrstr(CSOUND * csound,NSTRSTR * p)1717 int nstrstr(CSOUND *csound, NSTRSTR *p)
1718 {
1719 char *ss = cs_inverse_hash_get(csound,
1720 csound->engineState.instrumentNames,
1721 (int)*p->num);
1722 mfree(csound,p->ans->data);
1723 p->ans->data = cs_strdup(csound, ss);
1724 p->ans->size = strlen(ss);
1725 return OK;
1726 }
1727
1728 /* unlink expired notes from activ chain */
1729 /* and mark them inactive */
1730 /* close any files in each fdchain */
1731
1732 /* IV - Feb 05 2005: changed to double */
1733
beatexpire(CSOUND * csound,double beat)1734 void beatexpire(CSOUND *csound, double beat)
1735 {
1736 INSDS *ip;
1737 strt:
1738 if ((ip = csound->frstoff) != NULL && ip->offbet <= beat) {
1739 do {
1740 if (!ip->relesing && ip->xtratim) {
1741 /* IV - Nov 30 2002: */
1742 /* allow extra time for finite length (p3 > 0) score notes */
1743 set_xtratim(csound, ip); /* enter release stage */
1744 csound->frstoff = ip->nxtoff; /* update turnoff list */
1745 #ifdef BETA
1746 if (UNLIKELY(csound->oparms->odebug))
1747 csound->Message(csound, "Calling schedofftim line %d\n", __LINE__);
1748 #endif
1749 schedofftim(csound, ip);
1750 goto strt; /* and start again */
1751 }
1752 else
1753 deact(csound, ip); /* IV - Sep 5 2002: use deact() as it also */
1754 } /* deactivates subinstrument instances */
1755 while ((ip = ip->nxtoff) != NULL && ip->offbet <= beat);
1756 csound->frstoff = ip;
1757 if (UNLIKELY(csound->oparms->odebug)) {
1758 csound->Message(csound, "deactivated all notes to beat %7.3f\n", beat);
1759 csound->Message(csound, "frstoff = %p\n", (void*) csound->frstoff);
1760 }
1761 }
1762 }
1763
1764 /* unlink expired notes from activ chain */
1765 /* and mark them inactive */
1766 /* close any files in each fdchain */
1767
1768 /* IV - Feb 05 2005: changed to double */
1769
timexpire(CSOUND * csound,double time)1770 void timexpire(CSOUND *csound, double time)
1771 {
1772 INSDS *ip;
1773
1774 strt:
1775 if ((ip = csound->frstoff) != NULL && ip->offtim <= time) {
1776 do {
1777 if (!ip->relesing && ip->xtratim) {
1778 /* IV - Nov 30 2002: */
1779 /* allow extra time for finite length (p3 > 0) score notes */
1780 set_xtratim(csound, ip); /* enter release stage */
1781 csound->frstoff = ip->nxtoff; /* update turnoff list */
1782 #ifdef BETA
1783 if (UNLIKELY(csound->oparms->odebug))
1784 csound->Message(csound, "Calling schedofftim line %d\n", __LINE__);
1785 #endif
1786 schedofftim(csound, ip);
1787
1788 goto strt; /* and start again */
1789 }
1790 else {
1791 deact(csound, ip); /* IV - Sep 5 2002: use deact() as it also */
1792 }
1793 } /* deactivates subinstrument instances */
1794 while ((ip = ip->nxtoff) != NULL && ip->offtim <= time);
1795 csound->frstoff = ip;
1796 if (UNLIKELY(csound->oparms->odebug)) {
1797 csound->Message(csound, "deactivated all notes to time %7.3f\n", time);
1798 csound->Message(csound, "frstoff = %p\n", (void*) csound->frstoff);
1799 }
1800 }
1801 }
1802
1803 /**
1804 this was rewritten for Csound 6 to allow
1805 PARCS and local ksmps instruments
1806 */
1807
subinstr(CSOUND * csound,SUBINST * p)1808 int subinstr(CSOUND *csound, SUBINST *p)
1809 {
1810 OPDS *saved_pds = CS_PDS;
1811 MYFLT *pbuf;
1812 uint32_t frame, chan;
1813 unsigned int nsmps = CS_KSMPS;
1814 INSDS *ip = p->ip;
1815 int done = ATOMIC_GET(p->ip->init_done);
1816
1817 if (UNLIKELY(!done)) /* init not done, exit */
1818 return OK;
1819
1820 //printf("%s\n", p->ip->strarg);
1821
1822 if (UNLIKELY(p->ip == NULL)) { /* IV - Oct 26 2002 */
1823 return csoundPerfError(csound, &(p->h),
1824 Str("subinstr: not initialised"));
1825 }
1826 /* copy current spout buffer and clear it */
1827 ip->spout = (MYFLT*) p->saved_spout.auxp;
1828 memset(ip->spout, 0, csound->nspout*sizeof(MYFLT));
1829 csound->spoutactive = 0;
1830
1831 /* update release flag */
1832 ip->relesing = p->parent_ip->relesing; /* IV - Nov 16 2002 */
1833
1834 /* run each opcode */
1835 if (csound->ksmps == ip->ksmps) {
1836 int error = 0;
1837 if ((CS_PDS = (OPDS *) (ip->nxtp)) != NULL) {
1838 CS_PDS->insdshead->pds = NULL;
1839 do {
1840 error = (*CS_PDS->opadr)(csound, CS_PDS);
1841 if (CS_PDS->insdshead->pds != NULL) {
1842 CS_PDS = CS_PDS->insdshead->pds;
1843 CS_PDS->insdshead->pds = NULL;
1844 }
1845 } while (error == 0 && (CS_PDS = CS_PDS->nxtp));
1846 }
1847 ip->kcounter++;
1848 }
1849 else {
1850 int i, n = csound->nspout, start = 0;
1851 int lksmps = ip->ksmps;
1852 int incr = csound->nchnls*lksmps;
1853 int offset = ip->ksmps_offset;
1854 int early = ip->ksmps_no_end;
1855 ip->spin = csound->spin;
1856 ip->kcounter = csound->kcounter*csound->ksmps/lksmps;
1857
1858 /* we have to deal with sample-accurate code
1859 whole CS_KSMPS blocks are offset here, the
1860 remainder is left to each opcode to deal with.
1861 */
1862 while (offset >= lksmps) {
1863 offset -= lksmps;
1864 start += csound->nchnls;
1865 }
1866 ip->ksmps_offset = offset;
1867 if (early) {
1868 n -= (early*csound->nchnls);
1869 ip->ksmps_no_end = early % lksmps;
1870 }
1871
1872 for (i=start; i < n; i+=incr, ip->spin+=incr, ip->spout+=incr) {
1873 if ((CS_PDS = (OPDS *) (ip->nxtp)) != NULL) {
1874 int error = 0;
1875 CS_PDS->insdshead->pds = NULL;
1876 do {
1877 if(UNLIKELY(!ATOMIC_GET8(p->ip->actflg))){
1878 memset(p->ar, 0, sizeof(MYFLT)*CS_KSMPS*p->OUTCOUNT);
1879 goto endin;
1880 }
1881 error = (*CS_PDS->opadr)(csound, CS_PDS);
1882 if (CS_PDS->insdshead->pds != NULL) {
1883 CS_PDS = CS_PDS->insdshead->pds;
1884 CS_PDS->insdshead->pds = NULL;
1885 }
1886 } while (error == 0 && (CS_PDS = CS_PDS->nxtp));
1887 }
1888 ip->kcounter++;
1889 }
1890 ip->spout = (MYFLT*) p->saved_spout.auxp;
1891 }
1892 /* copy outputs */
1893 for (chan = 0; chan < p->OUTOCOUNT; chan++) {
1894 for (pbuf = ip->spout + chan*nsmps, frame = 0;
1895 frame < nsmps; frame++) {
1896 p->ar[chan][frame] = pbuf[frame];
1897 //printf("%f\n", p->ar[chan][frame]);
1898 //pbuf += csound->nchnls;
1899 }
1900 }
1901 endin:
1902 CS_PDS = saved_pds;
1903 /* check if instrument was deactivated (e.g. by perferror) */
1904 if (!p->ip) { /* loop to last opds */
1905 while (CS_PDS->nxtp) {
1906 CS_PDS = CS_PDS->nxtp;
1907 }
1908 }
1909 return OK;
1910 }
1911
1912 /* IV - Sep 17 2002 -- case 1: local ksmps is used */
1913
useropcd1(CSOUND * csound,UOPCODE * p)1914 int useropcd1(CSOUND *csound, UOPCODE *p)
1915 {
1916 OPDS *saved_pds = CS_PDS;
1917 int g_ksmps, ofs, early, offset, i;
1918 OPCODINFO *inm;
1919 CS_VARIABLE* current;
1920 INSDS *this_instr = p->ip;
1921 MYFLT** internal_ptrs = p->buf->iobufp_ptrs;
1922 MYFLT** external_ptrs = p->ar;
1923 int done;
1924
1925 done = ATOMIC_GET(p->ip->init_done);
1926 if (UNLIKELY(!done)) /* init not done, exit */
1927 return OK;
1928
1929 p->ip->relesing = p->parent_ip->relesing; /* IV - Nov 16 2002 */
1930 early = p->h.insdshead->ksmps_no_end;
1931 offset = p->h.insdshead->ksmps_offset;
1932 p->ip->spin = p->parent_ip->spin;
1933 p->ip->spout = p->parent_ip->spout;
1934 inm = p->buf->opcode_info;
1935
1936 /* global ksmps is the caller instr ksmps minus sample-accurate end */
1937 g_ksmps = CS_KSMPS - early;
1938
1939 /* sample-accurate offset */
1940 ofs = offset;
1941
1942 /* clear offsets, since with CS_KSMPS=1
1943 they don't apply to opcodes, but to the
1944 calling code (ie. this code)
1945 */
1946 this_instr->ksmps_offset = 0;
1947 this_instr->ksmps_no_end = 0;
1948
1949 if (this_instr->ksmps == 1) { /* special case for local kr == sr */
1950 do {
1951 /* copy inputs */
1952 current = inm->in_arg_pool->head;
1953 for (i = 0; i < inm->inchns; i++) {
1954 // this hardcoded type check for non-perf time vars needs to change
1955 //to use generic code...
1956 // skip a-vars for now, handle uniquely within performance loop
1957 if (current->varType != &CS_VAR_TYPE_I &&
1958 current->varType != &CS_VAR_TYPE_b &&
1959 current->varType != &CS_VAR_TYPE_A &&
1960 current->subType != &CS_VAR_TYPE_I &&
1961 current->subType != &CS_VAR_TYPE_A) {
1962 // This one checks if an array has a subtype of 'i'
1963 void* in = (void*)external_ptrs[i + inm->outchns];
1964 void* out = (void*)internal_ptrs[i + inm->outchns];
1965 current->varType->copyValue(csound, out, in);
1966 } else if (current->varType == &CS_VAR_TYPE_A) {
1967 MYFLT* in = (void*)external_ptrs[i + inm->outchns];
1968 MYFLT* out = (void*)internal_ptrs[i + inm->outchns];
1969 *out = *(in + ofs);
1970 } else if (current->varType == &CS_VAR_TYPE_ARRAY &&
1971 current->subType == &CS_VAR_TYPE_A) {
1972 ARRAYDAT* src = (ARRAYDAT*)external_ptrs[i + inm->outchns];
1973 ARRAYDAT* target = (ARRAYDAT*)internal_ptrs[i + inm->outchns];
1974 int count = src->sizes[0];
1975 int j;
1976 if (src->dimensions > 1) {
1977 for (j = 0; j < src->dimensions; j++) {
1978 count *= src->sizes[j];
1979 }
1980 }
1981
1982 for (j = 0; j < count; j++) {
1983 int memberOffset = j * (src->arrayMemberSize / sizeof(MYFLT));
1984 MYFLT* in = src->data + memberOffset;
1985 MYFLT* out = target->data + memberOffset;
1986 *out = *(in + ofs);
1987 }
1988 }
1989 current = current->next;
1990 }
1991
1992 if ((CS_PDS = (OPDS *) (this_instr->nxtp)) != NULL) {
1993 int error = 0;
1994 CS_PDS->insdshead->pds = NULL;
1995 do {
1996 if(UNLIKELY(!ATOMIC_GET8(p->ip->actflg))) goto endop;
1997 error = (*CS_PDS->opadr)(csound, CS_PDS);
1998 if (CS_PDS->insdshead->pds != NULL &&
1999 CS_PDS->insdshead->pds->insdshead) {
2000 CS_PDS = CS_PDS->insdshead->pds;
2001 CS_PDS->insdshead->pds = NULL;
2002 }
2003 } while (error == 0 && p->ip != NULL
2004 && (CS_PDS = CS_PDS->nxtp));
2005 }
2006
2007 /* copy a-sig outputs, accounting for offset */
2008 current = inm->out_arg_pool->head;
2009 for (i = 0; i < inm->outchns; i++) {
2010 if (current->varType == &CS_VAR_TYPE_A) {
2011 MYFLT* in = (void*)internal_ptrs[i];
2012 MYFLT* out = (void*)external_ptrs[i];
2013 *(out + ofs) = *in;
2014 } else if (current->varType == &CS_VAR_TYPE_ARRAY &&
2015 current->subType == &CS_VAR_TYPE_A) {
2016 ARRAYDAT* src = (ARRAYDAT*)internal_ptrs[i];
2017 ARRAYDAT* target = (ARRAYDAT*)external_ptrs[i];
2018 int count = src->sizes[0];
2019 int j;
2020 if (src->dimensions > 1) {
2021 for (j = 0; j < src->dimensions; j++) {
2022 count *= src->sizes[j];
2023 }
2024 }
2025
2026 for (j = 0; j < count; j++) {
2027 int memberOffset = j * (src->arrayMemberSize / sizeof(MYFLT));
2028 MYFLT* in = src->data + memberOffset;
2029 MYFLT* out = target->data + memberOffset;
2030 *(out + ofs) = *in;
2031 }
2032 }
2033
2034 current = current->next;
2035 }
2036
2037
2038 this_instr->kcounter++;
2039 this_instr->spout += csound->nchnls;
2040 this_instr->spin += csound->nchnls;
2041 } while (++ofs < g_ksmps);
2042 }
2043 else {
2044 /* generic case for local kr != sr */
2045 /* we have to deal with sample-accurate code
2046 whole CS_KSMPS blocks are offset here, the
2047 remainder is left to each opcode to deal with.
2048 */
2049 int start = 0;
2050 int lksmps = this_instr->ksmps;
2051 while (ofs >= lksmps) {
2052 ofs -= lksmps;
2053 start++;
2054 }
2055 this_instr->ksmps_offset = ofs;
2056 ofs = start;
2057 if (UNLIKELY(early)) this_instr->ksmps_no_end = early % lksmps;
2058
2059 do {
2060 /* copy a-sig inputs, accounting for offset */
2061 size_t asigSize = (this_instr->ksmps * sizeof(MYFLT));
2062 current = inm->in_arg_pool->head;
2063 for (i = 0; i < inm->inchns; i++) {
2064 // this hardcoded type check for non-perf time vars needs to change
2065 // to use generic code...
2066 // skip a-vars for now, handle uniquely within performance loop
2067 if (current->varType != &CS_VAR_TYPE_I &&
2068 current->varType != &CS_VAR_TYPE_b &&
2069 current->varType != &CS_VAR_TYPE_A &&
2070 current->subType != &CS_VAR_TYPE_I &&
2071 current->subType != &CS_VAR_TYPE_A) {
2072 // This one checks if an array has a subtype of 'i'
2073 void* in = (void*)external_ptrs[i + inm->outchns];
2074 void* out = (void*)internal_ptrs[i + inm->outchns];
2075 current->varType->copyValue(csound, out, in);
2076 } else if (current->varType == &CS_VAR_TYPE_A) {
2077 MYFLT* in = (void*)external_ptrs[i + inm->outchns];
2078 MYFLT* out = (void*)internal_ptrs[i + inm->outchns];
2079 memcpy(out, in + ofs, asigSize);
2080 } else if (current->varType == &CS_VAR_TYPE_ARRAY &&
2081 current->subType == &CS_VAR_TYPE_A) {
2082 ARRAYDAT* src = (ARRAYDAT*)external_ptrs[i + inm->outchns];
2083 ARRAYDAT* target = (ARRAYDAT*)internal_ptrs[i + inm->outchns];
2084 int count = src->sizes[0];
2085 int j;
2086 if (src->dimensions > 1) {
2087 for (j = 0; j < src->dimensions; j++) {
2088 count *= src->sizes[j];
2089 }
2090 }
2091
2092 for (j = 0; j < count; j++) {
2093 int memberOffset = j * (src->arrayMemberSize / sizeof(MYFLT));
2094 MYFLT* in = src->data + memberOffset;
2095 MYFLT* out = target->data + memberOffset;
2096 memcpy(out, in + ofs, asigSize);
2097 }
2098 }
2099 current = current->next;
2100 }
2101
2102 /* run each opcode */
2103 if ((CS_PDS = (OPDS *) (this_instr->nxtp)) != NULL) {
2104 int error = 0;
2105 CS_PDS->insdshead->pds = NULL;
2106 do {
2107 if(UNLIKELY(!ATOMIC_GET8(p->ip->actflg))) goto endop;
2108 error = (*CS_PDS->opadr)(csound, CS_PDS);
2109 if (CS_PDS->insdshead->pds != NULL &&
2110 CS_PDS->insdshead->pds->insdshead) {
2111 CS_PDS = CS_PDS->insdshead->pds;
2112 CS_PDS->insdshead->pds = NULL;
2113 }
2114 } while (error == 0 && p->ip != NULL
2115 && (CS_PDS = CS_PDS->nxtp));
2116 }
2117
2118 /* copy a-sig outputs, accounting for offset */
2119 current = inm->out_arg_pool->head;
2120 for (i = 0; i < inm->outchns; i++) {
2121 if (current->varType == &CS_VAR_TYPE_A) {
2122 MYFLT* in = (void*)internal_ptrs[i];
2123 MYFLT* out = (void*)external_ptrs[i];
2124 memcpy(out + ofs, in, asigSize);
2125 } else if (current->varType == &CS_VAR_TYPE_ARRAY &&
2126 current->subType == &CS_VAR_TYPE_A) {
2127 ARRAYDAT* src = (ARRAYDAT*)internal_ptrs[i];
2128 ARRAYDAT* target = (ARRAYDAT*)external_ptrs[i];
2129 int count = src->sizes[0];
2130 int j;
2131 if (src->dimensions > 1) {
2132 for (j = 0; j < src->dimensions; j++) {
2133 count *= src->sizes[j];
2134 }
2135 }
2136
2137 for (j = 0; j < count; j++) {
2138 int memberOffset = j * (src->arrayMemberSize / sizeof(MYFLT));
2139 MYFLT* in = src->data + memberOffset;
2140 MYFLT* out = target->data + memberOffset;
2141 memcpy(out + ofs, in, asigSize);
2142 }
2143
2144 }
2145
2146 current = current->next;
2147 }
2148
2149 this_instr->spout += csound->nchnls*lksmps;
2150 this_instr->spin += csound->nchnls*lksmps;
2151 this_instr->kcounter++;
2152 } while ((ofs += this_instr->ksmps) < g_ksmps);
2153 }
2154
2155
2156 /* copy outputs */
2157 current = inm->out_arg_pool->head;
2158 for (i = 0; i < inm->outchns; i++) {
2159 // this hardcoded type check for non-perf time vars needs to change
2160 // to use generic code...
2161 if (current->varType != &CS_VAR_TYPE_I &&
2162 current->varType != &CS_VAR_TYPE_b &&
2163 current->subType != &CS_VAR_TYPE_I) {
2164 void* in = (void*)internal_ptrs[i];
2165 void* out = (void*)external_ptrs[i];
2166
2167 if (current->varType == &CS_VAR_TYPE_A) {
2168 /* clear the beginning portion of outputs for sample accurate end */
2169 if (offset) {
2170 memset(out, '\0', sizeof(MYFLT) * offset);
2171 }
2172
2173 /* clear the end portion of outputs for sample accurate end */
2174 if (early) {
2175 memset((char*)out + g_ksmps, '\0', sizeof(MYFLT) * early);
2176 }
2177 } else if (current->varType == &CS_VAR_TYPE_ARRAY &&
2178 current->subType == &CS_VAR_TYPE_A) {
2179 if (offset || early) {
2180 ARRAYDAT* outDat = (ARRAYDAT*)out;
2181 int count = outDat->sizes[0];
2182 int j;
2183 if (outDat->dimensions > 1) {
2184 for (j = 0; j < outDat->dimensions; j++) {
2185 count *= outDat->sizes[j];
2186 }
2187 }
2188
2189 if (offset) {
2190 for (j = 0; j < count; j++) {
2191 int memberOffset = j * (outDat->arrayMemberSize / sizeof(MYFLT));
2192 MYFLT* outMem = outDat->data + memberOffset;
2193 memset(outMem, '\0', sizeof(MYFLT) * offset);
2194 }
2195 }
2196
2197 if (early) {
2198 for (j = 0; j < count; j++) {
2199 int memberOffset = j * (outDat->arrayMemberSize / sizeof(MYFLT));
2200 MYFLT* outMem = outDat->data + memberOffset;
2201 memset(outMem + g_ksmps, '\0', sizeof(MYFLT) * early);
2202 }
2203 }
2204 }
2205
2206 } else {
2207 current->varType->copyValue(csound, out, in);
2208 }
2209 }
2210 current = current->next;
2211 }
2212 endop:
2213 CS_PDS = saved_pds;
2214 /* check if instrument was deactivated (e.g. by perferror) */
2215 if (!p->ip) /* loop to last opds */
2216 while (CS_PDS && CS_PDS->nxtp) CS_PDS = CS_PDS->nxtp;
2217 return OK;
2218 }
2219
2220 /* IV - Sep 17 2002 -- case 2: simplified routine for no local ksmps */
2221
useropcd2(CSOUND * csound,UOPCODE * p)2222 int useropcd2(CSOUND *csound, UOPCODE *p)
2223 {
2224 OPDS *saved_pds = CS_PDS;
2225 MYFLT **tmp;
2226 INSDS *this_instr = p->ip;
2227 OPCODINFO *inm;
2228 CS_VARIABLE* current;
2229 int i, done;
2230
2231 inm = (OPCODINFO*) p->h.optext->t.oentry->useropinfo;
2232 done = ATOMIC_GET(p->ip->init_done);
2233
2234 if (UNLIKELY(!done)) /* init not done, exit */
2235 return OK;
2236
2237 p->ip->spin = p->parent_ip->spin;
2238 p->ip->spout = p->parent_ip->spout;
2239
2240 if (UNLIKELY(!(CS_PDS = (OPDS*) (p->ip->nxtp))))
2241 goto endop; /* no perf code */
2242
2243
2244 /* IV - Nov 16 2002: update release flag */
2245 p->ip->relesing = p->parent_ip->relesing;
2246 tmp = p->buf->iobufp_ptrs;
2247 inm = p->buf->opcode_info;
2248
2249 MYFLT** internal_ptrs = tmp;
2250 MYFLT** external_ptrs = p->ar;
2251
2252 /* copy inputs */
2253 current = inm->in_arg_pool->head;
2254 for (i = 0; i < inm->inchns; i++) {
2255 // this hardcoded type check for non-perf time vars needs to
2256 //change to use generic code...
2257 if (current->varType != &CS_VAR_TYPE_I &&
2258 current->varType != &CS_VAR_TYPE_b &&
2259 current->subType != &CS_VAR_TYPE_I) {
2260 if (current->varType == &CS_VAR_TYPE_A && CS_KSMPS == 1) {
2261 *internal_ptrs[i + inm->outchns] = *external_ptrs[i + inm->outchns];
2262 } else {
2263 void* in = (void*)external_ptrs[i + inm->outchns];
2264 void* out = (void*)internal_ptrs[i + inm->outchns];
2265 current->varType->copyValue(csound, out, in);
2266 // memcpy(out, in, p->buf->in_arg_sizes[i]);
2267 }
2268 }
2269 current = current->next;
2270 }
2271
2272 /* run each opcode */
2273 {
2274 int error = 0;
2275 CS_PDS->insdshead->pds = NULL;
2276 do {
2277 if(UNLIKELY(!ATOMIC_GET8(p->ip->actflg))) goto endop;
2278 error = (*CS_PDS->opadr)(csound, CS_PDS);
2279 if (CS_PDS->insdshead->pds != NULL &&
2280 CS_PDS->insdshead->pds->insdshead) {
2281 CS_PDS = CS_PDS->insdshead->pds;
2282 CS_PDS->insdshead->pds = NULL;
2283 }
2284 } while (error == 0 && p->ip != NULL
2285 && (CS_PDS = CS_PDS->nxtp));
2286 }
2287 this_instr->kcounter++;
2288
2289 /* copy outputs */
2290 current = inm->out_arg_pool->head;
2291 for (i = 0; i < inm->outchns; i++) {
2292 // this hardcoded type check for non-perf time vars needs to change to
2293 // use generic code...
2294 if (current->varType != &CS_VAR_TYPE_I &&
2295 current->varType != &CS_VAR_TYPE_b &&
2296 current->subType != &CS_VAR_TYPE_I) {
2297 if (current->varType == &CS_VAR_TYPE_A && CS_KSMPS == 1) {
2298 *external_ptrs[i] = *internal_ptrs[i];
2299 } else {
2300 void* in = (void*)internal_ptrs[i];
2301 void* out = (void*)external_ptrs[i];
2302 // memcpy(out, in, p->buf->out_arg_sizes[i]);
2303 current->varType->copyValue(csound, out, in);
2304 }
2305 }
2306 current = current->next;
2307 }
2308
2309 endop:
2310
2311
2312 /* restore globals */
2313 CS_PDS = saved_pds;
2314 /* check if instrument was deactivated (e.g. by perferror) */
2315 if (!p->ip) { /* loop to last opds */
2316 while (CS_PDS && CS_PDS->nxtp) {
2317 CS_PDS = CS_PDS->nxtp;
2318 }
2319 }
2320 return OK;
2321 }
2322
2323 /* UTILITY FUNCTIONS FOR LABELS */
2324
findLabelMemOffset(CSOUND * csound,INSTRTXT * ip,char * labelName)2325 int findLabelMemOffset(CSOUND* csound, INSTRTXT* ip, char* labelName) {
2326 IGN(csound);
2327 OPTXT* optxt = (OPTXT*) ip;
2328 int offset = 0;
2329
2330 while ((optxt = optxt->nxtop) != NULL) {
2331 TEXT* t = &optxt->t;
2332 if (strcmp(t->oentry->opname, "$label") == 0 &&
2333 strcmp(t->opcod, labelName) == 0) {
2334 break;
2335 }
2336 offset += t->oentry->dsblksiz;
2337 }
2338
2339 return offset;
2340 }
2341
2342 /* create instance of an instr template */
2343 /* allocates and sets up all pntrs */
2344
instance(CSOUND * csound,int insno)2345 static void instance(CSOUND *csound, int insno)
2346 {
2347 INSTRTXT *tp;
2348 INSDS *ip;
2349 OPTXT *optxt;
2350 OPDS *opds, *prvids, *prvpds;
2351 const OENTRY *ep;
2352 int i, n, pextent, pextra, pextrab;
2353 char *nxtopds, *opdslim;
2354 MYFLT **argpp, *lclbas;
2355 CS_VAR_MEM *lcloffbas; // start of pfields
2356 char* opMemStart;
2357
2358 OPARMS *O = csound->oparms;
2359 int odebug = O->odebug;
2360 ARG* arg;
2361 int argStringCount;
2362 CS_VARIABLE* current;
2363
2364 tp = csound->engineState.instrtxtp[insno];
2365 n = 3;
2366 if (O->midiKey>n) n = O->midiKey;
2367 if (O->midiKeyCps>n) n = O->midiKeyCps;
2368 if (O->midiKeyOct>n) n = O->midiKeyOct;
2369 if (O->midiKeyPch>n) n = O->midiKeyPch;
2370 if (O->midiVelocity>n) n = O->midiVelocity;
2371 if (O->midiVelocityAmp>n) n = O->midiVelocityAmp;
2372 pextra = n-3;
2373 pextrab = ((i = tp->pmax - 3L) > 0 ? (int) i * sizeof(CS_VAR_MEM) : 0);
2374 /* alloc new space, */
2375 pextent = sizeof(INSDS) + pextrab + pextra*sizeof(CS_VAR_MEM);
2376 ip =
2377 (INSDS*) csound->Calloc(csound,
2378 (size_t) pextent + tp->varPool->poolSize +
2379 (tp->varPool->varCount *
2380 CS_FLOAT_ALIGN(CS_VAR_TYPE_OFFSET)) +
2381 (tp->varPool->varCount * sizeof(CS_VARIABLE*)) +
2382 tp->opdstot);
2383 ip->csound = csound;
2384 ip->m_chnbp = (MCHNBLK*) NULL;
2385 ip->instr = tp;
2386 /* IV - Oct 26 2002: replaced with faster version (no search) */
2387 ip->prvinstance = tp->lst_instance;
2388 if (tp->lst_instance)
2389 tp->lst_instance->nxtinstance = ip;
2390 else
2391 tp->instance = ip;
2392 tp->lst_instance = ip;
2393 /* link into free instance chain */
2394 ip->nxtact = tp->act_instance;
2395 tp->act_instance = ip;
2396 ip->insno = insno;
2397 if (UNLIKELY(csound->oparms->odebug))
2398 csoundMessage(csound,"instance(): tp->act_instance = %p\n",
2399 tp->act_instance);
2400
2401
2402 if (insno > csound->engineState.maxinsno) {
2403 // size_t pcnt = (size_t) tp->opcode_info->perf_incnt;
2404 // pcnt += (size_t) tp->opcode_info->perf_outcnt;
2405 OPCODINFO* info = tp->opcode_info;
2406 size_t pcnt = sizeof(OPCOD_IOBUFS) +
2407 sizeof(MYFLT*) * (info->inchns + info->outchns);
2408 ip->opcod_iobufs = (void*) csound->Malloc(csound, pcnt);
2409 }
2410
2411 /* gbloffbas = csound->globalVarPool; */
2412 lcloffbas = (CS_VAR_MEM*)&ip->p0;
2413 lclbas = (MYFLT*) ((char*) ip + pextent); /* split local space */
2414 initializeVarPool((void *)csound, lclbas, tp->varPool);
2415
2416 opMemStart = nxtopds = (char*) lclbas + tp->varPool->poolSize +
2417 (tp->varPool->varCount * CS_FLOAT_ALIGN(CS_VAR_TYPE_OFFSET));
2418 opdslim = nxtopds + tp->opdstot;
2419 if (UNLIKELY(odebug))
2420 csound->Message(csound,
2421 Str("instr %d allocated at %p\n\tlclbas %p, opds %p\n"),
2422 insno, ip, lclbas, nxtopds);
2423 optxt = (OPTXT*) tp;
2424 prvids = prvpds = (OPDS*) ip;
2425 // prvids->insdshead = ip;
2426
2427 /* initialize vars for CS_TYPE */
2428 for (current = tp->varPool->head; current != NULL; current = current->next) {
2429 char* ptr = (char*)(lclbas + current->memBlockIndex);
2430 CS_TYPE** typePtr = (CS_TYPE**)(ptr - CS_VAR_TYPE_OFFSET);
2431 *typePtr = current->varType;
2432 }
2433
2434 while ((optxt = optxt->nxtop) != NULL) { /* for each op in instr */
2435 TEXT *ttp = &optxt->t;
2436 ep = ttp->oentry;
2437 opds = (OPDS*) nxtopds; /* take reqd opds */
2438 nxtopds += ep->dsblksiz;
2439 if (UNLIKELY(strcmp(ep->opname, "endin") == 0 /* (until ENDIN) */
2440 || strcmp(ep->opname, "endop") == 0)) /* (or ENDOP) */
2441 break;
2442
2443 if (UNLIKELY(strcmp(ep->opname, "pset") == 0)) {
2444 ip->p1.value = (MYFLT) insno;
2445 continue;
2446 }
2447 if (UNLIKELY(odebug))
2448 csound->Message(csound, Str("op (%s) allocated at %p\n"),
2449 ep->opname, opds);
2450 opds->optext = optxt; /* set common headata */
2451 opds->insdshead = ip;
2452 if (strcmp(ep->opname, "$label") == 0) { /* LABEL: */
2453 LBLBLK *lblbp = (LBLBLK *) opds;
2454 lblbp->prvi = prvids; /* save i/p links */
2455 lblbp->prvp = prvpds;
2456 continue; /* for later refs */
2457 }
2458 // ******** This needs revisipn with no distinction between k- and a- rate ****
2459 if ((ep->thread & 03) == 0) { /* thread 1 OR 2: */
2460 if (ttp->pftype == 'b') {
2461 prvids = prvids->nxti = opds;
2462 opds->iopadr = ep->iopadr;
2463 }
2464 else {
2465 prvpds = prvpds->nxtp = opds;
2466 opds->opadr = ep->kopadr;
2467 }
2468 goto args;
2469 }
2470 if ((ep->thread & 01) != 0) { /* thread 1: */
2471 prvids = prvids->nxti = opds; /* link into ichain */
2472 opds->iopadr = ep->iopadr; /* & set exec adr */
2473 if (UNLIKELY(opds->iopadr == NULL))
2474 csoundDie(csound, Str("null iopadr"));
2475 }
2476 if ((n = ep->thread & 02) != 0) { /* thread 2 : */
2477 prvpds = prvpds->nxtp = opds; /* link into pchain */
2478 /* if (!(n & 04) || */
2479 /* ((ttp->pftype == 'k' || ttp->pftype == 'c') && ep->kopadr != NULL)) */
2480 opds->opadr = ep->kopadr; /* krate or */
2481 /* else opds->opadr = ep->aopadr; /\* arate *\/ */
2482 if (UNLIKELY(odebug))
2483 csound->Message(csound, "opadr = %p\n", (void*) opds->opadr);
2484 if (UNLIKELY(opds->opadr == NULL))
2485 csoundDie(csound, Str("null opadr"));
2486 }
2487 args:
2488 if (ep->useropinfo == NULL)
2489 argpp = (MYFLT **) ((char *) opds + sizeof(OPDS));
2490 else /* user defined opcodes are a special case */
2491 argpp = &(((UOPCODE *) ((char *) opds))->ar[0]);
2492
2493 arg = ttp->outArgs;
2494 for (n = 0; arg != NULL; n++) {
2495 MYFLT *fltp;
2496 CS_VARIABLE* var = (CS_VARIABLE*)arg->argPtr;
2497 if (arg->type == ARG_GLOBAL) {
2498 fltp = &(var->memBlock->value); /* gbloffbas + var->memBlockIndex; */
2499 }
2500 else if (arg->type == ARG_LOCAL) {
2501 fltp = lclbas + var->memBlockIndex;
2502 }
2503 else if (arg->type == ARG_PFIELD) {
2504 CS_VAR_MEM* pfield = lcloffbas + arg->index;
2505 fltp = &(pfield->value);
2506 }
2507 else {
2508 csound->Message(csound, Str("FIXME: Unhandled out-arg type: %d\n"),
2509 arg->type);
2510 fltp = NULL;
2511 }
2512 argpp[n] = fltp;
2513 arg = arg->next;
2514 }
2515
2516 for (argStringCount = argsRequired(ep->outypes);
2517 n < argStringCount;
2518 n++) /* if more outypes, pad */
2519 argpp[n] = NULL;
2520
2521 arg = ttp->inArgs;
2522 ip->lclbas = lclbas;
2523 for (; arg != NULL; n++, arg = arg->next) {
2524 CS_VARIABLE* var = (CS_VARIABLE*)(arg->argPtr);
2525 if (arg->type == ARG_CONSTANT) {
2526 CS_VAR_MEM *varMem = (CS_VAR_MEM*)arg->argPtr;
2527 argpp[n] = &varMem->value;
2528 }
2529 else if (arg->type == ARG_STRING) {
2530 argpp[n] = (MYFLT*)(arg->argPtr);
2531 }
2532 else if (arg->type == ARG_PFIELD) {
2533 CS_VAR_MEM* pfield = lcloffbas + arg->index;
2534 argpp[n] = &(pfield->value);
2535 }
2536 else if (arg->type == ARG_GLOBAL) {
2537 argpp[n] = &(var->memBlock->value); /*gbloffbas + var->memBlockIndex; */
2538 }
2539 else if (arg->type == ARG_LOCAL){
2540 argpp[n] = lclbas + var->memBlockIndex;
2541 }
2542 else if (arg->type == ARG_LABEL) {
2543 argpp[n] = (MYFLT*)(opMemStart +
2544 findLabelMemOffset(csound, tp, (char*)arg->argPtr));
2545 }
2546 else {
2547 csound->Message(csound, Str("FIXME: instance unexpected arg: %d\n"),
2548 arg->type);
2549 }
2550 }
2551
2552 }
2553
2554 /* VL 13-12-13: point the memory to the local ksmps & kr variables,
2555 and initialise them */
2556 CS_VARIABLE* var = csoundFindVariableWithName(csound,
2557 ip->instr->varPool, "ksmps");
2558 if (var) {
2559 char* temp = (char*)(lclbas + var->memBlockIndex);
2560 var->memBlock = (CS_VAR_MEM*)(temp - CS_VAR_TYPE_OFFSET);
2561 var->memBlock->value = csound->ksmps;
2562 }
2563 var = csoundFindVariableWithName(csound, ip->instr->varPool, "kr");
2564 if (var) {
2565 char* temp = (char*)(lclbas + var->memBlockIndex);
2566 var->memBlock = (CS_VAR_MEM*)(temp - CS_VAR_TYPE_OFFSET);
2567 var->memBlock->value = csound->ekr;
2568 }
2569
2570 if (UNLIKELY(nxtopds > opdslim))
2571 csoundDie(csound, Str("inconsistent opds total"));
2572
2573 }
2574
prealloc_(CSOUND * csound,AOP * p,int instname)2575 int prealloc_(CSOUND *csound, AOP *p, int instname)
2576 {
2577 int n, a;
2578
2579 if (instname)
2580 n = (int) strarg2opcno(csound, ((STRINGDAT*)p->r)->data, 1,
2581 (*p->b == FL(0.0) ? 0 : 1));
2582 else {
2583 if (csound->ISSTRCOD(*p->r))
2584 n = (int) strarg2opcno(csound, get_arg_string(csound,*p->r), 1,
2585 (*p->b == FL(0.0) ? 0 : 1));
2586 else n = *p->r;
2587 }
2588
2589 if (UNLIKELY(n == NOT_AN_INSTRUMENT)) return NOTOK;
2590 if (csound->oparms->realtime)
2591 csoundSpinLock(&csound->alloc_spinlock);
2592 a = (int) *p->a - csound->engineState.instrtxtp[n]->active;
2593 for ( ; a > 0; a--)
2594 instance(csound, n);
2595 if (csound->oparms->realtime)
2596 csoundSpinUnLock(&csound->alloc_spinlock);
2597 return OK;
2598 }
2599
prealloc(CSOUND * csound,AOP * p)2600 int prealloc(CSOUND *csound, AOP *p){
2601 return prealloc_(csound,p,0);
2602 }
2603
prealloc_S(CSOUND * csound,AOP * p)2604 int prealloc_S(CSOUND *csound, AOP *p){
2605 return prealloc_(csound,p,1);
2606 }
2607
delete_instr(CSOUND * csound,DELETEIN * p)2608 int delete_instr(CSOUND *csound, DELETEIN *p)
2609 {
2610 int n;
2611 INSTRTXT *ip;
2612 INSDS *active;
2613 INSTRTXT *txtp;
2614
2615 if (IS_STR_ARG(p->insno))
2616 n = csound->strarg2insno(csound, ((STRINGDAT *)p->insno)->data, 1);
2617 else
2618 n = (int) (*p->insno + FL(0.5));
2619
2620 if (UNLIKELY(n == NOT_AN_INSTRUMENT ||
2621 n > csound->engineState.maxinsno ||
2622 csound->engineState.instrtxtp[n] == NULL))
2623 return OK; /* Instrument does not exist so noop */
2624 ip = csound->engineState.instrtxtp[n];
2625 active = ip->instance;
2626 while (active != NULL) { /* Check there are no active instances */
2627 INSDS *nxt = active->nxtinstance;
2628 if (UNLIKELY(active->actflg)) { /* Can only remove non-active instruments */
2629 char *name = csound->engineState.instrtxtp[n]->insname;
2630 if (name)
2631 return csound->InitError(csound,
2632 Str("Instrument %s is still active"), name);
2633 else
2634 return csound->InitError(csound,
2635 Str("Instrument %d is still active"), n);
2636 }
2637 #if 0
2638 if (active->opcod_iobufs && active->insno > csound->engineState.maxinsno)
2639 csound->Free(csound, active->opcod_iobufs); /* IV - Nov 10 2002 */
2640 #endif
2641 if (active->fdchp != NULL)
2642 fdchclose(csound, active);
2643 if (active->auxchp != NULL)
2644 auxchfree(csound, active);
2645 free_instr_var_memory(csound, active);
2646 csound->Free(csound, active);
2647 active = nxt;
2648 }
2649 csound->engineState.instrtxtp[n] = NULL;
2650 /* Now patch it out */
2651 for (txtp = &(csound->engineState.instxtanchor);
2652 txtp != NULL;
2653 txtp = txtp->nxtinstxt)
2654 if (txtp->nxtinstxt == ip) {
2655 OPTXT *t = ip->nxtop;
2656 txtp->nxtinstxt = ip->nxtinstxt;
2657 while (t) {
2658 OPTXT *s = t->nxtop;
2659 csound->Free(csound, t);
2660 t = s;
2661 }
2662 csound->Free(csound, ip);
2663 return OK;
2664 }
2665 return NOTOK;
2666 }
2667
2668
2669 void killInstance_enqueue(CSOUND *csound, MYFLT instr, int insno,
2670 INSDS *ip, int mode,
2671 int allow_release);
2672
killInstance(CSOUND * csound,MYFLT instr,int insno,INSDS * ip,int mode,int allow_release)2673 void killInstance(CSOUND *csound, MYFLT instr, int insno, INSDS *ip,
2674 int mode, int allow_release) {
2675 INSDS *ip2 = NULL, *nip;
2676 do { /* This loop does not terminate in mode=0 */
2677 nip = ip->nxtact;
2678 if (((mode & 8) && ip->offtim >= 0.0) ||
2679 ((mode & 4) && ip->p1.value != instr) ||
2680 (allow_release && ip->relesing)) {
2681 ip = nip;
2682 continue;
2683 }
2684 if (!(mode & 3)) {
2685 if (allow_release) {
2686 xturnoff(csound, ip);
2687 }
2688 else {
2689 nip = ip->nxtact;
2690 xturnoff_now(csound, ip);
2691 }
2692 }
2693 else {
2694 ip2 = ip;
2695 if ((mode & 3) == 1)
2696 break;
2697 }
2698 ip = nip;
2699 } while (ip != NULL && (int) ip->insno == insno);
2700
2701 if (ip2 != NULL) {
2702 if (allow_release) {
2703 xturnoff(csound, ip2);
2704 }
2705 else {
2706 xturnoff_now(csound, ip2);
2707 }
2708 }
2709 }
2710
csoundKillInstanceInternal(CSOUND * csound,MYFLT instr,char * instrName,int mode,int allow_release,int async)2711 int csoundKillInstanceInternal(CSOUND *csound, MYFLT instr, char *instrName,
2712 int mode, int allow_release, int async)
2713 {
2714 INSDS *ip;
2715 int insno;
2716
2717 if (instrName) {
2718 insno = named_instr_find(csound, instrName);
2719 instr = (MYFLT) insno;
2720 } else insno = instr;
2721
2722 if (UNLIKELY(insno < 1 || insno > (int) csound->engineState.maxinsno ||
2723 csound->engineState.instrtxtp[insno] == NULL)) {
2724 return CSOUND_ERROR;
2725 }
2726
2727 if (UNLIKELY(mode < 0 || mode > 15 || (mode & 3) == 3)) {
2728 csoundUnlockMutex(csound->API_lock);
2729 return CSOUND_ERROR;
2730 }
2731 ip = &(csound->actanchor);
2732
2733 while ((ip = ip->nxtact) != NULL && (int) ip->insno != insno);
2734 if (UNLIKELY(ip == NULL)) {
2735 return CSOUND_ERROR;
2736 }
2737
2738 if (!async) {
2739 csoundLockMutex(csound->API_lock);
2740 killInstance(csound, instr, insno, ip, mode, allow_release);
2741 csoundUnlockMutex(csound->API_lock);
2742 }
2743 else
2744 killInstance_enqueue(csound, instr, insno, ip, mode, allow_release);
2745 return CSOUND_SUCCESS;
2746 }
2747