1
/* WhySynth DSSI software synthesizer plugin and GUI
3
* Copyright (C) 2004-2006, 2010 Sean Bolton and others.
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.
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.
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.
24
#include <sys/types.h>
31
#include "whysynth_types.h"
33
#include "whysynth_voice.h"
35
y_patch_t y_init_voice = {
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 */
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 */
61
y_data_is_comment(char *buf) /* line is blank, whitespace, or first non-whitespace character is '#' */
66
if (buf[i] == '#') return 1;
67
if (buf[i] == '\n') return 1;
68
if (buf[i] != ' ' && buf[i] != '\t') return 0;
75
y_data_parse_text(const char *buf, char *name, int maxlen)
80
while (buf[i] && o < maxlen) {
81
if (buf[i] < 33 || buf[i] > 126) {
83
} else if (buf[i] == '%') {
84
if (buf[i + 1] && buf[i + 2] && sscanf(buf + i + 1, "%2x", &t) == 1) {
94
/* trim trailing spaces */
95
while (o && name[o - 1] == ' ') o--;
99
/* y_sscanf.c - dual-locale sscanf
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):
106
* - this function only skips whitespace when there is explicit ' ' in
108
* - it doesn't return EOF like sscanf(3), just the number of sucessful
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.
120
_is_whitespace(char c)
122
return (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f' || c == '\v');
128
return (c >= '0' && c <= '9');
134
return ((c >= '0' && c <= '9') ||
135
(c >= 'a' && c <= 'f') ||
136
(c >= 'A' && c <= 'F'));
139
static int y_atof(const char *buffer, double *result); /* forward */
142
y_vsscanf(const char *buffer, const char *format, va_list ap)
145
const char *bp = buffer;
148
while ((fc = *format++)) {
150
if (_is_whitespace(fc)) { /* skip whitespace */
152
while (_is_whitespace(*bp))
155
} else if (fc == '%') { /* a conversion */
157
int skip = 0; /* '*' no-store modifier */
158
int width = 0; /* field width */
159
int big = 0; /* storage length modifier */
161
if (*format == '*') {
165
while (_is_digit(*format)) {
166
width = width * 10 + (*format - '0');
169
if (*format == 'l') {
174
if (*format == '%') { /* '%' - literal percent character */
182
} else if (*format == 'c') { /* 'c' - one or more characters */
185
char *sp = va_arg(ap, char *);
187
if (width == 0) width = 1;
188
for (i = 0; i < width && *bp != 0; i++, bp++)
189
if (!skip) *sp++ = *bp;
194
} else if (*format == 'd') { /* 'd' - 32 or 64 bit signed decimal integer */
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 */
208
if (negative) n = -n;
211
*va_arg(ap, int64_t *) = n;
213
*va_arg(ap, int32_t *) = n;
218
} else if (*format == 'f') { /* 'f' - float or double */
221
int n = y_atof(bp, &d);
222
if (n == 0) /* no digits converted */
226
*va_arg(ap, double *) = d;
228
*va_arg(ap, float *) = (float)d;
234
} else if (*format == 'n') { /* 'n' - store number of characters scanned so far */
236
if (!skip) *va_arg(ap, int *) = bp - buffer;
239
} else if (*format == 's') { /* 's' - string of non-whitespace characters */
242
char *sp = va_arg(ap, char *);
244
break; /* must specify a width */
245
for (i = 0; i < width && *bp != 0 && !_is_whitespace(*bp); i++, bp++)
246
if (!skip) *sp++ = *bp;
253
break; /* conversion failed */
256
} else if (*format == 'x') { /* 'x' - 32 or 64 bit signed hexidecimal integer */
260
for (i = 0; (width == 0 || i < width) && _is_hexdigit(*bp); i++, bp++) {
262
if (*bp >= 'a') n += *bp - 'a' + 10;
263
else if (*bp >= 'A') n += *bp - 'A' + 10;
266
if (i == 0) /* no digits converted */
270
*va_arg(ap, int64_t *) = n;
272
*va_arg(ap, int32_t *) = n;
278
break; /* bad conversion character */
281
} else if (fc == *bp) { /* a literal match */
285
} else { /* match fail */
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. */
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 */
307
struct lconv *lc = localeconv();
308
int dplen = strlen(lc->decimal_point);
310
/* skip leading spaces */
311
/* while( _is_whitespace(*z) ) z++; */
312
/* get sign of significand */
319
/* skip leading zeroes */
320
while( z[0]=='0' ) z++, nDigits++;
322
/* copy max significant digits to significand */
323
while( _is_digit(*z) && s<((INT64_MAX-9)/10) ){
324
s = s*10 + (*z - '0');
327
/* skip non-significant significand digits
328
** (increase exponent by d to shift decimal left) */
329
while( _is_digit(*z) ) z++, nDigits++, d++;
331
/* if decimal point is present */
332
if( *z=='.' || !strncmp(z, lc->decimal_point, 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');
343
/* skip non-significant digits */
344
while( _is_digit(*z) ) z++, nDigits++;
345
} else if (nDigits == 0)
346
return 0; /* no significand digits converted */
348
/* if exponent is present */
349
if( *z=='e' || *z=='E' ){
352
/* get sign of exponent */
359
/* copy digits to exponent */
360
while( _is_digit(*z) ){
361
e = e*10 + (*z - '0');
365
return 0; /* malformed exponent */
368
/* adjust exponent by d, and update sign */
377
/* if 0 significand */
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;
383
/* attempt to reduce exponent */
385
while( s<(INT64_MAX/10) && e>0 ) e--,s*=10;
387
while( !(s%10) && e>0 ) e--,s/=10;
390
/* adjust the sign of significand */
393
/* if exponent, scale significand as appropriate
394
** and store in result. */
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; }
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; }
423
/* store the result */
426
/* return number of characters used */
427
return (int)(z - zBegin);
431
y_sscanf(const char *str, const char *format, ...)
436
va_start(ap, format);
437
conversions = y_vsscanf(str, format, ap);
443
/* end of y_sscanf.c */
446
y_data_read_patch(FILE *file, y_patch_t *patch)
449
char c, buf[256], buf2[180];
453
if (!fgets(buf, 256, file)) return 0;
454
} while (y_data_is_comment(buf));
456
if (sscanf(buf, " WhySynth patch format %d begin", &i) != 1 ||
460
memcpy(&tmp, &y_init_voice, sizeof(y_patch_t));
464
if (!fgets(buf, 256, file)) return 0;
466
/* 'name %20%20<init%20voice>' */
467
if (sscanf(buf, " name %90s", buf2) == 1) {
469
y_data_parse_text(buf2, tmp.name, 30);
472
/* 'comment %20%20<init%20voice>' */
473
} else if (sscanf(buf, " comment %180s", buf2) == 1) {
475
y_data_parse_text(buf2, tmp.comment, 60);
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) {
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;
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)
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) {
512
case 1: vcf = &tmp.vcf1; break;
513
case 2: vcf = &tmp.vcf2; break;
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,
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) {
535
} else if (y_sscanf(buf, " volume %f", &tmp.volume) == 1) {
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) {
548
/* 'glide 0.984375' */
549
} else if (y_sscanf(buf, " glide %f", &tmp.glide_time) == 1) {
554
} else if (sscanf(buf, " bend %d", &tmp.bend_range) == 1) {
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) {
566
case 'g': lfo = &tmp.glfo; break;
567
case 'v': lfo = &tmp.vlfo; break;
568
case 'm': lfo = &tmp.mlfo; break;
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)
578
} else if (y_sscanf(buf, " mlfo %f %f", &tmp.mlfo_phase_spread,
579
&tmp.mlfo_random_freq) == 2) {
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) {
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;
601
if (y_sscanf(buf, " egY %c %d %d %f %f %d %f %f %d %f %f %d %f %f %f %f %d %f",
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)
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) {
619
/* 'WhySynth patch end' */
620
} else if (sscanf(buf, " WhySynth patch %3s", buf2) == 1 &&
621
!strcmp(buf2, "end")) {
623
break; /* finished */
627
return 0; /* unrecognized line */
631
memcpy(patch, &tmp, sizeof(y_patch_t));
633
return 1; /* -FIX- error handling yet to be implemented */
637
y_data_locate_patch_file(const char *origpath, const char *project_dir)
641
const char *filename;
643
if (stat(origpath, &statbuf) == 0)
644
return strdup(origpath);
645
else if (!project_dir)
648
filename = strrchr(origpath, '/');
650
if (filename) ++filename;
651
else filename = origpath;
652
if (!*filename) return NULL;
654
path = (char *)malloc(strlen(project_dir) + strlen(filename) + 2);
655
sprintf(path, "%s/%s", project_dir, filename);
657
if (stat(path, &statbuf) == 0)