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