1 /*
2 fout.c:
3
4 Copyright (C) 1999 Gabriel Maldonado, John ffitch, Matt Ingalls
5 (C) 2005, 2006 Istvan Varga
6
7 This file is part of Csound.
8
9 The Csound Library is free software; you can redistribute it
10 and/or modify it under the terms of the GNU Lesser General Public
11 License as published by the Free Software Foundation; either
12 version 2.1 of the License, or (at your option) any later version.
13
14 Csound is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU Lesser General Public License for more details.
18
19 You should have received a copy of the GNU Lesser General Public
20 License along with Csound; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
22 02110-1301 USA
23 */
24
25 /* Opcodes By Gabriel Maldonado, 1999 */
26 /* Code modified by JPff to remove fixed size arrays, allow
27 AIFF and WAV, and close files neatly. Also bugs fixed */
28
29 #include "stdopcod.h"
30 #include <sndfile.h>
31 #include "fout.h"
32 #include "soundio.h"
33 #include <ctype.h>
34
35 /* remove a file reference, optionally closing the file */
36
fout_deinit_callback(CSOUND * csound,void * p_)37 static CS_NOINLINE int32_t fout_deinit_callback(CSOUND *csound, void *p_)
38 {
39 FOUT_FILE *p = (FOUT_FILE*) p_;
40 struct fileinTag *pp;
41 p->sf = (SNDFILE*) NULL;
42 p->f = (FILE*) NULL;
43 if (p->idx) {
44 pp = &(((STDOPCOD_GLOBALS*) csound->stdOp_Env)->file_opened[p->idx - 1]);
45 p->idx = 0;
46 if (pp->refCount) {
47 pp->refCount--;
48 /* VL 29/08/07: files were not being closed properly,
49 changed check to 0 */
50 if (pp->refCount == 0/*0x80000000U*/) {
51 pp->file = (SNDFILE*) NULL;
52 pp->raw = (FILE*) NULL;
53 csound->Free(csound, pp->name);
54 pp->name = (char*) NULL;
55 pp->do_scale = 0;
56 pp->refCount = 0U;
57
58 if (pp->fd != NULL) {
59 if ((csound->oparms->msglevel & 7) == 7)
60 csound->Message(csound, Str("Closing file '%s'...\n"),
61 csound->GetFileName(pp->fd));
62 csound->FileClose(csound, pp->fd);
63 pp->fd = NULL;
64 }
65 }
66 }
67 }
68
69 return OK;
70 }
71
fout_open_file(CSOUND * csound,FOUT_FILE * p,void * fp,int32_t fileType,MYFLT * iFile,int32_t isString,void * fileParams,int32_t forceSync)72 static CS_NOINLINE int32_t fout_open_file(CSOUND *csound, FOUT_FILE *p, void *fp,
73 int32_t fileType, MYFLT *iFile,
74 int32_t isString,
75 void *fileParams, int32_t forceSync)
76 {
77 STDOPCOD_GLOBALS *pp = (STDOPCOD_GLOBALS*) csound->stdOp_Env;
78 char *name;
79 int32_t idx, csFileType, need_deinit = 0;
80
81 if (p != (FOUT_FILE*) NULL) p->async = 0;
82 if (fp != NULL) {
83 if (fileType == CSFILE_STD)
84 *((FILE**) fp) = (FILE*) NULL;
85 else
86 *((SNDFILE**) fp) = (SNDFILE*) NULL;
87 }
88 /* if the opcode already uses a file, remove old reference first */
89 if (p != (FOUT_FILE*) NULL) {
90 if (p->idx)
91 fout_deinit_callback(csound, (void*) p);
92 else
93 need_deinit = 1;
94 }
95 /* get file name, */
96 if (isString) name = cs_strdup(csound, ((STRINGDAT *)iFile)->data);
97 else if (csound->ISSTRCOD(*iFile))
98 name = cs_strdup(csound, get_arg_string(csound, *iFile));
99 /* else csound->strarg2name(csound, NULL, iFile, "fout.", 0);*/
100 else {
101 /* or handle to previously opened file */
102 idx = (int32_t) MYFLT2LRND(*iFile);
103 if (UNLIKELY(idx < 0 || idx > pp->file_num ||
104 (fileType == CSFILE_STD && pp->file_opened[idx].raw == NULL) ||
105 (fileType != CSFILE_STD && pp->file_opened[idx].file == NULL))) {
106 return csound->InitError(csound, Str("invalid file handle"));
107 }
108 goto returnHandle;
109 }
110 /* check for a valid name */
111 if (UNLIKELY(name == NULL || name[0] == '\0')) {
112 csound->Free(csound, name);
113 return csound->InitError(csound, Str("invalid file name"));
114 }
115 /* is this file already open ? */
116 if (fileType == CSFILE_STD) {
117 for (idx = 0; idx <= pp->file_num; idx++) {
118 if (pp->file_opened[idx].raw != (FILE*) NULL &&
119 strcmp(pp->file_opened[idx].name, name) == 0)
120 goto returnHandle;
121 }
122 }
123 else {
124 for (idx = 0; idx <= pp->file_num; idx++) {
125 if (pp->file_opened[idx].file != (SNDFILE*) NULL &&
126 strcmp(pp->file_opened[idx].name, name) == 0)
127 goto returnHandle;
128 }
129 }
130 /* allocate new file handle, or use an already existing unused one */
131 for (idx = 0; idx <= pp->file_num; idx++) {
132 if (pp->file_opened[idx].fd == NULL)
133 break;
134 }
135 if (idx > pp->file_num) {
136 if (idx >= pp->file_max) {
137 struct fileinTag *tmp;
138 /* Expand by 4 each time */
139 pp->file_max = (idx | 3) + 1;
140 tmp = (struct fileinTag *)
141 csound->ReAlloc(csound, pp->file_opened,
142 sizeof(struct fileinTag) * pp->file_max);
143 pp->file_opened = tmp;
144 memset(&(tmp[pp->file_num + 1]), 0,
145 sizeof(struct fileinTag) * (pp->file_max - (pp->file_num + 1)));
146 }
147 pp->file_num = idx;
148 }
149 memset(&pp->file_opened[idx], 0, sizeof(struct fileinTag));
150 /* pp->file_opened[idx].file = (SNDFILE*) NULL; */
151 /* pp->file_opened[idx].raw = (FILE*) NULL; */
152 /* pp->file_opened[idx].fd = NULL; */
153 /* pp->file_opened[idx].name = (char*) NULL; */
154 /* pp->file_opened[idx].do_scale = 0; */
155 /* pp->file_opened[idx].refCount = 0U; */
156 /* attempt to open file */
157 if (fileType == CSFILE_STD) {
158 FILE *f;
159 void *fd;
160 char *filemode = (char*)fileParams;
161
162 /* akozar: csFileType cannot be as specific as I'd like since it is not
163 possible to know the real file type until this handle is used */
164 if ((strcmp(filemode, "rb") == 0 || (strcmp(filemode, "wb") == 0)))
165 csFileType = CSFTYPE_OTHER_BINARY;
166 else csFileType = CSFTYPE_OTHER_TEXT;
167 fd = csound->FileOpen2(csound, &f, fileType, name, fileParams, "",
168 csFileType, 0);
169 if (UNLIKELY(fd == NULL)) {
170 csound->InitError(csound, Str("error opening file '%s'"), name);
171 csound->Free(csound, name);
172 return NOTOK;
173 }
174 /* setvbuf(f, (char *) NULL, _IOLBF, 0); */ /* Ensure line buffering */
175 pp->file_opened[idx].raw = f;
176 pp->file_opened[idx].fd = fd;
177 }
178 else {
179 SNDFILE *sf;
180 void *fd;
181 //int32_t buf_reqd;
182 int32_t do_scale = 0;
183
184 if (fileType == CSFILE_SND_W) {
185 do_scale = ((SF_INFO*) fileParams)->format;
186 csFileType = csound->sftype2csfiletype(do_scale);
187 if (csound->oparms->realtime == 0 || forceSync == 1) {
188 fd = csound->FileOpen2(csound, &sf, fileType, name, fileParams,
189 "SFDIR", csFileType, 0);
190 p->async = 0;
191 }
192 else {
193 p->fd = fd = csound->FileOpenAsync(csound, &sf, fileType,
194 name, fileParams,
195 "SFDIR;SSDIR", CSFTYPE_UNKNOWN_AUDIO,
196 p->bufsize, 0);
197 p->async = 1;
198 }
199 p->nchnls = ((SF_INFO*) fileParams)->channels;
200 }
201 else {
202 if (csound->oparms->realtime == 0 || forceSync == 1) {
203 fd = csound->FileOpen2(csound, &sf, fileType, name, fileParams,
204 "SFDIR;SSDIR", CSFTYPE_UNKNOWN_AUDIO, 0);
205 p->async = 0;
206
207 } else {
208 p->fd = fd = csound->FileOpenAsync(csound, &sf, fileType,
209 name, fileParams,
210 "SFDIR;SSDIR", CSFTYPE_UNKNOWN_AUDIO,
211 p->bufsize, 0);
212 p->async = 1;
213 }
214 p->nchnls = ((SF_INFO*) fileParams)->channels;
215 do_scale = ((SF_INFO*) fileParams)->format;
216 }
217 do_scale = (SF2TYPE(do_scale) == TYP_RAW ? 0 : 1);
218 if (UNLIKELY(fd == NULL)) {
219 csound->InitError(csound, Str("error opening sound file '%s'"), name);
220 csound->Free(csound, name);
221 return NOTOK;
222 }
223 if (!do_scale) {
224 #ifdef USE_DOUBLE
225 sf_command(sf, SFC_SET_NORM_DOUBLE, NULL, SF_FALSE);
226 #else
227 sf_command(sf, SFC_SET_NORM_FLOAT, NULL, SF_FALSE);
228 #endif
229 }
230 /* if (CS_KSMPS >= 512)
231 buf_reqd = CS_KSMPS * ((SF_INFO*) fileParams)->channels;
232 else
233 buf_reqd = (1 + (int32_t)(512 / CS_KSMPS)) * CS_KSMPS
234 * ((SF_INFO*) fileParams)->channels;
235 if (UNLIKELY(buf_reqd > pp->buf_size)) {
236 pp->buf_size = buf_reqd;
237 pp->buf = (MYFLT*) csound->ReAlloc(csound, pp->buf, sizeof(MYFLT)
238 * buf_reqd);
239 }
240 */ /* VL - now using per-instance buffer */
241 pp->file_opened[idx].file = sf;
242 pp->file_opened[idx].fd = fd;
243 pp->file_opened[idx].do_scale = do_scale;
244 }
245 /* store file information */
246 pp->file_opened[idx].name = name;
247
248 returnHandle:
249 /* return 'idx' as file handle */
250 if (fp != NULL) {
251 if (fileType == CSFILE_STD)
252 *((FILE**) fp) = pp->file_opened[idx].raw;
253 else
254 *((SNDFILE**) fp) = pp->file_opened[idx].file;
255 }
256 if (p != (FOUT_FILE*) NULL) {
257 if (fileType == CSFILE_STD) {
258 p->sf = (SNDFILE*) NULL;
259 p->f = pp->file_opened[idx].raw;
260 }
261 else {
262 p->sf = pp->file_opened[idx].file;
263 p->f = (FILE*) NULL;
264 }
265 p->idx = idx + 1;
266 pp->file_opened[idx].refCount++;
267 if (need_deinit) {
268 p->h.insdshead = csound->ids->insdshead;
269 /* FIXME: should check for error here */
270 csound->RegisterDeinitCallback(csound, p, fout_deinit_callback);
271 }
272 }
273 return idx;
274 }
275
outfile(CSOUND * csound,OUTFILE * p)276 static int32_t outfile(CSOUND *csound, OUTFILE *p)
277 {
278 uint32_t offset = p->h.insdshead->ksmps_offset;
279 uint32_t early = p->h.insdshead->ksmps_no_end;
280 uint32_t i, j, k, nsmps = CS_KSMPS;
281 uint32_t nargs = p->nargs;
282 MYFLT *buf = (MYFLT *) p->buf.auxp;
283
284 if (UNLIKELY(early)) nsmps -= early;
285 if (p->f.sf == NULL) {
286 if (p->f.f != NULL) { /* VL: make sure there is an open file */
287 FILE *fp = p->f.f;
288 for (k = offset; k < nsmps; k++) {
289 for (j = 0; j < nargs; j++)
290 fprintf(fp, "%g ", p->argums[j][k]);
291 fprintf(fp, "\n");
292 }
293 }
294 }
295 else {
296 for (j = offset, k = p->buf_pos; j < nsmps; j++)
297 for (i = 0; i < nargs; i++)
298 buf[k++] = p->argums[i][j] * p->scaleFac;
299 p->buf_pos = k;
300 if (p->buf_pos >= p->guard_pos) {
301
302 //#ifndef USE_DOUBLE
303 //sf_write_float(p->f.sf, buf, p->buf_pos);
304 //#else
305 //sf_write_double(p->f.sf, buf, p->buf_pos);
306 //#endif
307 if (p->f.async==1)
308 csound->WriteAsync(csound, p->f.fd, buf, p->buf_pos);
309 else sf_write_MYFLT(p->f.sf, buf, p->buf_pos);
310 p->buf_pos = 0;
311 }
312
313 }
314 return OK;
315 }
316
outfile_array(CSOUND * csound,OUTFILEA * p)317 static int32_t outfile_array(CSOUND *csound, OUTFILEA *p)
318 {
319 uint32_t offset = p->h.insdshead->ksmps_offset;
320 uint32_t early = p->h.insdshead->ksmps_no_end;
321 uint32_t i, j, k, nsmps = CS_KSMPS;
322 uint32_t nargs = p->tabin->sizes[0];
323 MYFLT *buf = (MYFLT *) p->buf.auxp;
324 MYFLT *data = p->tabin->data;
325
326 if (UNLIKELY(early)) nsmps -= early;
327 if (p->f.sf == NULL) {
328 if (p->f.f != NULL) { /* VL: make sure there is an open file */
329 FILE *fp = p->f.f;
330 for (k = offset; k < nsmps; k++) {
331 for (j = 0; j < nargs; j++)
332 fprintf(fp, "%g ", data[j*CS_KSMPS+k]);
333 fprintf(fp, "\n");
334 }
335 }
336 }
337 else {
338 for (j = offset, k = p->buf_pos; j < nsmps; j++)
339 for (i = 0; i < nargs; i++)
340 buf[k++] = data[i*CS_KSMPS+j] * p->scaleFac;
341 p->buf_pos = k;
342 if (p->buf_pos >= p->guard_pos) {
343
344 //#ifndef USE_DOUBLE
345 //sf_write_float(p->f.sf, buf, p->buf_pos);
346 //#else
347 //sf_write_double(p->f.sf, buf, p->buf_pos);
348 //#endif
349 if (p->f.async==1)
350 csound->WriteAsync(csound, p->f.fd, buf, p->buf_pos);
351 else
352 sf_write_MYFLT(p->f.sf, buf, p->buf_pos);
353 p->buf_pos = 0;
354 }
355
356 }
357 return OK;
358 }
359
360 static const int32_t fout_format_table[51] = {
361 /* 0 - 9 */
362 (SF_FORMAT_FLOAT | SF_FORMAT_RAW), (SF_FORMAT_PCM_16 | SF_FORMAT_RAW),
363 SF_FORMAT_PCM_16, SF_FORMAT_ULAW, SF_FORMAT_PCM_16, SF_FORMAT_PCM_32,
364 SF_FORMAT_FLOAT, SF_FORMAT_PCM_U8, SF_FORMAT_PCM_24, SF_FORMAT_DOUBLE,
365 /* 10 - 19 */
366 SF_FORMAT_WAV, (SF_FORMAT_PCM_S8 | SF_FORMAT_WAV),
367 (SF_FORMAT_ALAW | SF_FORMAT_WAV), (SF_FORMAT_ULAW | SF_FORMAT_WAV),
368 (SF_FORMAT_PCM_16 | SF_FORMAT_WAV), (SF_FORMAT_PCM_32 | SF_FORMAT_WAV),
369 (SF_FORMAT_FLOAT | SF_FORMAT_WAV), (SF_FORMAT_PCM_U8 | SF_FORMAT_WAV),
370 (SF_FORMAT_PCM_24 | SF_FORMAT_WAV), (SF_FORMAT_DOUBLE | SF_FORMAT_WAV),
371 /* 20 - 29 */
372 SF_FORMAT_AIFF, (SF_FORMAT_PCM_S8 | SF_FORMAT_AIFF),
373 (SF_FORMAT_ALAW | SF_FORMAT_AIFF), (SF_FORMAT_ULAW | SF_FORMAT_AIFF),
374 (SF_FORMAT_PCM_16 | SF_FORMAT_AIFF), (SF_FORMAT_PCM_32 | SF_FORMAT_AIFF),
375 (SF_FORMAT_FLOAT | SF_FORMAT_AIFF), (SF_FORMAT_PCM_U8 | SF_FORMAT_AIFF),
376 (SF_FORMAT_PCM_24 | SF_FORMAT_AIFF), (SF_FORMAT_DOUBLE | SF_FORMAT_AIFF),
377 /* 30 - 39 */
378 SF_FORMAT_RAW, (SF_FORMAT_PCM_S8 | SF_FORMAT_RAW),
379 (SF_FORMAT_ALAW | SF_FORMAT_RAW), (SF_FORMAT_ULAW | SF_FORMAT_RAW),
380 (SF_FORMAT_PCM_16 | SF_FORMAT_RAW), (SF_FORMAT_PCM_32 | SF_FORMAT_RAW),
381 (SF_FORMAT_FLOAT | SF_FORMAT_RAW), (SF_FORMAT_PCM_U8 | SF_FORMAT_RAW),
382 (SF_FORMAT_PCM_24 | SF_FORMAT_RAW), (SF_FORMAT_DOUBLE | SF_FORMAT_RAW),
383 /* 40 - 49 */
384 SF_FORMAT_IRCAM, (SF_FORMAT_PCM_S8 | SF_FORMAT_IRCAM),
385 (SF_FORMAT_ALAW | SF_FORMAT_IRCAM), (SF_FORMAT_ULAW | SF_FORMAT_IRCAM),
386 (SF_FORMAT_PCM_16 | SF_FORMAT_IRCAM), (SF_FORMAT_PCM_32 | SF_FORMAT_IRCAM),
387 (SF_FORMAT_FLOAT | SF_FORMAT_IRCAM), (SF_FORMAT_PCM_U8 | SF_FORMAT_IRCAM),
388 (SF_FORMAT_PCM_24 | SF_FORMAT_IRCAM), (SF_FORMAT_DOUBLE | SF_FORMAT_IRCAM),
389 /* 50 */
390 (SF_FORMAT_OGG | SF_FORMAT_VORBIS)
391 };
392
fout_flush_callback(CSOUND * csound,void * p_)393 static int32_t fout_flush_callback(CSOUND *csound, void *p_)
394 {
395 OUTFILE *p = (OUTFILE*) p_;
396
397 if (p->f.sf != NULL && p->buf_pos > 0) {
398 //#ifndef USE_DOUBLE
399 //sf_write_float(p->f.sf, (float*) p->buf.auxp, p->buf_pos);
400 //#else
401 //sf_write_double(p->f.sf, (double*) p->buf.auxp, p->buf_pos);
402 //#endif
403 if (p->f.async == 1)
404 csound->WriteAsync(csound, p->f.fd, (MYFLT *) p->buf.auxp, p->buf_pos);
405 else
406 sf_write_MYFLT(p->f.sf, (MYFLT *) p->buf.auxp, p->buf_pos);
407 }
408 return OK;
409 }
410
fouta_flush_callback(CSOUND * csound,void * p_)411 static int32_t fouta_flush_callback(CSOUND *csound, void *p_)
412 {
413 OUTFILEA *p = (OUTFILEA*) p_;
414
415 if (p->f.sf != NULL && p->buf_pos > 0) {
416 //#ifndef USE_DOUBLE
417 //sf_write_float(p->f.sf, (float*) p->buf.auxp, p->buf_pos);
418 //#else
419 //sf_write_double(p->f.sf, (double*) p->buf.auxp, p->buf_pos);
420 //#endif
421 if (p->f.async == 1)
422 csound->WriteAsync(csound, p->f.fd, (MYFLT *) p->buf.auxp, p->buf_pos);
423 else
424 sf_write_MYFLT(p->f.sf, (MYFLT *) p->buf.auxp, p->buf_pos);
425 }
426 return OK;
427 }
428
outfile_set_S(CSOUND * csound,OUTFILE * p)429 static int32_t outfile_set_S(CSOUND *csound, OUTFILE *p/*, int32_t istring*/)
430 {
431 SF_INFO sfinfo;
432 int32_t format_, n, buf_reqd;
433 int32_t istring = 1;
434
435 memset(&sfinfo, 0, sizeof(SF_INFO));
436 format_ = (int32_t) MYFLT2LRND(*p->iflag);
437 if (format_ >= 51)
438 sfinfo.format = SF_FORMAT_PCM_16 | SF_FORMAT_RAW;
439 else if (format_ < 0) {
440 sfinfo.format = FORMAT2SF(csound->oparms->outformat);
441 sfinfo.format |= TYPE2SF(csound->oparms->filetyp);
442 }
443 else sfinfo.format = fout_format_table[format_];
444 if (!SF2FORMAT(sfinfo.format))
445 sfinfo.format |= FORMAT2SF(csound->oparms->outformat);
446 if (!SF2TYPE(sfinfo.format))
447 sfinfo.format |= TYPE2SF(csound->oparms->filetyp);
448 sfinfo.samplerate = (int32_t) MYFLT2LRND(CS_ESR);
449 p->nargs = p->INOCOUNT - 2;
450 p->buf_pos = 0;
451
452 if (CS_KSMPS >= 512)
453 p->guard_pos = CS_KSMPS * p->nargs;
454 else
455 p->guard_pos = 512* p->nargs;
456
457 if (CS_KSMPS >= 512)
458 buf_reqd = CS_KSMPS * p->nargs;
459 else
460 buf_reqd = (1 + (int32_t)(512 / CS_KSMPS)) * CS_KSMPS * p->nargs;
461 if (p->buf.auxp == NULL || p->buf.size < buf_reqd*sizeof(MYFLT)) {
462 csound->AuxAlloc(csound, sizeof(MYFLT)*buf_reqd, &p->buf);
463 }
464 p->f.bufsize = p->buf.size;
465 sfinfo.channels = p->nargs;
466 n = fout_open_file(csound, &(p->f), NULL, CSFILE_SND_W,
467 p->fname, istring, &sfinfo, 0);
468 if (UNLIKELY(n < 0))
469 return NOTOK;
470
471 if (((STDOPCOD_GLOBALS*) csound->stdOp_Env)->file_opened[n].do_scale)
472 p->scaleFac = csound->dbfs_to_float;
473 else
474 p->scaleFac = FL(1.0);
475
476 csound->RegisterDeinitCallback(csound, p, fout_flush_callback);
477 return OK;
478 }
479
480 /* static int32_t outfile_set(CSOUND *csound, OUTFILE *p){ */
481 /* return outfile_set_(csound,p,0); */
482 /* } */
483
484 /* static int32_t outfile_set_S(CSOUND *csound, OUTFILE *p){ */
485 /* return outfile_set_(csound,p,1); */
486 /* } */
487
outfile_set_A(CSOUND * csound,OUTFILEA * p)488 static int32_t outfile_set_A(CSOUND *csound, OUTFILEA *p)
489 {
490 SF_INFO sfinfo;
491 int32_t format_, n, buf_reqd;
492 int32_t len = p->tabin->sizes[0];
493
494 memset(&sfinfo, 0, sizeof(SF_INFO));
495 format_ = (int32_t) MYFLT2LRND(*p->iflag);
496 if (format_ >= 51)
497 sfinfo.format = SF_FORMAT_PCM_16 | SF_FORMAT_RAW;
498 else if (format_ < 0) {
499 sfinfo.format = FORMAT2SF(csound->oparms->outformat);
500 sfinfo.format |= TYPE2SF(csound->oparms->filetyp);
501 }
502 else
503 sfinfo.format = fout_format_table[format_];
504 if (!SF2FORMAT(sfinfo.format))
505 sfinfo.format |= FORMAT2SF(csound->oparms->outformat);
506 if (!SF2TYPE(sfinfo.format))
507 sfinfo.format |= TYPE2SF(csound->oparms->filetyp);
508 sfinfo.samplerate = (int32_t) MYFLT2LRND(CS_ESR);
509 p->buf_pos = 0;
510
511 if (CS_KSMPS >= 512)
512 buf_reqd = p->guard_pos = CS_KSMPS * len;
513 else {
514 p->guard_pos = 512 * len;
515 buf_reqd = (1 + (int32_t)(512 / CS_KSMPS)) * p->guard_pos;
516 // Or......
517 //buf_reqd = (1 + (int32_t)(512 / CS_KSMPS)) * CS_KSMPS * len;
518 }
519 if (p->buf.auxp == NULL || p->buf.size < buf_reqd*sizeof(MYFLT)) {
520 csound->AuxAlloc(csound, sizeof(MYFLT)*buf_reqd, &p->buf);
521 }
522 p->f.bufsize = p->buf.size;
523 sfinfo.channels = len;
524 n = fout_open_file(csound, &(p->f), NULL, CSFILE_SND_W,
525 p->fname, 1, &sfinfo, 0);
526 if (UNLIKELY(n < 0))
527 return NOTOK;
528
529 if (((STDOPCOD_GLOBALS*) csound->stdOp_Env)->file_opened[n].do_scale)
530 p->scaleFac = csound->dbfs_to_float;
531 else
532 p->scaleFac = FL(1.0);
533
534 csound->RegisterDeinitCallback(csound, p, fouta_flush_callback);
535 return OK;
536 }
537
538
koutfile(CSOUND * csound,KOUTFILE * p)539 static int32_t koutfile(CSOUND *csound, KOUTFILE *p)
540 {
541 int32_t i, k;
542 int32_t nargs = p->nargs;
543 MYFLT *buf = (MYFLT *) p->buf.auxp;
544
545 for (i = 0, k = p->buf_pos; i < nargs; i++)
546 buf[k++] = p->argums[i][0] * p->scaleFac;
547 p->buf_pos = k;
548 if (p->buf_pos >= p->guard_pos) {
549 //#ifndef USE_DOUBLE
550 //sf_write_float(p->f.sf, buf, p->buf_pos);
551 //#else
552 //sf_write_double(p->f.sf, buf, p->buf_pos);
553 //#endif
554 if (p->f.async==1)
555 csound->WriteAsync(csound, p->f.fd, buf, p->buf_pos);
556 else sf_write_MYFLT(p->f.sf, buf, p->buf_pos);
557 p->buf_pos = 0;
558 }
559 return OK;
560 }
561
koutfile_set_(CSOUND * csound,KOUTFILE * p,int32_t istring)562 static int32_t koutfile_set_(CSOUND *csound, KOUTFILE *p, int32_t istring)
563 {
564 SF_INFO sfinfo;
565 int32_t format_, n, buf_reqd;
566
567 memset(&sfinfo, 0, sizeof(SF_INFO));
568 p->nargs = p->INOCOUNT - 2;
569 p->buf_pos = 0;
570
571 if (CS_KSMPS >= 512)
572 p->guard_pos = CS_KSMPS * p->nargs;
573 else
574 p->guard_pos = 512 * p->nargs;
575
576 sfinfo.channels = p->nargs;
577 sfinfo.samplerate = (int32_t) MYFLT2LRND(CS_EKR);
578 format_ = (int32_t) MYFLT2LRND(*p->iflag);
579 if ((uint32_t) format_ >= 10ul)
580 sfinfo.format = SF_FORMAT_PCM_16 | SF_FORMAT_RAW;
581 else
582 sfinfo.format = fout_format_table[format_] | SF_FORMAT_RAW;
583
584 if (CS_KSMPS >= 512)
585 buf_reqd = CS_KSMPS * p->nargs;
586 else
587 buf_reqd = (1 + (int32_t)(512 / CS_KSMPS)) * CS_KSMPS * p->nargs;
588 if (p->buf.auxp == NULL || p->buf.size < buf_reqd*sizeof(MYFLT)) {
589 csound->AuxAlloc(csound, sizeof(MYFLT)*buf_reqd, &p->buf);
590 }
591 p->f.bufsize = p->buf.size;
592 n = fout_open_file(csound, &(p->f), NULL, CSFILE_SND_W,
593 p->fname, istring, &sfinfo, 0);
594 if (UNLIKELY(n < 0))
595 return NOTOK;
596
597 if (((STDOPCOD_GLOBALS*) csound->stdOp_Env)->file_opened[n].do_scale)
598 p->scaleFac = csound->dbfs_to_float;
599 else
600 p->scaleFac = FL(1.0);
601
602 csound->RegisterDeinitCallback(csound, p, fout_flush_callback);
603 return OK;
604 }
605
koutfile_set(CSOUND * csound,KOUTFILE * p)606 static int32_t koutfile_set(CSOUND *csound, KOUTFILE *p){
607 return koutfile_set_(csound,p,0);
608 }
609
koutfile_set_S(CSOUND * csound,KOUTFILE * p)610 static int32_t koutfile_set_S(CSOUND *csound, KOUTFILE *p){
611 return koutfile_set_(csound,p,1);
612 }
613
614
615 /*--------------*/
616
617 /* syntax:
618 ihandle fiopen "filename" [, iascii]
619 */
620
621 /* open a file and return its handle */
622 /* the handle is simply a stack index */
623
fiopen_(CSOUND * csound,FIOPEN * p,int32_t istring)624 static int32_t fiopen_(CSOUND *csound, FIOPEN *p, int32_t istring)
625 {
626 char *omodes[] = {"w", "r", "wb", "rb"};
627 FILE *rfp = (FILE*) NULL;
628 int32_t idx = (int32_t) MYFLT2LRND(*p->iascii), n;
629
630 if (idx < 0 || idx > 3)
631 idx = 0;
632 n = fout_open_file(csound, (FOUT_FILE*) NULL, &rfp, CSFILE_STD,
633 p->fname, istring, omodes[idx], 1);
634 if (UNLIKELY(n < 0))
635 return NOTOK;
636 if (idx > 1)
637 setbuf(rfp, NULL);
638 *p->ihandle = (MYFLT) n;
639
640 return OK;
641 }
642
fiopen(CSOUND * csound,FIOPEN * p)643 static int32_t fiopen(CSOUND *csound, FIOPEN *p){
644 return fiopen_(csound, p, 0);
645 }
646
fiopen_S(CSOUND * csound,FIOPEN * p)647 static int32_t fiopen_S(CSOUND *csound, FIOPEN *p){
648 return fiopen_(csound, p, 1);
649 }
650
ficlose_opcode_(CSOUND * csound,FICLOSE * p,int32_t istring)651 static int32_t ficlose_opcode_(CSOUND *csound, FICLOSE *p, int32_t istring)
652 {
653 STDOPCOD_GLOBALS *pp = (STDOPCOD_GLOBALS*) csound->stdOp_Env;
654 int32_t idx = -1;
655
656 if (istring || csound->ISSTRCOD(*(p->iFile))) {
657 char *fname = NULL;
658 if (istring) fname = cs_strdup(csound, ((STRINGDAT *)p->iFile)->data);
659 else if (csound->ISSTRCOD(*(p->iFile)))
660 fname = cs_strdup(csound, get_arg_string(csound, *p->iFile));
661 if (UNLIKELY(fname == NULL || fname[0] == (char) 0)) {
662 if (fname != NULL) csound->Free(csound, fname);
663 return csound->InitError(csound, Str("invalid file name"));
664 }
665 for (idx = 0; idx <= pp->file_num; idx++) {
666 if (pp->file_opened[idx].fd != NULL &&
667 pp->file_opened[idx].name != (char*) NULL &&
668 strcmp(fname, pp->file_opened[idx].name) == 0)
669 break;
670 }
671 if (UNLIKELY(idx > pp->file_num)) {
672 csound->Warning(csound, Str("cannot close '%s': "
673 "not found in list of open files"), fname);
674 csound->Free(csound, fname);
675 return OK;
676 }
677 csound->Free(csound, fname);
678 }
679 else {
680 idx = (int32_t) MYFLT2LRND(*(p->iFile));
681 if (UNLIKELY(idx < 0 || idx > pp->file_num ||
682 pp->file_opened[idx].fd == NULL)) {
683 csound->Warning(csound,
684 Str("cannot close file #%d: not a valid handle"), idx);
685 return OK;
686 }
687 }
688 if (pp->file_opened[idx].refCount) {
689 if (UNLIKELY(!(pp->file_opened[idx].refCount & 0x80000000U))) {
690 pp->file_opened[idx].refCount |= 0x80000000U;
691 csound->Warning(csound, Str("file #%d (%s) is in use, will be closed "
692 "when released"),
693 idx, pp->file_opened[idx].name);
694 }
695 }
696 else {
697 FOUT_FILE tmp;
698 pp->file_opened[idx].refCount = 1;
699 /*ref count was set to 0x80000001U, but it needs to be 1 */
700 memset(&tmp, 0, sizeof(FOUT_FILE));
701 tmp.h.insdshead = p->h.insdshead;
702 tmp.idx = idx + 1;
703 fout_deinit_callback(csound, (void*) &tmp);
704 }
705
706 return OK;
707 }
708
ficlose_opcode(CSOUND * csound,FICLOSE * p)709 static int32_t ficlose_opcode(CSOUND *csound, FICLOSE *p){
710 return ficlose_opcode_(csound,p,0);
711 }
712
ficlose_opcode_S(CSOUND * csound,FICLOSE * p)713 static int32_t ficlose_opcode_S(CSOUND *csound, FICLOSE *p){
714 return ficlose_opcode_(csound,p,1);
715 }
716
717 /* syntax:
718 fouti ihandle, iascii, iflag, iarg1 [, iarg2, ...., iargN]
719 */
720
ioutfile_set(CSOUND * csound,IOUTFILE * p)721 static int32_t ioutfile_set(CSOUND *csound, IOUTFILE *p)
722 {
723 STDOPCOD_GLOBALS *pp = (STDOPCOD_GLOBALS*) csound->stdOp_Env;
724 MYFLT **args = p->argums;
725 FILE *rfil;
726 uint32_t j;
727 int32_t n = (int32_t) MYFLT2LRND(*p->ihandle);
728
729 if (UNLIKELY(n < 0 || n > pp->file_num))
730 return csound->InitError(csound, Str("fouti: invalid file handle"));
731 rfil = pp->file_opened[n].raw;
732 if (UNLIKELY(rfil == NULL))
733 return csound->InitError(csound, Str("fouti: invalid file handle"));
734 if (*p->iascii == 0) { /* ascii format */
735 switch ((int32_t) MYFLT2LRND(*p->iflag)) {
736 case 1:
737 { /* with prefix (i-statement, p1, p2 and p3) */
738 int32_t p1 = (int32_t) p->h.insdshead->p1.value;
739 double p2 = (double) CS_KCNT * CS_ONEDKR;
740 double p3 = p->h.insdshead->p3.value;
741 if (p3 > FL(0.0))
742 fprintf(rfil, "i %i %f %f ", p1, p2, p3);
743 else
744 fprintf(rfil, "i %i %f . ", p1, p2);
745 }
746 break;
747 case 2: /* with prefix (start at 0 time) */
748 if (pp->fout_kreset == 0)
749 pp->fout_kreset = CS_KCNT;
750 {
751 int32_t p1 = (int32_t) p->h.insdshead->p1.value;
752 double p2 = (double) (CS_KCNT - pp->fout_kreset)
753 * CS_ONEDKR;
754 double p3 = p->h.insdshead->p3.value;
755 if (p3 > FL(0.0))
756 fprintf(rfil, "i %i %f %f ", p1, p2, p3);
757 else
758 fprintf(rfil, "i %i %f . ", p1, p2);
759 }
760 break;
761 case 3: /* reset */
762 pp->fout_kreset = 0;
763 return OK;
764 }
765 for (j = 0; j < p->INOCOUNT - 3; j++) {
766 fprintf(rfil, " %f", (double) *args[j]);
767 }
768 putc('\n', rfil);
769 }
770 else { /* binary format */
771 for (j = 0; j < p->INOCOUNT - 3; j++) {
772 if (UNLIKELY(1!=fwrite(args[j], sizeof(MYFLT), 1, rfil))) return NOTOK;
773 }
774 }
775 return OK;
776 }
777
778
779
ioutfile_set_r(CSOUND * csound,IOUTFILE_R * p)780 static int32_t ioutfile_set_r(CSOUND *csound, IOUTFILE_R *p)
781 {
782 STDOPCOD_GLOBALS *pp = (STDOPCOD_GLOBALS*) csound->stdOp_Env;
783 if (p->h.insdshead->xtratim < 1)
784 p->h.insdshead->xtratim = 1;
785 p->counter = CS_KCNT;
786 p->done = 1;
787 if (*p->iflag == 2 && pp->fout_kreset == 0)
788 pp->fout_kreset = CS_KCNT;
789 return OK;
790 }
791
ioutfile_r(CSOUND * csound,IOUTFILE_R * p)792 static int32_t ioutfile_r(CSOUND *csound, IOUTFILE_R *p)
793 {
794 STDOPCOD_GLOBALS *pp;
795 MYFLT **args;
796 FILE *rfil;
797 uint32_t j;
798 int32_t n;
799
800 if (!p->h.insdshead->relesing || !p->done)
801 return OK;
802
803 pp = (STDOPCOD_GLOBALS*) csound->stdOp_Env;
804 args = p->argums;
805 n = (int32_t) MYFLT2LRND(*p->ihandle);
806 if (UNLIKELY(n < 0 || n > pp->file_num))
807 return csound->InitError(csound, Str("fouti: invalid file handle"));
808 rfil = pp->file_opened[n].raw;
809 if (UNLIKELY(rfil == NULL))
810 return csound->InitError(csound, Str("fouti: invalid file handle"));
811 if (*p->iascii == 0) { /* ascii format */
812 switch ((int32_t) MYFLT2LRND(*p->iflag)) {
813 case 1:
814 { /* whith prefix (i-statement, p1, p2 and p3) */
815 int32_t p1 = (int32_t) p->h.insdshead->p1.value;
816 double p2 = p->counter * CS_ONEDKR;
817 double p3 = (double) (CS_KCNT - p->counter)
818 * CS_ONEDKR;
819 fprintf(rfil, "i %i %f %f ", p1, p2, p3);
820 }
821 break;
822 case 2: /* with prefix (start at 0 time) */
823 {
824 int32_t p1 = (int32_t) p->h.insdshead->p1.value;
825 double p2 = (p->counter - pp->fout_kreset) * CS_ONEDKR;
826 double p3 = (double) (CS_KCNT - p->counter)
827 * CS_ONEDKR;
828 fprintf(rfil, "i %i %f %f ", p1, p2, p3);
829 }
830 break;
831 case 3: /* reset */
832 pp->fout_kreset = 0;
833 return OK;
834 }
835 for (j = 0; j < p->INOCOUNT - 3; j++) {
836 fprintf(rfil, " %f", (double) *args[j]);
837 }
838 putc('\n', rfil);
839 }
840 else { /* binary format */
841 for (j = 0; j < p->INOCOUNT - 3; j++) {
842 if (UNLIKELY(1!=fwrite(args[j], sizeof(MYFLT), 1, rfil))) return NOTOK;
843 }
844 }
845 p->done = 0;
846
847 return OK;
848 }
849
850 /*----------------------------------*/
851
infile_set_(CSOUND * csound,INFILE * p,int32_t istring)852 static int32_t infile_set_(CSOUND *csound, INFILE *p, int32_t istring)
853 {
854 SF_INFO sfinfo;
855 int32_t n, buf_reqd;
856 p->nargs = p->INOCOUNT - 3;
857 p->currpos = MYFLT2LRND(*p->iskpfrms);
858 p->flag = 1;
859 memset(&sfinfo, 0, sizeof(SF_INFO));
860 sfinfo.samplerate = (int32_t) MYFLT2LRND(CS_ESR);
861 /* Following code is seriously broken*/
862 if ((int32_t) MYFLT2LRND(*p->iflag) == -2)
863 sfinfo.format = FORMAT2SF(AE_FLOAT) | TYPE2SF(TYP_RAW);
864 else if ((int32_t) MYFLT2LRND(*p->iflag) == -1)
865 sfinfo.format = FORMAT2SF(AE_SHORT) | TYPE2SF(TYP_RAW);
866 else
867 sfinfo.format = 0;
868 sfinfo.channels = p->INOCOUNT - 3;
869 if (CS_KSMPS >= 512)
870 p->frames = CS_KSMPS;
871 else
872 p->frames = (int32_t)(512 / CS_KSMPS) * CS_KSMPS;
873
874 if (CS_KSMPS >= 512)
875 buf_reqd = CS_KSMPS * sfinfo.channels;
876 else
877 buf_reqd = (1 + (int32_t)(512 / CS_KSMPS)) * CS_KSMPS * p->nargs;
878 if (p->buf.auxp == NULL || p->buf.size < buf_reqd*sizeof(MYFLT)) {
879 csound->AuxAlloc(csound, sizeof(MYFLT)*buf_reqd, &p->buf);
880 }
881 p->f.bufsize = p->buf.size;
882 n = fout_open_file(csound, &(p->f), NULL, CSFILE_SND_R,
883 p->fname, istring, &sfinfo, 0);
884 if (UNLIKELY(n < 0))
885 return NOTOK;
886
887 if (((STDOPCOD_GLOBALS*) csound->stdOp_Env)->file_opened[n].do_scale)
888 p->scaleFac = csound->e0dbfs;
889 else
890 p->scaleFac = FL(1.0);
891
892
893
894 p->guard_pos = p->frames * p->nargs;
895 p->buf_pos = p->guard_pos;
896
897 if (p->f.async == 1)
898 csound->FSeekAsync(csound,p->f.fd, p->currpos*p->f.nchnls, SEEK_SET);
899
900 return OK;
901 }
902
infile_set(CSOUND * csound,INFILE * p)903 static int32_t infile_set(CSOUND *csound, INFILE *p){
904 return infile_set_(csound,p,0);
905 }
906
infile_set_S(CSOUND * csound,INFILE * p)907 static int32_t infile_set_S(CSOUND *csound, INFILE *p){
908 return infile_set_(csound,p,1);
909 }
910
911 #include "arrays.h"
912
infile_set_A(CSOUND * csound,INFILEA * p)913 static int32_t infile_set_A(CSOUND *csound, INFILEA *p)
914 {
915 SF_INFO sfinfo;
916 int32_t n, buf_reqd;
917 p->currpos = MYFLT2LRND(*p->iskpfrms);
918 p->flag = 1;
919 memset(&sfinfo, 0, sizeof(SF_INFO));
920 sfinfo.samplerate = (int32_t) MYFLT2LRND(CS_ESR);
921 if ((int32_t) MYFLT2LRND(*p->iflag) == -2)
922 sfinfo.format = FORMAT2SF(AE_FLOAT) | TYPE2SF(TYP_RAW);
923 else if ((int32_t) MYFLT2LRND(*p->iflag) == -1)
924 sfinfo.format = FORMAT2SF(AE_SHORT) | TYPE2SF(TYP_RAW);
925 else
926 sfinfo.format = 0;
927 sfinfo.channels = p->INOCOUNT - 3;
928 if (CS_KSMPS >= 512)
929 p->frames = CS_KSMPS;
930 else
931 p->frames = (int32_t)(512 / CS_KSMPS) * CS_KSMPS;
932 p->chn = sfinfo.channels;
933 if (CS_KSMPS >= 512)
934 buf_reqd = CS_KSMPS * sfinfo.channels;
935 else
936 buf_reqd = (1 + (int32_t)(512 / CS_KSMPS)) * CS_KSMPS * sfinfo.channels;
937 if (p->buf.auxp == NULL || p->buf.size < buf_reqd*sizeof(MYFLT)) {
938 csound->AuxAlloc(csound, sizeof(MYFLT)*buf_reqd, &p->buf);
939 }
940 p->f.bufsize = p->buf.size;
941 n = fout_open_file(csound, &(p->f), NULL, CSFILE_SND_R,
942 p->fname, 1, &sfinfo, 0);
943 if (UNLIKELY(n < 0))
944 return NOTOK;
945
946 if (((STDOPCOD_GLOBALS*) csound->stdOp_Env)->file_opened[n].do_scale)
947 p->scaleFac = csound->e0dbfs;
948 else
949 p->scaleFac = FL(1.0);
950
951 p->guard_pos = p->frames * p->chn;
952 p->buf_pos = p->guard_pos;
953
954 if (p->f.async == 1)
955 csound->FSeekAsync(csound,p->f.fd, p->currpos*p->f.nchnls, SEEK_SET);
956
957 tabinit(csound, p->tabout, p->chn);
958 return OK;
959 }
960
infile_act(CSOUND * csound,INFILE * p)961 static int32_t infile_act(CSOUND *csound, INFILE *p)
962 {
963 uint32_t offset = p->h.insdshead->ksmps_offset;
964 uint32_t early = p->h.insdshead->ksmps_no_end;
965 uint32_t i, k, j = offset;
966 uint32_t nsmps = CS_KSMPS, ksmps, nargs = p->nargs;
967 MYFLT *buf = (MYFLT *) p->buf.auxp;
968
969 ksmps = nsmps;
970 if (UNLIKELY(offset))
971 for (i = 0; i < nargs; i++)
972 memset(p->argums[i], '\0', offset*sizeof(MYFLT));
973 if (UNLIKELY(early)) {
974 nsmps -= early;
975 for (i = 0; i < nargs; i++)
976 memset(&p->argums[i][nsmps], '\0', early*sizeof(MYFLT));
977 }
978 if (p->flag) {
979 if (p->buf_pos >= p->guard_pos) {
980 if (UNLIKELY(p->f.async == 0)) {
981 sf_seek(p->f.sf, p->currpos*p->f.nchnls, SEEK_SET);
982 p->remain = (uint32_t) sf_read_MYFLT(p->f.sf, (MYFLT*) buf,
983 p->frames*p->f.nchnls);
984 p->remain /= p->f.nchnls;
985 } else {
986 p->remain = csoundReadAsync(csound,p->f.fd,(MYFLT *)buf,
987 p->frames*p->f.nchnls);
988 p->remain /= p->f.nchnls;
989 }
990 p->currpos += p->frames;
991 p->buf_pos = 0;
992 }
993 if (p->remain < nsmps)
994 nsmps = p->remain;
995 for (k = (uint32_t)p->buf_pos; j < nsmps; j++)
996 for (i = 0; i < nargs; i++)
997 p->argums[i][j] = buf[k++] * p->scaleFac;
998 p->buf_pos = k;
999 p->remain -= ksmps;
1000 if (p->remain <= 0 && p->buf_pos < p->guard_pos) {
1001 p->flag = 0;
1002 for (; j < ksmps; j++)
1003 for (i = 0; i < nargs; i++)
1004 p->argums[i][j] = FL(0.0);
1005 }
1006 return OK;
1007 }
1008 for ( ; j < ksmps; j++)
1009 for (i = 0; i < nargs; i++)
1010 p->argums[i][j] = FL(0.0);
1011
1012 return OK;
1013 }
1014
infile_arr(CSOUND * csound,INFILEA * p)1015 static int32_t infile_arr(CSOUND *csound, INFILEA *p)
1016 {
1017 uint32_t offset = p->h.insdshead->ksmps_offset;
1018 uint32_t early = p->h.insdshead->ksmps_no_end;
1019 uint32_t i, k, j = offset;
1020 uint32_t nsmps = CS_KSMPS, ksmps, chn = p->chn;
1021 MYFLT *buf = (MYFLT *) p->buf.auxp;
1022 MYFLT *data = p->tabout->data;
1023
1024 ksmps = nsmps;
1025 if (UNLIKELY(offset))
1026 for (i = 0; i < chn; i++)
1027 memset(&data[i*chn], '\0', offset*sizeof(MYFLT));
1028 if (UNLIKELY(early)) {
1029 nsmps -= early;
1030 for (i = 0; i < chn; i++)
1031 memset(&data[i*chn+nsmps], '\0', early*sizeof(MYFLT));
1032 }
1033 if (p->flag) {
1034 if (p->buf_pos >= p->guard_pos) {
1035 if (UNLIKELY(p->f.async == 0)) {
1036 sf_seek(p->f.sf, p->currpos*p->f.nchnls, SEEK_SET);
1037 p->remain = (uint32_t) sf_read_MYFLT(p->f.sf, (MYFLT*) buf,
1038 p->frames*p->f.nchnls);
1039 p->remain /= p->f.nchnls;
1040 } else {
1041 p->remain = csoundReadAsync(csound,p->f.fd,(MYFLT *)buf,
1042 p->frames*p->f.nchnls);
1043 p->remain /= p->f.nchnls;
1044 }
1045 p->currpos += p->frames;
1046 p->buf_pos = 0;
1047 }
1048 if (p->remain < nsmps)
1049 nsmps = p->remain;
1050 for (k = (uint32_t)p->buf_pos; j < nsmps; j++)
1051 for (i = 0; i < chn; i++)
1052 data[i*chn+j] = buf[k++] * p->scaleFac;
1053 p->buf_pos = k;
1054 p->remain -= ksmps;
1055 if (p->remain <= 0 && p->buf_pos < p->guard_pos) {
1056 p->flag = 0;
1057 for (; j < ksmps; j++)
1058 for (i = 0; i < chn; i++)
1059 data[i*chn+j] = FL(0.0);
1060 }
1061 return OK;
1062 }
1063 for ( ; j < ksmps; j++)
1064 for (i = 0; i < chn; i++)
1065 data[i*chn+j] = FL(0.0);
1066
1067 return OK;
1068 }
1069
1070 /* ---------------------------- */
1071
kinfile_set_(CSOUND * csound,KINFILE * p,int32_t istring)1072 static int32_t kinfile_set_(CSOUND *csound, KINFILE *p, int32_t istring)
1073 {
1074 SF_INFO sfinfo;
1075 int32_t n, buf_reqd;
1076
1077 memset(&sfinfo, 0, sizeof(SF_INFO));
1078 sfinfo.samplerate = (int32_t) MYFLT2LRND(CS_EKR);
1079 if ((int32_t) MYFLT2LRND(*p->iflag) == -2)
1080 sfinfo.format = FORMAT2SF(AE_FLOAT) | TYPE2SF(TYP_RAW);
1081 else if ((int32_t) MYFLT2LRND(*p->iflag) == -1)
1082 sfinfo.format = FORMAT2SF(AE_SHORT) | TYPE2SF(TYP_RAW);
1083 else
1084 sfinfo.format = 0;
1085 sfinfo.channels = p->INOCOUNT - 3;
1086
1087 p->nargs = p->INOCOUNT - 3;
1088 p->currpos = MYFLT2LRND(*p->iskpfrms);
1089 p->flag = 1;
1090
1091 if (CS_KSMPS >= 512)
1092 p->frames = CS_KSMPS;
1093 else
1094 p->frames = (int32_t)(512 / CS_KSMPS) * CS_KSMPS;
1095
1096 if (CS_KSMPS >= 512)
1097 buf_reqd = CS_KSMPS * sfinfo.channels;
1098 else
1099 buf_reqd = (1 + (int32_t)(512 / CS_KSMPS)) * CS_KSMPS * p->nargs;
1100 if (p->buf.auxp == NULL || p->buf.size < buf_reqd*sizeof(MYFLT)) {
1101 csound->AuxAlloc(csound, sizeof(MYFLT)*buf_reqd, &p->buf);
1102 }
1103 p->f.bufsize = p->buf.size;
1104 n = fout_open_file(csound, &(p->f), NULL, CSFILE_SND_R,
1105 p->fname, istring, &sfinfo, 0);
1106 if (UNLIKELY(n < 0))
1107 return NOTOK;
1108
1109 if (((STDOPCOD_GLOBALS*) csound->stdOp_Env)->file_opened[n].do_scale)
1110 p->scaleFac = csound->e0dbfs;
1111 else
1112 p->scaleFac = FL(1.0);
1113
1114 p->guard_pos = p->frames * p->nargs;
1115 p->buf_pos = p->guard_pos;
1116
1117 if (p->f.async == 1)
1118 csound->FSeekAsync(csound,p->f.fd, p->currpos*p->f.nchnls, SEEK_SET);
1119
1120 return OK;
1121 }
1122
kinfile_set(CSOUND * csound,KINFILE * p)1123 static int32_t kinfile_set(CSOUND *csound, KINFILE *p){
1124 return kinfile_set_(csound,p,0);
1125 }
1126
kinfile_set_S(CSOUND * csound,KINFILE * p)1127 static int32_t kinfile_set_S(CSOUND *csound, KINFILE *p){
1128 return kinfile_set_(csound,p,1);
1129 }
1130
1131
kinfile(CSOUND * csound,KINFILE * p)1132 static int32_t kinfile(CSOUND *csound, KINFILE *p)
1133 {
1134 int32_t i, k;
1135 int32_t nargs = p->nargs;
1136 MYFLT *buf = (MYFLT *) p->buf.auxp;
1137
1138 if (p->flag) {
1139 if (p->buf_pos >= p->guard_pos) {
1140 if (UNLIKELY(p->f.async == 0)) {
1141 sf_seek(p->f.sf, p->currpos*p->f.nchnls, SEEK_SET);
1142 p->remain = (uint32_t) sf_read_MYFLT(p->f.sf, (MYFLT*) buf,
1143 p->frames*p->f.nchnls);
1144 p->remain /= p->f.nchnls;
1145 } else {
1146 p->remain = csoundReadAsync(csound,p->f.fd,(MYFLT *)buf,
1147 p->frames*p->f.nchnls);
1148 p->remain /= p->f.nchnls;
1149 }
1150 p->currpos += p->frames;
1151 p->buf_pos = 0;
1152 }
1153 if (p->remain > 0) {
1154 for (i = 0, k = p->buf_pos; i < nargs; i++)
1155 p->argums[i][0] = buf[k++] * p->scaleFac;
1156 p->buf_pos = k;
1157 p->remain--;
1158 return OK;
1159 }
1160 p->flag = 0;
1161 }
1162 for (i = 0; i < nargs; i++)
1163 p->argums[i][0] = FL(0.0);
1164 return OK;
1165 }
1166
i_infile_(CSOUND * csound,I_INFILE * p,int32_t istring)1167 static int32_t i_infile_(CSOUND *csound, I_INFILE *p, int32_t istring)
1168 {
1169 int32_t j, n, nargs;
1170 FILE *fp = NULL;
1171 MYFLT **args = p->argums;
1172 char *omodes[] = {"r", "r", "rb"};
1173 int32_t idx = (int32_t) MYFLT2LRND(*p->iflag);
1174
1175 if (UNLIKELY(idx < 0 || idx > 2))
1176 idx = 0;
1177 n = fout_open_file(csound, (FOUT_FILE*) NULL, &fp, CSFILE_STD,
1178 p->fname, istring, omodes[idx], 0);
1179 if (UNLIKELY(n < 0))
1180 return NOTOK;
1181
1182 nargs = p->INOCOUNT - 3;
1183 switch ((int32_t) MYFLT2LRND(*p->iflag)) {
1184 case 0: /* ascii file with loop */
1185 {
1186 char cf[64], *cfp;
1187 int32_t cc;
1188 newcycle:
1189 for (j = 0; j < nargs; j++) {
1190 cfp = cf;
1191 while ((*cfp = cc = getc(fp)) == 'i' || isspace(*cfp));
1192 if (cc == EOF) {
1193 fseek(fp, 0, SEEK_SET);
1194 goto newcycle;
1195 }
1196 while (isdigit(*cfp) || *cfp == '.' || *cfp == '+' || *cfp == '-') {
1197 *(++cfp) = (char)(cc = getc(fp));
1198 }
1199 *++cfp = '\0'; /* Must terminate string */
1200 *(args[j]) = (MYFLT) atof(cf);
1201 if (cc == EOF) {
1202 fseek(fp, 0, SEEK_SET);
1203 break;
1204 }
1205 }
1206 }
1207 break;
1208 case 1: /* ascii file without loop */
1209 {
1210 char cf[64], *cfp;
1211 int32_t cc;
1212 for (j = 0; j < nargs; j++) {
1213 cfp = cf;
1214 while ((*cfp = cc = getc(fp)) == 'i' || isspace(*cfp));
1215 if (cc == EOF) {
1216 *(args[j]) = FL(0.0);
1217 break;
1218 }
1219 while (isdigit(*cfp) || *cfp == '.' || *cfp == '+' || *cfp == '-') {
1220 *(++cfp) = cc = getc(fp);
1221 }
1222 *++cfp = '\0'; /* Must terminate */
1223 *(args[j]) = (MYFLT) atof (cf);
1224 if (cc == EOF) {
1225 *(args[j]) = FL(0.0);
1226 break;
1227 }
1228 }
1229 }
1230 break;
1231 case 2: /* binary floats without loop */
1232 if (fseek(fp, p->currpos * sizeof(float) * nargs, SEEK_SET)<0) return NOTOK;
1233 p->currpos++;
1234 for (j = 0; j < nargs; j++) {
1235 if (1 == fread(args[j], sizeof(float), 1, fp));
1236 else {
1237 p->flag = 0;
1238 *(args[j]) = FL(0.0);
1239 }
1240 }
1241 break;
1242 }
1243 return OK;
1244 }
1245
i_infile(CSOUND * csound,I_INFILE * p)1246 static int32_t i_infile(CSOUND *csound, I_INFILE *p){
1247 return i_infile_(csound,p,0);
1248 }
1249
i_infile_S(CSOUND * csound,I_INFILE * p)1250 static int32_t i_infile_S(CSOUND *csound, I_INFILE *p){
1251 return i_infile_(csound,p,1);
1252 }
1253
1254
1255 /*---------------------------*/
1256
incr(CSOUND * csound,INCR * p)1257 static int32_t incr(CSOUND *csound, INCR *p)
1258 {
1259 IGN(csound);
1260 MYFLT *avar = p->avar, *aincr = p->aincr;
1261 uint32_t offset = p->h.insdshead->ksmps_offset;
1262 uint32_t early = p->h.insdshead->ksmps_no_end;
1263 uint32_t n, nsmps = CS_KSMPS;
1264
1265 if (UNLIKELY(early)) nsmps -= early;
1266 for (n = offset; n < nsmps; n++)
1267 avar[n] += aincr[n];
1268 return OK;
1269 }
1270
clear(CSOUND * csound,CLEARS * p)1271 static int32_t clear(CSOUND *csound, CLEARS *p)
1272 {
1273 IGN(csound);
1274 uint32_t nsmps = CS_KSMPS, j;
1275
1276 for (j = 0; j < p->INOCOUNT; j++) {
1277 memset(p->argums[j], 0, sizeof(MYFLT)*nsmps);
1278 }
1279 return OK;
1280 }
1281
1282 /*---------------------------------*/
1283 /* formatted output to a text file */
1284
fprintf_set_(CSOUND * csound,FPRINTF * p,int32_t istring)1285 static int32_t fprintf_set_(CSOUND *csound, FPRINTF *p, int32_t istring)
1286 {
1287 int32_t n;
1288 char *sarg = (char*) p->fmt->data;
1289 char *sdest = p->txtstring;
1290
1291 memset(p->txtstring, 0, 8192); /* Nasty to have exposed constant in code */
1292
1293 if (p->h.opadr != (SUBR) NULL) /* fprintks */
1294 n = fout_open_file(csound, &(p->f), NULL, CSFILE_STD,
1295 p->fname, istring, "w", 1);
1296 else /* fprints */
1297 n = fout_open_file(csound, (FOUT_FILE*) NULL, &(p->f.f), CSFILE_STD,
1298 p->fname, istring, "w", 1);
1299 if (UNLIKELY(n < 0))
1300 return NOTOK;
1301 //setvbuf(p->f.f, (char*)NULL, _IOLBF, BUFSIZ); /* Seems a good option */
1302 /* Copy the string to the storage place in PRINTKS.
1303 *
1304 * We will look out for certain special codes and write special
1305 * bytes directly to the string.
1306 *
1307 * There is probably a more elegant way of doing this, then using
1308 * the look flag. I could use goto - but I would rather not. */
1309 /* This is really a if then else if...
1310 * construct and is currently grotty -- JPff */
1311 do {
1312 char temp = *sarg++;
1313 char tempn = *sarg--;
1314 /* Look for a single caret and insert an escape char. */
1315 if ((temp == '^') && (tempn != '^')) {
1316 *sdest++ = 0x1B; /* ESC */
1317 }
1318 /* Look for a double caret and insert a single caret
1319 - stepping forward one */
1320 else if ((temp == '^') && (tempn == '^')) {
1321 *sdest++ = '^';
1322 sarg++;
1323 }
1324 /* Look for a single tilde and insert an escape followed by a '['.
1325 * ESC[ is the escape sequence for ANSI consoles */
1326 else if ((temp == '~') && (tempn != '~')) {
1327 *sdest++ = 0x1B; /* ESC */
1328 *sdest++ = '[';
1329 }
1330 /* Look for a double tilde and insert a tilde caret
1331 - stepping forward one. */
1332 else if ((temp == '~') && (tempn == '~')) {
1333 *sdest++ = '~';
1334 sarg++;
1335 }
1336 /* Look for \n, \N etc */
1337 else if (temp == '\\') {
1338 switch (tempn) {
1339 case 'r': case 'R':
1340 *sdest++ = '\r';
1341 sarg++;
1342 break;
1343 case 'n': case 'N':
1344 *sdest++ = '\n';
1345 sarg++;
1346 break;
1347 case 't': case 'T':
1348 *sdest++ = '\t';
1349 sarg++;
1350 break;
1351 case 'a': case 'A':
1352 *sdest++ = '\a';
1353 sarg++;
1354 break;
1355 case 'b': case 'B':
1356 *sdest++ = '\b';
1357 sarg++;
1358 break;
1359 case '\\':
1360 *sdest++ = '\\';
1361 sarg++;
1362 break;
1363 default:
1364 *sdest++ = tempn;
1365 sarg++;
1366 break;
1367 }
1368 }
1369 else if (temp == '%') {
1370 /* an extra option to specify tab and return as %t and %r */
1371 switch (tempn) {
1372 case 'r': case 'R':
1373 *sdest++ = '\r';
1374 sarg++;
1375 break;
1376 case 'n': case 'N':
1377 *sdest++ = '\n';
1378 sarg++;
1379 break;
1380 case 't': case 'T':
1381 *sdest++ = '\t';
1382 sarg++;
1383 break;
1384 case '!': /* and a ';' */
1385 *sdest++ = ';';
1386 sarg++;
1387 break;
1388 default:
1389 *sdest++ = temp;
1390 break;
1391 }
1392 }
1393 else {
1394 /* If none of these match, then copy the character directly
1395 * and try again. */
1396 *sdest++ = temp;
1397 }
1398 /* Increment pointer and process next character until end of string. */
1399 } while (*++sarg != 0);
1400 return OK;
1401 }
1402
fprintf_set(CSOUND * csound,FPRINTF * p)1403 static int32_t fprintf_set(CSOUND *csound, FPRINTF *p){
1404 return fprintf_set_(csound,p,0);
1405 }
1406
fprintf_set_S(CSOUND * csound,FPRINTF * p)1407 static int32_t fprintf_set_S(CSOUND *csound, FPRINTF *p){
1408 return fprintf_set_(csound,p,1);
1409 }
1410
1411
1412
1413 /* perform a sprintf-style format -- matt ingalls */
sprints1(char * outstring,char * fmt,MYFLT ** kvals,int32 numVals)1414 void sprints1(char *outstring, char *fmt, MYFLT **kvals, int32 numVals)
1415 {
1416 char strseg[8192];
1417 int32_t len = 8192;
1418 int32_t i = 0, j = 0;
1419 char *segwaiting = 0;
1420 while (*fmt) {
1421 if (*fmt == '%') {
1422 /* if already a segment waiting, then lets print it */
1423 if (segwaiting) {
1424 strseg[i] = '\0';
1425 switch (*segwaiting) {
1426 case '%':
1427 strNcpy(outstring, "%%", len);
1428 j--;
1429 break;
1430 case 'd':
1431 case 'i':
1432 case 'o':
1433 case 'x':
1434 case 'X':
1435 case 'u':
1436 case 'c':
1437 snprintf(outstring, len, strseg, (int32_t) MYFLT2LRND(*kvals[j]));
1438 break;
1439 case 'h':
1440 snprintf(outstring, len, strseg, (int16) MYFLT2LRND(*kvals[j]));
1441 break;
1442 case 'l':
1443 snprintf(outstring, len, strseg, (int32) MYFLT2LRND(*kvals[j]));
1444 break;
1445 case 's':
1446 snprintf(outstring, len, strseg, ((STRINGDAT*)(kvals[j]))->data);
1447 break;
1448 default:
1449 snprintf(outstring, len, strseg, *kvals[j]);
1450 break;
1451 }
1452 len -= strlen(outstring);
1453 outstring += strlen(outstring);
1454 i = 0;
1455 segwaiting = 0;
1456
1457 /* prevent potential problems */
1458 /* if user didnt give enough input params */
1459 if (j < numVals-1)
1460 j++;
1461 }
1462 /* copy the '%' */
1463 strseg[i++] = *fmt++;
1464
1465 /* find the format code */
1466 segwaiting = fmt;
1467 while (*segwaiting && !isalpha(*segwaiting) && !(*segwaiting=='%'))
1468 segwaiting++;
1469 }
1470 else
1471 strseg[i++] = *fmt++;
1472 }
1473
1474 if (i) {
1475 strseg[i] = '\0';
1476 if (segwaiting) {
1477 switch (*segwaiting) {
1478 case '%':
1479 strNcpy(outstring, "%%", len);
1480 j--;
1481 break;
1482 case 'd':
1483 case 'i':
1484 case 'o':
1485 case 'x':
1486 case 'X':
1487 case 'u':
1488 case 'c':
1489 snprintf(outstring, len, strseg, (int32_t) MYFLT2LRND(*kvals[j]));
1490 break;
1491 case 'h':
1492 snprintf(outstring, len, strseg, (int16) MYFLT2LRND(*kvals[j]));
1493 break;
1494 case 'l':
1495 snprintf(outstring, len, strseg, (int64_t) MYFLT2LRND(*kvals[j]));
1496 break;
1497
1498 default:
1499 snprintf(outstring, len, strseg, *kvals[j]);
1500 break;
1501 }
1502 }
1503 else
1504 snprintf(outstring, len, "%s", strseg);
1505 }
1506
1507 }
1508
fprintf_k(CSOUND * csound,FPRINTF * p)1509 static int32_t fprintf_k(CSOUND *csound, FPRINTF *p)
1510 {
1511 char string[8192];
1512
1513 (void) csound;
1514 sprints1(string, p->txtstring, p->argums, p->INOCOUNT - 2);
1515 fprintf(p->f.f, "%s", string);
1516 fflush(p->f.f);
1517 return OK;
1518 }
1519
1520 /* i-rate fprints */
fprintf_i(CSOUND * csound,FPRINTF * p)1521 static int32_t fprintf_i(CSOUND *csound, FPRINTF *p)
1522 {
1523 char string[8192];
1524
1525 if (UNLIKELY(fprintf_set(csound, p) != OK))
1526 return NOTOK;
1527 sprints1(string, p->txtstring, p->argums, p->INOCOUNT - 2);
1528 fprintf(p->f.f,"%s", string);
1529 fflush(p->f.f);
1530 return OK;
1531 }
1532
fprintf_i_S(CSOUND * csound,FPRINTF * p)1533 static int32_t fprintf_i_S(CSOUND *csound, FPRINTF *p)
1534 {
1535 char string[8192];
1536
1537 if (UNLIKELY(fprintf_set_S(csound, p) != OK))
1538 return NOTOK;
1539 sprints1(string, p->txtstring, p->argums, p->INOCOUNT - 2);
1540 fprintf(p->f.f, "%s", string);
1541 fflush(p->f.f);
1542 return OK;
1543 }
1544
1545 #define S(x) sizeof(x)
1546 static OENTRY localops[] = {
1547
1548 {"fprints", S(FPRINTF), 0, 1, "", "SSN",
1549 (SUBR) fprintf_i_S, (SUBR) NULL,(SUBR) NULL, NULL, },
1550 {"fprints.i", S(FPRINTF), 0, 1, "", "iSN",
1551 (SUBR) fprintf_i, (SUBR) NULL,(SUBR) NULL, NULL},
1552 { "fprintks", S(FPRINTF), WR, 3, "", "SSN",
1553 (SUBR) fprintf_set_S, (SUBR) fprintf_k, (SUBR) NULL, NULL,},
1554 { "fprintks.i", S(FPRINTF), WR, 3, "", "iSN",
1555 (SUBR) fprintf_set, (SUBR) fprintf_k, (SUBR) NULL, NULL},
1556 { "vincr", S(INCR), WI, 2, "", "aa",
1557 (SUBR) NULL, (SUBR) incr, NULL },
1558 { "clear", S(CLEARS), WI, 2, "", "y",
1559 (SUBR) NULL, (SUBR) clear, NULL},
1560 { "fout", S(OUTFILE), 0, 3, "", "Siy",
1561 (SUBR) outfile_set_S, (SUBR) outfile, NULL},
1562 { "fout.A", S(OUTFILEA), 0, 3, "", "Sia[]",
1563 (SUBR) outfile_set_A, (SUBR) outfile_array, NULL},
1564 /* { "fout.i", S(OUTFILE), 0, 3, "", "iiy", */
1565 /* (SUBR) outfile_set, (SUBR) outfile, NULL}, */
1566 { "foutk", S(KOUTFILE), 0, 3, "", "Siz",
1567 (SUBR) koutfile_set_S, (SUBR) koutfile, (SUBR) NULL, NULL },
1568 { "foutk.i", S(KOUTFILE), 0, 3, "", "iiz",
1569 (SUBR) koutfile_set, (SUBR) koutfile, (SUBR) NULL, NULL },
1570 { "fouti", S(IOUTFILE), 0, 1, "", "iiim",
1571 (SUBR) ioutfile_set, (SUBR) NULL, (SUBR) NULL, NULL },
1572 { "foutir", S(IOUTFILE_R), 0, 3, "", "iiim",
1573 (SUBR) ioutfile_set_r, (SUBR) ioutfile_r, (SUBR) NULL, NULL},
1574 { "fiopen", S(FIOPEN), 0, 1, "i", "Si",
1575 (SUBR) fiopen_S, (SUBR) NULL, (SUBR) NULL, NULL},
1576 { "fiopen.i", S(FIOPEN), 0, 1, "i", "ii",
1577 (SUBR) fiopen, (SUBR) NULL, (SUBR) NULL, NULL},
1578 { "ficlose", S(FICLOSE), 0, 1, "", "S",
1579 (SUBR) ficlose_opcode_S, (SUBR) NULL, (SUBR) NULL, NULL},
1580 { "ficlose.S", S(FICLOSE), 0, 1, "", "i",
1581 (SUBR) ficlose_opcode, (SUBR) NULL, (SUBR) NULL, NULL },
1582 { "fin.a", S(INFILE), WI|_QQ, 3, "", "Siiy",
1583 (SUBR) infile_set_S, (SUBR) infile_act, NULL},
1584 { "fin.A", S(INFILEA), WI, 3, "", "Siia[]",
1585 (SUBR) infile_set_A, (SUBR) infile_arr, NULL},
1586 { "fin.i", S(INFILE), WI|_QQ, 3, "", "iiiy",
1587 (SUBR) infile_set, (SUBR) infile_act, NULL},
1588 { "fink", S(KINFILE), WI, 3, "", "Siiz",
1589 (SUBR) kinfile_set_S, (SUBR) kinfile, (SUBR) NULL, NULL},
1590 { "fink.i", S(KINFILE), WI, 3, "", "iiiz",
1591 (SUBR) kinfile_set, (SUBR) kinfile, (SUBR) NULL, NULL},
1592 { "fini", S(I_INFILE), WI, 1, "", "Siim",
1593 (SUBR) i_infile_S, (SUBR) NULL, (SUBR) NULL, NULL },
1594 { "fini.i", S(I_INFILE), WI, 1, "", "iiim",
1595 (SUBR) i_infile, (SUBR) NULL, (SUBR) NULL, NULL}
1596 };
1597
fout_init_(CSOUND * csound)1598 int32_t fout_init_(CSOUND *csound)
1599 {
1600 return csound->AppendOpcodes(csound, &(localops[0]),
1601 (int32_t) (sizeof(localops) / sizeof(OENTRY)));
1602 }
1603