1 /* WhySynth DSSI software synthesizer plugin and GUI
2 *
3 * Copyright (C) 2004-2006, 2010 Sean Bolton and others.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of
8 * the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be
11 * useful, but WITHOUT ANY WARRANTY; without even the implied
12 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 * PURPOSE. See the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public
16 * License along with this program; if not, write to the Free
17 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301 USA.
19 */
20
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <unistd.h>
27 #include <stdarg.h>
28 #include <inttypes.h>
29 #include <locale.h>
30
31 #include "whysynth_types.h"
32 #include "whysynth.h"
33 #include "whysynth_voice.h"
34
35 y_patch_t y_init_voice = {
36 " <-->",
37 "",
38 /* -PORTS- */
39 { 1, 0, 0, 0.0f, 0, 0.0f, 0.0f, 0.0f, 0, 0.0f, 0, 0.0f, 0.5f, 0.5f }, /* osc1 */
40 { 0, 0, 0, 0.0f, 0, 0.0f, 0.0f, 0.0f, 0, 0.0f, 0, 0.0f, 0.5f, 0.5f }, /* osc2 */
41 { 0, 0, 0, 0.0f, 0, 0.0f, 0.0f, 0.0f, 0, 0.0f, 0, 0.0f, 0.5f, 0.5f }, /* osc3 */
42 { 0, 0, 0, 0.0f, 0, 0.0f, 0.0f, 0.0f, 0, 0.0f, 0, 0.0f, 0.5f, 0.5f }, /* osc4 */
43 { 1, 0, 50.0f, 0, 0.0f, 0.0f, 0.0f }, /* vcf1 */
44 { 0, 0, 50.0f, 0, 0.0f, 0.0f, 0.0f }, /* vcf2 */
45 0.0f, 0.2f, 0.0f, 0.8f, 0.5f, 0.5f, 0.5f, 0.5f, /* mix */
46 0.5f, /* volume */
47 0, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, /* effects */
48 0.984375f, 2, /* glide / bend */
49 { 1.0f, 0, 0.0f, 0, 0.0f }, /* glfo */
50 { 1.0f, 0, 0.0f, 0, 0.0f }, /* vlfo */
51 { 1.0f, 0, 0.0f, 0, 0.0f }, 90.0f, 0.0f, /* mlfo */
52 { 1, 3, 0.004, 1, 3, 0.001, 1, 3, 0.001, 1, 3, 0.2, 0, 0, 0, 0, 0 }, /* ego */
53 { 0, 3, 0.1, 1, 3, 0.1, 1, 3, 0.1, 1, 3, 0.2, 0, 0, 0, 0, 0 }, /* eg1 */
54 { 0, 3, 0.1, 1, 3, 0.1, 1, 3, 0.1, 1, 3, 0.2, 0, 0, 0, 0, 0 }, /* eg2 */
55 { 0, 3, 0.1, 1, 3, 0.1, 1, 3, 0.1, 1, 3, 0.2, 0, 0, 0, 0, 0 }, /* eg3 */
56 { 0, 3, 0.1, 1, 3, 0.1, 1, 3, 0.1, 1, 3, 0.2, 0, 0, 0, 0, 0 }, /* eg4 */
57 1.0f, 0, 0.0f, 0, 0.0f /* modmix */
58 };
59
60 int
y_data_is_comment(char * buf)61 y_data_is_comment(char *buf) /* line is blank, whitespace, or first non-whitespace character is '#' */
62 {
63 int i = 0;
64
65 while (buf[i]) {
66 if (buf[i] == '#') return 1;
67 if (buf[i] == '\n') return 1;
68 if (buf[i] != ' ' && buf[i] != '\t') return 0;
69 i++;
70 }
71 return 1;
72 }
73
74 void
y_data_parse_text(const char * buf,char * name,int maxlen)75 y_data_parse_text(const char *buf, char *name, int maxlen)
76 {
77 int i = 0, o = 0;
78 unsigned int t;
79
80 while (buf[i] && o < maxlen) {
81 if (buf[i] < 33 || buf[i] > 126) {
82 break;
83 } else if (buf[i] == '%') {
84 if (buf[i + 1] && buf[i + 2] && sscanf(buf + i + 1, "%2x", &t) == 1) {
85 name[o++] = (char)t;
86 i += 3;
87 } else {
88 break;
89 }
90 } else {
91 name[o++] = buf[i++];
92 }
93 }
94 /* trim trailing spaces */
95 while (o && name[o - 1] == ' ') o--;
96 name[o] = '\0';
97 }
98
99 /* y_sscanf.c - dual-locale sscanf
100 *
101 * Like the standard sscanf(3), but this version accepts floating point
102 * numbers containing either the locale-specified decimal point or the
103 * "C" locale decimal point ("."). That said, there are important
104 * differences between this and a standard sscanf(3):
105 *
106 * - this function only skips whitespace when there is explicit ' ' in
107 * the format,
108 * - it doesn't return EOF like sscanf(3), just the number of sucessful
109 * conversions,
110 * - it doesn't match character classes,
111 * - there is only one length modifier: 'l', and it only applies to 'd'
112 * (for int64_t) and 'f' (for double),
113 * - '%s' with no field-width specified is an error,
114 * - there are no 'i, 'o', 'p', or 'u' conversions, similarly
115 * - use 'f' instead of 'a', 'A', 'e', 'E', 'F', 'g', or 'G', and
116 * - '%f' doesn't do hexadecimal, infinity or NaN.
117 */
118
119 static int
_is_whitespace(char c)120 _is_whitespace(char c)
121 {
122 return (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f' || c == '\v');
123 }
124
125 static int
_is_digit(char c)126 _is_digit(char c)
127 {
128 return (c >= '0' && c <= '9');
129 }
130
131 static int
_is_hexdigit(char c)132 _is_hexdigit(char c)
133 {
134 return ((c >= '0' && c <= '9') ||
135 (c >= 'a' && c <= 'f') ||
136 (c >= 'A' && c <= 'F'));
137 }
138
139 static int y_atof(const char *buffer, double *result); /* forward */
140
141 static int
y_vsscanf(const char * buffer,const char * format,va_list ap)142 y_vsscanf(const char *buffer, const char *format, va_list ap)
143 {
144 char fc;
145 const char *bp = buffer;
146 int conversions = 0;
147
148 while ((fc = *format++)) {
149
150 if (_is_whitespace(fc)) { /* skip whitespace */
151
152 while (_is_whitespace(*bp))
153 bp++;
154
155 } else if (fc == '%') { /* a conversion */
156
157 int skip = 0; /* '*' no-store modifier */
158 int width = 0; /* field width */
159 int big = 0; /* storage length modifier */
160
161 if (*format == '*') {
162 skip = 1;
163 format++;
164 }
165 while (_is_digit(*format)) {
166 width = width * 10 + (*format - '0');
167 format++;
168 }
169 if (*format == 'l') {
170 big = 1;
171 format++;
172 }
173
174 if (*format == '%') { /* '%' - literal percent character */
175
176 if (*bp == '%')
177 bp++;
178 else
179 break;
180 format++;
181
182 } else if (*format == 'c') { /* 'c' - one or more characters */
183
184 int i;
185 char *sp = va_arg(ap, char *);
186
187 if (width == 0) width = 1;
188 for (i = 0; i < width && *bp != 0; i++, bp++)
189 if (!skip) *sp++ = *bp;
190 if (i > 0 && !skip)
191 conversions++;
192 format++;
193
194 } else if (*format == 'd') { /* 'd' - 32 or 64 bit signed decimal integer */
195
196 int negative = 0;
197 int i;
198 int64_t n = 0;
199
200 if (*bp == '-') {
201 negative = 1;
202 bp++;
203 }
204 for (i = negative; (width == 0 || i < width) && _is_digit(*bp); i++, bp++)
205 n = n * 10 + (*bp - '0');
206 if (i == negative) /* no digits converted */
207 break;
208 if (negative) n = -n;
209 if (!skip) {
210 if (big)
211 *va_arg(ap, int64_t *) = n;
212 else
213 *va_arg(ap, int32_t *) = n;
214 conversions++;
215 }
216 format++;
217
218 } else if (*format == 'f') { /* 'f' - float or double */
219
220 double d;
221 int n = y_atof(bp, &d);
222 if (n == 0) /* no digits converted */
223 break;
224 if (!skip) {
225 if (big)
226 *va_arg(ap, double *) = d;
227 else
228 *va_arg(ap, float *) = (float)d;
229 conversions++;
230 }
231 bp += n;
232 format++;
233
234 } else if (*format == 'n') { /* 'n' - store number of characters scanned so far */
235
236 if (!skip) *va_arg(ap, int *) = bp - buffer;
237 format++;
238
239 } else if (*format == 's') { /* 's' - string of non-whitespace characters */
240
241 int i;
242 char *sp = va_arg(ap, char *);
243 if (width == 0)
244 break; /* must specify a width */
245 for (i = 0; i < width && *bp != 0 && !_is_whitespace(*bp); i++, bp++)
246 if (!skip) *sp++ = *bp;
247 if (i > 0) {
248 if (!skip) {
249 *sp = 0;
250 conversions++;
251 }
252 } else
253 break; /* conversion failed */
254 format++;
255
256 } else if (*format == 'x') { /* 'x' - 32 or 64 bit signed hexidecimal integer */
257 int i;
258 int64_t n = 0;
259
260 for (i = 0; (width == 0 || i < width) && _is_hexdigit(*bp); i++, bp++) {
261 n = n * 16;
262 if (*bp >= 'a') n += *bp - 'a' + 10;
263 else if (*bp >= 'A') n += *bp - 'A' + 10;
264 else n += *bp - '0';
265 }
266 if (i == 0) /* no digits converted */
267 break;
268 if (!skip) {
269 if (big)
270 *va_arg(ap, int64_t *) = n;
271 else
272 *va_arg(ap, int32_t *) = n;
273 conversions++;
274 }
275 format++;
276
277 } else {
278 break; /* bad conversion character */
279 }
280
281 } else if (fc == *bp) { /* a literal match */
282
283 bp++;
284
285 } else { /* match fail */
286 break;
287 }
288 }
289
290 return conversions;
291 }
292
293 /* The following function is based on sqlite3AtoF() from sqlite 3.6.18.
294 * The sqlite author disclaims copyright to the source code from which
295 * this was adapted. */
296 static int
y_atof(const char * z,double * pResult)297 y_atof(const char *z, double *pResult){
298 const char *zBegin = z;
299 /* sign * significand * (10 ^ (esign * exponent)) */
300 int sign = 1; /* sign of significand */
301 int64_t s = 0; /* significand */
302 int d = 0; /* adjust exponent for shifting decimal point */
303 int esign = 1; /* sign of exponent */
304 int e = 0; /* exponent */
305 double result;
306 int nDigits = 0;
307 struct lconv *lc = localeconv();
308 int dplen = strlen(lc->decimal_point);
309
310 /* skip leading spaces */
311 /* while( _is_whitespace(*z) ) z++; */
312 /* get sign of significand */
313 if( *z=='-' ){
314 sign = -1;
315 z++;
316 }else if( *z=='+' ){
317 z++;
318 }
319 /* skip leading zeroes */
320 while( z[0]=='0' ) z++, nDigits++;
321
322 /* copy max significant digits to significand */
323 while( _is_digit(*z) && s<((INT64_MAX-9)/10) ){
324 s = s*10 + (*z - '0');
325 z++, nDigits++;
326 }
327 /* skip non-significant significand digits
328 ** (increase exponent by d to shift decimal left) */
329 while( _is_digit(*z) ) z++, nDigits++, d++;
330
331 /* if decimal point is present */
332 if( *z=='.' || !strncmp(z, lc->decimal_point, dplen) ) {
333 if (*z=='.')
334 z++;
335 else
336 z += dplen;
337 /* copy digits from after decimal to significand
338 ** (decrease exponent by d to shift decimal right) */
339 while( _is_digit(*z) && s<((INT64_MAX-9)/10) ){
340 s = s*10 + (*z - '0');
341 z++, nDigits++, d--;
342 }
343 /* skip non-significant digits */
344 while( _is_digit(*z) ) z++, nDigits++;
345 } else if (nDigits == 0)
346 return 0; /* no significand digits converted */
347
348 /* if exponent is present */
349 if( *z=='e' || *z=='E' ){
350 int eDigits = 0;
351 z++;
352 /* get sign of exponent */
353 if( *z=='-' ){
354 esign = -1;
355 z++;
356 }else if( *z=='+' ){
357 z++;
358 }
359 /* copy digits to exponent */
360 while( _is_digit(*z) ){
361 e = e*10 + (*z - '0');
362 z++, eDigits++;
363 }
364 if (eDigits == 0)
365 return 0; /* malformed exponent */
366 }
367
368 /* adjust exponent by d, and update sign */
369 e = (e*esign) + d;
370 if( e<0 ) {
371 esign = -1;
372 e *= -1;
373 } else {
374 esign = 1;
375 }
376
377 /* if 0 significand */
378 if( !s ) {
379 /* In the IEEE 754 standard, zero is signed.
380 ** Add the sign if we've seen at least one digit */
381 result = (sign<0 && nDigits) ? -(double)0 : (double)0;
382 } else {
383 /* attempt to reduce exponent */
384 if( esign>0 ){
385 while( s<(INT64_MAX/10) && e>0 ) e--,s*=10;
386 }else{
387 while( !(s%10) && e>0 ) e--,s/=10;
388 }
389
390 /* adjust the sign of significand */
391 s = sign<0 ? -s : s;
392
393 /* if exponent, scale significand as appropriate
394 ** and store in result. */
395 if( e ){
396 double scale = 1.0;
397 /* attempt to handle extremely small/large numbers better */
398 if( e>307 && e<342 ){
399 while( e%308 ) { scale *= 1.0e+1; e -= 1; }
400 if( esign<0 ){
401 result = s / scale;
402 result /= 1.0e+308;
403 }else{
404 result = s * scale;
405 result *= 1.0e+308;
406 }
407 }else{
408 /* 1.0e+22 is the largest power of 10 than can be
409 ** represented exactly. */
410 while( e%22 ) { scale *= 1.0e+1; e -= 1; }
411 while( e>0 ) { scale *= 1.0e+22; e -= 22; }
412 if( esign<0 ){
413 result = s / scale;
414 }else{
415 result = s * scale;
416 }
417 }
418 } else {
419 result = (double)s;
420 }
421 }
422
423 /* store the result */
424 *pResult = result;
425
426 /* return number of characters used */
427 return (int)(z - zBegin);
428 }
429
430 int
y_sscanf(const char * str,const char * format,...)431 y_sscanf(const char *str, const char *format, ...)
432 {
433 va_list ap;
434 int conversions;
435
436 va_start(ap, format);
437 conversions = y_vsscanf(str, format, ap);
438 va_end(ap);
439
440 return conversions;
441 }
442
443 /* end of y_sscanf.c */
444
445 int
y_data_read_patch(FILE * file,y_patch_t * patch)446 y_data_read_patch(FILE *file, y_patch_t *patch)
447 {
448 int i;
449 char c, buf[256], buf2[180];
450 y_patch_t tmp;
451
452 do {
453 if (!fgets(buf, 256, file)) return 0;
454 } while (y_data_is_comment(buf));
455
456 if (sscanf(buf, " WhySynth patch format %d begin", &i) != 1 ||
457 i != 0)
458 return 0;
459
460 memcpy(&tmp, &y_init_voice, sizeof(y_patch_t));
461
462 while (1) {
463
464 if (!fgets(buf, 256, file)) return 0;
465
466 /* 'name %20%20<init%20voice>' */
467 if (sscanf(buf, " name %90s", buf2) == 1) {
468
469 y_data_parse_text(buf2, tmp.name, 30);
470 continue;
471
472 /* 'comment %20%20<init%20voice>' */
473 } else if (sscanf(buf, " comment %180s", buf2) == 1) {
474
475 y_data_parse_text(buf2, tmp.comment, 60);
476 continue;
477
478 /* -PORTS- */
479 /* 'oscY 1 1 0 0 0 0 0 0 0.5 0 0 0 0 0.5 0.5' */
480 /* 'oscY 2 0 0 0 0 0 0 0 0.5 0 0 0 0 0.5 0.5' */
481 /* 'oscY 3 0 0 0 0 0 0 0 0.5 0 0 0 0 0.5 0.5' */
482 /* 'oscY 4 0 0 0 0 0 0 0 0.5 0 0 0 0 0.5 0.5' */
483 } else if (sscanf(buf, " oscY %d", &i) == 1) {
484
485 struct posc *osc;
486
487 switch (i) {
488 case 1: osc = &tmp.osc1; break;
489 case 2: osc = &tmp.osc2; break;
490 case 3: osc = &tmp.osc3; break;
491 case 4: osc = &tmp.osc4; break;
492 default:
493 return 0;
494 }
495 if (y_sscanf(buf, " oscY %d %d %d %d %f %d %f %f %f %d %f %d %f %f %f",
496 &i, &osc->mode, &osc->waveform, &osc->pitch,
497 &osc->detune, &osc->pitch_mod_src, &osc->pitch_mod_amt,
498 &osc->mparam1, &osc->mparam2, &osc->mmod_src,
499 &osc->mmod_amt, &osc->amp_mod_src, &osc->amp_mod_amt,
500 &osc->level_a, &osc->level_b) != 15)
501 return 0;
502
503 continue;
504
505 /* 'vcfY 1 1 0 50 0 0 0 0' */
506 /* 'vcfY 2 0 0 50 0 0 0 0' */
507 } else if (sscanf(buf, " vcfY %d", &i) == 1) {
508
509 struct pvcf *vcf;
510
511 switch (i) {
512 case 1: vcf = &tmp.vcf1; break;
513 case 2: vcf = &tmp.vcf2; break;
514 default:
515 return 0;
516 }
517 if (y_sscanf(buf, " vcfY %d %d %d %f %d %f %f %f",
518 &i, &vcf->mode, &vcf->source, &vcf->frequency,
519 &vcf->freq_mod_src, &vcf->freq_mod_amt, &vcf->qres,
520 &vcf->mparam) != 8)
521 return 0;
522
523 continue;
524
525 /* 'mix 0 0.2 0 0.8 0.5 0.5 0.5 0.5' */
526 } else if (y_sscanf(buf, " mix %f %f %f %f %f %f %f %f",
527 &tmp.busa_level, &tmp.busa_pan,
528 &tmp.busb_level, &tmp.busb_pan,
529 &tmp.vcf1_level, &tmp.vcf1_pan,
530 &tmp.vcf2_level, &tmp.vcf2_pan) == 8) {
531
532 continue;
533
534 /* 'volume 0.5' */
535 } else if (y_sscanf(buf, " volume %f", &tmp.volume) == 1) {
536
537 continue;
538
539 /* 'effects 0 0 0 0 0' */
540 } else if (y_sscanf(buf, " effects %d %f %f %f %f %f %f %f",
541 &tmp.effect_mode, &tmp.effect_param1,
542 &tmp.effect_param2, &tmp.effect_param3,
543 &tmp.effect_param4, &tmp.effect_param5,
544 &tmp.effect_param6, &tmp.effect_mix) == 8) {
545
546 continue;
547
548 /* 'glide 0.984375' */
549 } else if (y_sscanf(buf, " glide %f", &tmp.glide_time) == 1) {
550
551 continue;
552
553 /* 'bend 2' */
554 } else if (sscanf(buf, " bend %d", &tmp.bend_range) == 1) {
555
556 continue;
557
558 /* 'lfoY g 1 0 0 0 0' */
559 /* 'lfoY v 1 0 0 0 0' */
560 /* 'lfoY m 1 0 0 0 0' */
561 } else if (sscanf(buf, " lfoY %c", &c) == 1) {
562
563 struct plfo *lfo;
564
565 switch (c) {
566 case 'g': lfo = &tmp.glfo; break;
567 case 'v': lfo = &tmp.vlfo; break;
568 case 'm': lfo = &tmp.mlfo; break;
569 default:
570 return 0;
571 }
572 if (y_sscanf(buf, " lfoY %c %f %d %f %d %f",
573 &c, &lfo->frequency, &lfo->waveform, &lfo->delay,
574 &lfo->amp_mod_src, &lfo->amp_mod_amt) != 6)
575 return 0;
576
577 /* 'mlfo 90 0' */
578 } else if (y_sscanf(buf, " mlfo %f %f", &tmp.mlfo_phase_spread,
579 &tmp.mlfo_random_freq) == 2) {
580
581 continue;
582
583 /* 'egY o 0 0.1 1 0.1 1 0.1 1 0.2 0.1 1 0 0 0 0 0' */
584 /* 'egY 1 0 0.1 1 0.1 1 0.1 1 0.2 0.1 1 0 0 0 0 0' */
585 /* 'egY 2 0 0.1 1 0.1 1 0.1 1 0.2 0.1 1 0 0 0 0 0' */
586 /* 'egY 3 0 0.1 1 0.1 1 0.1 1 0.2 0.1 1 0 0 0 0 0' */
587 /* 'egY 4 0 0.1 1 0.1 1 0.1 1 0.2 0.1 1 0 0 0 0 0' */
588 } else if (sscanf(buf, " egY %c", &c) == 1) {
589
590 struct peg *eg;
591
592 switch (c) {
593 case 'o': eg = &tmp.ego; break;
594 case '1': eg = &tmp.eg1; break;
595 case '2': eg = &tmp.eg2; break;
596 case '3': eg = &tmp.eg3; break;
597 case '4': eg = &tmp.eg4; break;
598 default:
599 return 0;
600 }
601 if (y_sscanf(buf, " egY %c %d %d %f %f %d %f %f %d %f %f %d %f %f %f %f %d %f",
602 &c, &eg->mode,
603 &eg->shape1, &eg->time1, &eg->level1,
604 &eg->shape2, &eg->time2, &eg->level2,
605 &eg->shape3, &eg->time3, &eg->level3,
606 &eg->shape4, &eg->time4,
607 &eg->vel_level_sens, &eg->vel_time_scale,
608 &eg->kbd_time_scale, &eg->amp_mod_src,
609 &eg->amp_mod_amt) != 18)
610 return 0;
611
612 /* 'modmix 1 0 0 0 0' */
613 } else if (y_sscanf(buf, " modmix %f %d %f %d %f", &tmp.modmix_bias,
614 &tmp.modmix_mod1_src, &tmp.modmix_mod1_amt,
615 &tmp.modmix_mod2_src, &tmp.modmix_mod2_amt) == 5) {
616
617 continue;
618
619 /* 'WhySynth patch end' */
620 } else if (sscanf(buf, " WhySynth patch %3s", buf2) == 1 &&
621 !strcmp(buf2, "end")) {
622
623 break; /* finished */
624
625 } else {
626
627 return 0; /* unrecognized line */
628 }
629 }
630
631 memcpy(patch, &tmp, sizeof(y_patch_t));
632
633 return 1; /* -FIX- error handling yet to be implemented */
634 }
635
636 char *
y_data_locate_patch_file(const char * origpath,const char * project_dir)637 y_data_locate_patch_file(const char *origpath, const char *project_dir)
638 {
639 struct stat statbuf;
640 char *path;
641 const char *filename;
642
643 if (stat(origpath, &statbuf) == 0)
644 return strdup(origpath);
645 else if (!project_dir)
646 return NULL;
647
648 filename = strrchr(origpath, '/');
649
650 if (filename) ++filename;
651 else filename = origpath;
652 if (!*filename) return NULL;
653
654 path = (char *)malloc(strlen(project_dir) + strlen(filename) + 2);
655 sprintf(path, "%s/%s", project_dir, filename);
656
657 if (stat(path, &statbuf) == 0)
658 return path;
659
660 free(path);
661 return NULL;
662 }
663
664