1 /*
2 ugrw1.c:
3
4 Copyright (C) 1997 Robin Whittle
5
6 This file is part of Csound.
7
8 The Csound Library is free software; you can redistribute it
9 and/or modify it under the terms of the GNU Lesser General Public
10 License as published by the Free Software Foundation; either
11 version 2.1 of the License, or (at your option) any later version.
12
13 Csound is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public
19 License along with Csound; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21 02110-1301 USA
22 */
23
24 /* These files are based on Robin Whittle's
25 * ugrw1.c of 27 August 1996
26 * and ugrw1.h of 7 January 1995
27 *
28 * In February 1997, John Fitch reformatted the comments and
29 * cleaned up some code in printksset() - which was working fine
30 * but was inelegantly coded.
31 * In February 1998, John Fitch modified the code wrt types so it
32 * compiled with MicroSoft C without warnings.
33 *
34 *
35 * Copyright notice - Robin Whittle 25 February 1997
36 *
37 * Documentation files, and the original .c and .h files, with more
38 * spaced out comments, are available from http://www.firstpr.com.au
39 *
40 * The code in both ugrw1 and ugrw2 is copyright Robin Whittle.
41 * Permission is granted to use this in whole or in part for any
42 * purpose, provided this copyright notice remains intact and
43 * any alterations to the source code, including comments, are
44 * clearly indicated as such.
45 */
46
47 #include "csoundCore.h"
48 #include "ugrw1.h"
49 #include <math.h>
50 #include <ctype.h>
51
52 /*****************************************************************************/
53 /*****************************************************************************/
54 /*****************************************************************************/
55 /*****************************************************************************/
56
57 /* Subroutines for reading absolute time. */
58
59 /* timek()
60 *
61 * Called at i rate or k rate, by timek, itimek, timesr or itemes.
62 *
63 * This is based on global variable kcounter in insert.c.
64 * Since is apparently is not declared in a header file, we must declare it
65 * an external.
66 * Actually moved to the glob structure -- JPff march 2002
67 */
68
timek(CSOUND * csound,RDTIME * p)69 int32_t timek(CSOUND *csound, RDTIME *p)
70 {
71 IGN(csound);
72 /* Read the global variable kcounter and turn it into a float. */
73 *p->rslt = (MYFLT) CS_KCNT;
74 return OK;
75 }
76
77 /* timesr() */
timesr(CSOUND * csound,RDTIME * p)78 int32_t timesr(CSOUND *csound, RDTIME *p)
79 {
80 /* Read the global variable kcounter divide it by the k rate. */
81 IGN(csound);
82 *p->rslt = (MYFLT) CS_KCNT * CS_ONEDKR;
83 return OK;
84 }
85
86 /*-----------------------------------*/
87
88 /* Subroutines to read time for this instance of the instrument. */
89
90 /* instimset() runs at init time and keeps a record of the time then
91 * in the RDTIME data structure.
92 * Returns 0.
93 */
instimset(CSOUND * csound,RDTIME * p)94 int32_t instimset(CSOUND *csound, RDTIME *p)
95 {
96 IGN(csound);
97 p->instartk = CS_KCNT;
98 *p->rslt = FL(0.0);
99 return OK;
100 }
101
102 /* instimek()
103 *
104 * Read difference between the global variable kcounter and the starting
105 * time of this instance. Return it as a float.
106 */
instimek(CSOUND * csound,RDTIME * p)107 int32_t instimek(CSOUND *csound, RDTIME *p)
108 {
109 IGN(csound);
110 *p->rslt = (MYFLT) (CS_KCNT - p->instartk);
111 return OK;
112 }
113
114 /* insttimes()
115 *
116 * Read difference between the global variable kcounter and the starting
117 * time of this instance. Return it as a float in seconds.
118 */
instimes(CSOUND * csound,RDTIME * p)119 int32_t instimes(CSOUND *csound, RDTIME *p)
120 {
121 IGN(csound);
122 *p->rslt = (MYFLT) (CS_KCNT - p->instartk) * CS_ONEDKR;
123 return OK;
124 }
125
126 /*****************************************************************************/
127 /*****************************************************************************/
128
129 /* Printing at k rate - printk. */
130
131 /* printkset is called when the instance of the instrument is initialised. */
132
printkset(CSOUND * csound,PRINTK * p)133 int32_t printkset(CSOUND *csound, PRINTK *p)
134 {
135 /* Set up ctime so that if it was 0 or negative, it is set to a low value
136 * to ensure that the print cycle happens every k cycle. This low value is
137 * 1 / ekr */
138 /* Not sure this mattersin revised version. Would just work! -- JPff */
139 if (*p->ptime < CS_ONEDKR)
140 p->ctime = FL(0.0);
141 else
142 p->ctime = *p->ptime * csound->ekr;
143
144 /* Set up the number of spaces.
145 Limit to 120 for people with big screens or printers.
146 */
147 p->pspace = (int32_t) *p->space;
148 if (UNLIKELY(p->pspace < 0L))
149 p->pspace = 0L;
150 else if (UNLIKELY(p->pspace > 120L))
151 p->pspace = 120L;
152
153 //printf("printkset: ctime = %f\n", p->ctime);
154 p->printat = CS_KCNT;
155 p->initialised = -1;
156 return OK;
157 }
158 /*************************************/
159
160 /* printk
161 *
162 * Called on every k cycle. It must decide when to do a print operation.
163 */
printk(CSOUND * csound,PRINTK * p)164 int32_t printk(CSOUND *csound, PRINTK *p)
165 {
166 if (UNLIKELY(p->initialised != -1))
167 csound->PerfError(csound, &(p->h), Str("printk not initialised"));
168
169 //printf("printk: KCNT = %lu\n", CS_KCNT);
170 //printf("printat = %lf\n", p->printat);
171 /* Now test if the cycle number has reached the next print time */
172 if (p->printat <= CS_KCNT-1) {
173 /* Do the print cycle.
174 * Print instrument number and time. Instrument number stuff from
175 * printv() in disprep.c.
176 */
177 csound->MessageS(csound, CSOUNDMSG_ORCH, " i%4d ",
178 (int32_t)p->h.insdshead->p1.value);
179 csound->MessageS(csound, CSOUNDMSG_ORCH, Str("time %11.5f: "),
180 csound->icurTime/csound->esr-CS_ONEDKR);
181 /* Print spaces and then the value we want to read. */
182 if (p->pspace > 0L) {
183 char s[128]; /* p->pspace is limited to 120 in printkset() above */
184 memset(s, ' ', 128 /*(size_t) p->pspace */);
185 s[p->pspace] = '\0';
186 csound->MessageS(csound, CSOUNDMSG_ORCH, "%s", s);
187 }
188 if (*p->named)
189 csound->MessageS(csound, CSOUNDMSG_ORCH, "%s = %11.5f\n",
190 p->h.optext->t.inlist->arg[1], *p->val);
191 else
192 csound->MessageS(csound, CSOUNDMSG_ORCH, "%11.5f\n", *p->val);
193 p->printat = CS_KCNT + p->ctime - 1;
194 }
195 return OK;
196 }
197
198 /*---------------------------------------------------------------------------*/
199
200 /* printks() and printksset() */
201
202 /* Printing at k rate with a string * and up to four variables - printks. */
203
204 #define ESC (0x1B)
205
206 /* printksset is called when the instance of the instrument is initialised. */
printksset_(CSOUND * csound,PRINTKS * p,char * sarg)207 int32_t printksset_(CSOUND *csound, PRINTKS *p, char *sarg)
208 {
209 char *sdest;
210 char temp, tempn;
211
212 if (*p->ptime < CS_ONEDKR)
213 p->ctime = CS_ONEDKR;
214 else
215 p->ctime = *p->ptime * csound->ekr;
216 if(!p->h.insdshead->reinitflag)
217 p->printat = CS_KCNT;
218 memset(p->txtstring, 0, 8192); /* This line from matt ingalls */
219 sdest = p->txtstring;
220 /* Copy the string to the storage place in PRINTKS.
221 *
222 * We will look out for certain special codes and write special
223 * bytes directly to the string.
224 *
225 * There is probably a more elegant way of doing this, then using
226 * the look flag. I could use goto - but I would rather not. */
227 /* This is really a if then else if...
228 * construct and is currently grotty -- JPff */
229 while (*sarg) {
230 temp = *sarg++;
231 tempn = *sarg--;
232 /* Look for a single caret and insert an escape char. */
233 if ((temp == '^') && (tempn != '^')) {
234 *sdest++ = ESC;
235 }
236 /* Look for a double caret and insert a single caret - stepping forward one */
237 else if ((temp == '^') && (tempn == '^')) {
238 *sdest++ = '^';
239 sarg++;
240 }
241 /* Look for a single tilde and insert an escape followed by a '['.
242 * ESC[ is the escape sequence for ANSI consoles */
243 else if ((temp == '~') && (tempn != '~')) {
244 *sdest++ = ESC;
245 *sdest++ = '[';
246 }
247 /* Look for a double tilde and insert a tilde caret - stepping forward one. */
248 else if ((temp == '~') && (tempn == '~')) {
249 *sdest++ = '~';
250 sarg++;
251 }
252 /* Look for \n, \N etc */
253 else if (temp == '\\') {
254 switch (tempn) {
255 case 'r': case 'R':
256 *sdest++ = '\r';
257 sarg++;
258 break;
259 case 'n': case 'N':
260 *sdest++ = '\n';
261 sarg++;
262 break;
263 case 't': case 'T':
264 *sdest++ = '\t';
265 sarg++;
266 break;
267 case 'a': case 'A':
268 *sdest++ = '\a';
269 sarg++;
270 break;
271 case 'b': case 'B':
272 *sdest++ = '\b';
273 sarg++;
274 break;
275 case '\\':
276 *sdest++ = '\\';
277 sarg++;
278 break;
279 default:
280 *sdest++ = tempn;
281 sarg++;
282 break;
283 }
284 }
285 /* This case is from matt ingalls */
286 else if (temp == '%' && tempn != '%' ) {
287 /* an extra option to specify tab and
288 return as %t and %r*/
289 /* allowing for %% escape -- VL */
290 switch (tempn) {
291 case 'r': case 'R':
292 *sdest++ = '\r';
293 sarg++;
294 break;
295 case 'n': case 'N':
296 *sdest++ = '\n';
297 sarg++;
298 break;
299 case 't': case 'T':
300 *sdest++ = '\t';
301 sarg++;
302 break;
303 case '!': /* and a ';' */
304 *sdest++ = ';';
305 sarg++;
306 break;
307 // case '%': /* Should we do this? JPff */
308 // *sdest++ = '%'; /* No. VL */
309 // sarg++;
310 // break;
311 default:
312 *sdest++ = temp;
313 break;
314 }
315 }
316 else {
317 /* If none of these match, then copy the character directly
318 * and try again. */
319 *sdest++ = temp;
320 }
321 /* Increment pointer and process next character until end of string. */
322 ++sarg;
323 }
324 if(!p->h.insdshead->reinitflag)
325 p->printat = CS_KCNT;
326 p->initialised = -1;
327 return OK;
328 }
329
printksset_S(CSOUND * csound,PRINTKS * p)330 int32_t printksset_S(CSOUND *csound, PRINTKS *p){
331 char *sarg;
332 sarg = ((STRINGDAT*)p->ifilcod)->data;
333 if (sarg == NULL) return csoundInitError(csound, Str("null string\n"));
334 p->old = cs_strdup(csound, sarg);
335 return printksset_(csound, p, sarg);
336 }
337
printksset(CSOUND * csound,PRINTKS * p)338 int32_t printksset(CSOUND *csound, PRINTKS *p){
339 char* arg_string = get_arg_string(csound, *p->ifilcod);
340
341 if (arg_string == NULL) {
342 return csoundInitError(csound, Str("null string\n"));
343 }
344 return printksset_(csound, p, arg_string);
345 }
346
347
348 //perform a sprintf-style format -- matt ingalls
349 /* void sprints_local(char *outstring, char *fmt, MYFLT **kvals, int32_t numVals) */
350 /* { */
351 /* char strseg[8192]; */
352 /* int32_t i = 0, j = 0; */
353 /* char *segwaiting = 0; */
354 /* puts(fmt); */
355 /* while (*fmt) { */
356 /* if (*fmt == '%') { */
357 /* /\* if already a segment waiting, then lets print it *\/ */
358 /* if (segwaiting) { */
359 /* MYFLT xx = (j>=numVals? FL(0.0) : *kvals[j]); */
360 /* /\* printf("***xx = %f (int32_t)(xx+.5)=%d round=%d mode=%d\n", *\/ */
361 /* /\* xx, (int32_t)(xx+.5), MYFLT2LRND(xx), fegetround()); *\/ */
362 /* strseg[i] = '\0'; */
363
364 /* switch (*segwaiting) { */
365 /* case 'd': */
366 /* case 'i': */
367 /* case 'o': */
368 /* case 'x': */
369 /* case 'X': */
370 /* case 'u': */
371 /* case 'c': */
372 /* snprintf(outstring, 8196, strseg, (int32_t)MYFLT2LRND(xx)); */
373 /* break; */
374 /* case 'h': */
375 /* snprintf(outstring, 8196, strseg, (int32_t16)MYFLT2LRND(xx)); */
376 /* break; */
377 /* case 'l': */
378 /* snprintf(outstring, 8196, strseg, (int32_t32)MYFLT2LRND(xx)); */
379 /* break; */
380
381 /* default: */
382 /* printf("strseg:%s - %c\n", strseg, *segwaiting); */
383 /* CS_SPRINTF(outstring, strseg, xx); */
384 /* break; */
385 /* } */
386 /* outstring += strlen(outstring); */
387
388 /* i = 0; */
389 /* segwaiting = 0; */
390
391 /* // prevent potential problems if user didnt give enough input params */
392 /* if (j < numVals-1) */
393 /* j++; */
394 /* } */
395
396 /* /\* copy the '%' *\/ */
397 /* strseg[i++] = *fmt++; */
398
399 /* /\* find the format code *\/ */
400 /* segwaiting = fmt; */
401 /* while (*segwaiting && !isalpha(*segwaiting)) */
402 /* segwaiting++; */
403 /* } */
404 /* else */
405 /* strseg[i++] = *fmt++; */
406 /* } */
407
408 /* if (i) { */
409 /* strseg[i] = '\0'; */
410 /* if (segwaiting) { */
411 /* MYFLT xx = (j>=numVals? FL(0.0) : *kvals[j]); */
412 /* /\* printf("***xx = %f (int32_t)(xx+.5)=%d round=%d mode=%d\n", *\/ */
413 /* /\* xx, (int32_t)(xx+.5), MYFLT2LRND(xx), fegetround()); *\/ */
414 /* switch (*segwaiting) { */
415 /* case 'd': */
416 /* case 'i': */
417 /* case 'o': */
418 /* case 'x': */
419 /* case 'X': */
420 /* case 'u': */
421 /* case 'c': */
422 /* snprintf(outstring, 8196, strseg, (int32_t)MYFLT2LRND(xx)); */
423 /* break; */
424 /* case 'h': */
425 /* snprintf(outstring, 8196, strseg, (int16)MYFLT2LRND(xx)); */
426 /* break; */
427 /* case 'l': */
428 /* snprintf(outstring, 8196, strseg, (int32_t)MYFLT2LRND(xx)); */
429 /* break; */
430
431 /* default: */
432 /* CS_SPRINTF(outstring, strseg, xx); */
433 /* break; */
434 /* } */
435 /* } */
436 /* else */
437 /* snprintf(outstring, 8196, "%s", strseg); */
438 /* } */
439 /* } */
440 /* VL - rewritten 1/16
441 escaping %% correctly now.
442 */
sprints(char * outstring,char * fmt,MYFLT ** kvals,int32_t numVals)443 static int32_t sprints(char *outstring, char *fmt, MYFLT **kvals, int32_t numVals)
444 {
445 char tmp[8],cc;
446 int32_t j = 0;
447 int32_t len = 8192;
448 while (*fmt) {
449 if (*fmt == '%') {
450 if (*(fmt+1) == '%') {
451 *outstring++ = *fmt++;
452 /* *outstring++ = */ fmt++;
453 len-=1;
454 }
455 else if (*(fmt+1) && isspace(*(fmt+1))) {
456 *outstring++ = *fmt++;
457 *outstring++ = '%';
458 *outstring++ = *fmt++;
459 len-=3;
460 }
461 else {
462 int32_t n = 1;
463 char check='%';
464 tmp[0] = check;
465 while (*(fmt+n) &&
466 !isblank(*(fmt+n))) {
467 tmp[n] = *(fmt+n);
468 if (isalpha(tmp[n])) { check = tmp[n]; break;}
469 n++;
470 }
471 tmp[n] = *(fmt+n);
472 tmp[n+1] = '\0';
473 n++;
474 if (j>=numVals) return NOTOK;
475 switch (check) {
476 case 'd':
477 case 'i':
478 case 'o':
479 case 'x':
480 case 'X':
481 case 'u':
482 snprintf(outstring, len, tmp, MYFLT2LRND(*kvals[j]));
483 break;
484 case 'c':
485 cc = (char) MYFLT2LRND(*kvals[j]);
486 if (cc == '%') {
487 *outstring++ = '%';
488 }
489 snprintf(outstring, len, tmp, cc);
490 break;
491 case 's':
492 {
493 if (csoundGetTypeForArg(kvals[j]) == &CS_VAR_TYPE_S)
494 snprintf(outstring, len, tmp, ((STRINGDAT*)kvals[j])->data);
495 else snprintf(outstring, len, tmp, "??");
496 break;
497 }
498 default:
499 //puts(fmt);
500 snprintf(outstring, len, tmp, *kvals[j]);
501 break;
502 }
503 if (j < numVals-1)
504 j++;
505 fmt += n;
506 outstring += strlen(outstring);
507 len -= strlen(outstring);
508 }
509 }
510 else {
511 *outstring++ = *fmt++; *outstring = '\0';
512 len--;
513 }
514 }
515 return OK;
516 }
517
518
519 /*************************************/
520
521 /* printks is called on every k cycle
522 * It must decide when to do a
523 * print operation.
524 */
printks(CSOUND * csound,PRINTKS * p)525 int32_t printks(CSOUND *csound, PRINTKS *p)
526 {
527 char string[8192]; /* matt ingals replacement */
528
529 if (csound->ISSTRCOD(*p->ifilcod) == 0) {
530 char *sarg;
531 sarg = ((STRINGDAT*)p->ifilcod)->data;
532 if (sarg == NULL)
533 return csoundPerfError(csound, &(p->h), Str("null string\n"));
534 if (p->old==NULL || strcmp(sarg, p->old) != 0) {
535 printksset_(csound, p, sarg);
536 csound->Free(csound, p->old);
537 p->old = cs_strdup(csound, sarg);
538 }
539 }
540
541 /*-----------------------------------*/
542 if (UNLIKELY(p->initialised != -1))
543 csound->PerfError(csound, &(p->h), Str("printks not initialised"));
544 if (p->printat <= CS_KCNT-1) {
545 //string[0]='\0'; /* incase of empty string */
546 memset(string,0,8192);
547 if (sprints(string, p->txtstring, p->kvals, p->INOCOUNT-2)!=OK)
548 return
549 csound->PerfError(csound, &(p->h),
550 Str("Insufficient arguments in formatted printing"));
551 csound->MessageS(csound, CSOUNDMSG_ORCH, "%s", string);
552 p->printat = CS_KCNT + p->ctime -1;
553 }
554 return OK;
555 }
556
557 /* matt ingalls -- i-rate prints */
printsset(CSOUND * csound,PRINTS * p)558 int32_t printsset(CSOUND *csound, PRINTS *p)
559 {
560 PRINTKS pk;
561 char string[8192];
562 MYFLT ptime = 1;
563 string[0] = '\0'; /* necessary as sprints is not nice */
564 pk.h = p->h;
565 pk.ifilcod = p->ifilcod;
566 pk.ptime = &ptime;
567 printksset(csound, &pk);
568 memset(string,0,8192);
569 memset(pk.txtstring,0,sizeof(pk.txtstring));
570 if (sprints(string, pk.txtstring, p->kvals, p->INOCOUNT-1)!=OK)
571 return
572 csound->InitError(csound,
573 Str("Insufficient arguments in formatted printing"));
574 csound->MessageS(csound, CSOUNDMSG_ORCH, "%s", string);
575 return OK;
576 }
577
printsset_S(CSOUND * csound,PRINTS * p)578 int32_t printsset_S(CSOUND *csound, PRINTS *p)
579 {
580 PRINTKS pk;
581 char string[8192];
582 MYFLT ptime = 1;
583 string[0] = '\0'; /* necessary as sprints is not nice */
584 pk.h = p->h;
585 pk.ifilcod = p->ifilcod;
586 pk.ptime = &ptime;
587 printksset_S(csound, &pk);
588 if (strlen(pk.txtstring) < 8191){
589 memset(string,0,8192);
590 if (sprints(string, pk.txtstring, p->kvals, p->INOCOUNT-1)!=OK)
591 return
592 csound->InitError(csound,
593 Str("Insufficient arguments in formatted printing"));
594 csound->MessageS(csound, CSOUNDMSG_ORCH, "%s", string);
595 } else {
596 csound->Warning(csound,
597 Str("Formatting string too long: %s"), pk.txtstring);
598 }
599 return OK;
600 }
601
602 /*****************************************************************************/
603
604 /* peakk and peak ugens */
605
606 /* peakk()
607 *
608 * Write the absolute value of the input argument to the output if the former
609 * is higher. */
peakk(CSOUND * csound,PEAK * p)610 int32_t peakk(CSOUND *csound, PEAK *p)
611 {
612 IGN(csound);
613 if (*p->kpeakout < FABS(*p->xsigin)) {
614 *p->kpeakout = FABS(*p->xsigin);
615 }
616 return OK;
617 }
618
619 /* peaka()
620 *
621 * Similar to peakk, but looks at an a rate input variable. */
peaka(CSOUND * csound,PEAK * p)622 int32_t peaka(CSOUND *csound, PEAK *p)
623 {
624 IGN(csound);
625 uint32_t offset = p->h.insdshead->ksmps_offset;
626 uint32_t early = p->h.insdshead->ksmps_no_end;
627 uint32_t n, nsmps = CS_KSMPS;
628 MYFLT *peak, pp;
629 MYFLT *asigin;
630
631 asigin = p->xsigin;
632 peak = p->kpeakout;
633 pp = *peak;
634 if (UNLIKELY(early)) nsmps -= early;
635 for (n=offset;n<nsmps;n++) {
636 MYFLT x = FABS(asigin[n]);
637 if (pp < x) pp = x;
638 }
639 *peak = pp;
640 return OK;
641 }
642
643 /*****************************************************************************/
644
645 /* Gab 21-8-97 */
646 /* print a k variable each time it changes (useful for MIDI control sliders) */
647
printk2set(CSOUND * csound,PRINTK2 * p)648 int32_t printk2set(CSOUND *csound, PRINTK2 *p)
649 {
650 IGN(csound);
651 p->pspace = (int32_t)*p->space;
652 if (UNLIKELY(p->pspace < 0))
653 p->pspace = 0;
654 else if (UNLIKELY(p->pspace > 120))
655 p->pspace = 120;
656 p->oldvalue = FL(-1.12123e35); /* hack to force printing first value */
657 return OK;
658 }
659
660 /* Gab 21-8-97 */
661 /* print a k variable each time it changes (useful for MIDI control sliders) */
662
printk2(CSOUND * csound,PRINTK2 * p)663 int32_t printk2(CSOUND *csound, PRINTK2 *p)
664 {
665 MYFLT value = *p->val;
666
667 if (p->oldvalue != value) {
668 csound->MessageS(csound, CSOUNDMSG_ORCH, " i%d ",
669 (int32_t)p->h.insdshead->p1.value);
670 if (p->pspace > 0) {
671 char s[128]; /* p->pspace is limited to 120 in printk2set() above */
672 memset(s, ' ', (size_t) p->pspace);
673 s[p->pspace] = '\0';
674 csound->MessageS(csound, CSOUNDMSG_ORCH, "%s", s);
675 }
676 if (*p->named)
677 csound->MessageS(csound, CSOUNDMSG_ORCH, "%s = %11.5f\n",
678 *p->h.optext->t.inlist->arg, *p->val);
679 else
680 csound->MessageS(csound, CSOUNDMSG_ORCH, "%11.5f\n", *p->val);
681 p->oldvalue = value;
682 }
683 return OK;
684 }
685
printk3set(CSOUND * csound,PRINTK3 * p)686 int32_t printk3set(CSOUND *csound, PRINTK3 *p)
687 {
688 IGN(csound);
689 p->oldvalue = FL(-1.12123e35); /* hack to force printing first value */
690 p->sarg = ((STRINGDAT*)p->iformat)->data;
691 return OK;
692 }
693
printk3(CSOUND * csound,PRINTK3 * p)694 int32_t printk3(CSOUND *csound, PRINTK3 *p)
695 {
696 MYFLT value = *p->val;
697
698 if (p->oldvalue != value) {
699 char buff[8196];
700 MYFLT *vv[1];
701 vv[0] = &value;
702 buff[0] = '\0';
703 if (sprints(buff, p->sarg, vv, 1)!=OK)
704 return
705 csound->PerfError(csound, &(p->h),
706 Str("Insufficient arguments in formatted printing"));
707 csound->MessageS(csound, CSOUNDMSG_ORCH, "%s", buff);
708 p->oldvalue = value;
709 }
710 //else printf("....%f %f\n", p->oldvalue, value);
711 return OK;
712 }
713
714 /* inz writes to za space at a rate as many channels as can. */
inz(CSOUND * csound,IOZ * p)715 int32_t inz(CSOUND *csound, IOZ *p)
716 {
717 int32_t indx, i;
718 int32_t nchns = csound->GetNchnls(csound);
719 uint32_t offset = p->h.insdshead->ksmps_offset;
720 uint32_t early = p->h.insdshead->ksmps_no_end;
721 uint32_t n, nsmps = CS_KSMPS;
722 /* Check to see this index is within the limits of za space. */
723 MYFLT* zastart;
724 int zalast = csound->GetZaBounds(csound, &zastart);
725 indx = (int32_t) *p->ndx;
726 if (UNLIKELY(indx + nchns >= zalast)) goto err1;
727 else if (UNLIKELY(indx < 0)) goto err2;
728 else {
729 MYFLT *writeloc;
730 /* Now write to the array in za space pointed to by indx. */
731 writeloc = zastart + (indx * nsmps);
732 early = nsmps - early;
733 for (i = 0; i < nchns; i++)
734 for (n = 0; n < nsmps; n++)
735 *writeloc++ = ((n>=offset && n<early) ?
736 CS_SPIN[i * nsmps+n] : FL(0.0));
737 }
738 return OK;
739 err1:
740 return csound->PerfError(csound, &(p->h),
741 Str("inz index > isizea. Not writing."));
742 err2:
743 return csound->PerfError(csound, &(p->h),
744 Str("inz index < 0. Not writing."));
745 }
746
747 /* outz reads from za space at a rate to output. */
outz(CSOUND * csound,IOZ * p)748 int32_t outz(CSOUND *csound, IOZ *p)
749 {
750 int32_t indx;
751 int32_t i;
752 uint32_t offset = p->h.insdshead->ksmps_offset;
753 uint32_t early = p->h.insdshead->ksmps_no_end;
754 uint32_t n, nsmps = CS_KSMPS;
755 int32_t nchns = csound->GetNchnls(csound);
756 MYFLT *spout = csound->spraw;
757
758 /* Check to see this index is within the limits of za space. */
759 MYFLT* zastart;
760 int zalast = csound->GetZaBounds(csound, &zastart);
761 indx = (int32) *p->ndx;
762 if (UNLIKELY((indx + nchns) >= zalast)) goto err1;
763 else if (UNLIKELY(indx < 0)) goto err2;
764 else {
765 MYFLT *readloc;
766 /* Now read from the array in za space and write to the output. */
767 readloc = zastart + (indx * nsmps);
768 early = nsmps-early;
769 if (!csound->spoutactive) {
770 memset(spout, '\0', nchns*nsmps*sizeof(MYFLT));
771 for (i = 0; i < nchns; i++) {
772 memcpy(&spout[i * nsmps+offset], readloc+offset,
773 (early-offset)*sizeof(MYFLT));
774 readloc += nsmps;
775 }
776 csound->spoutactive = 1;
777 }
778 else {
779 for (i = 0; i < nchns; i++) {
780 for (n = offset; n < nsmps-early; n++) {
781 spout[n + i*nsmps] += readloc[n];
782 }
783 readloc += nsmps;
784 }
785 }
786 }
787 return OK;
788 err1:
789 return csound->PerfError(csound, &(p->h),
790 Str("outz index > isizea. No output"));
791 err2:
792 return csound->PerfError(csound, &(p->h),
793 Str("outz index < 0. No output."));
794 }
795