~luke.andrew/whysynth-controller/whysynth-refactor-filters

« back to all changes in this revision

Viewing changes to src/common_data.c

  • Committer: Luke Andrew
  • Date: 2011-03-30 10:05:45 UTC
  • Revision ID: luke.bzr@la.id.au-20110330100545-d90fiznwavvyc1mi
initial checkin from 20100922 tarball

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
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
 
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
 
120
_is_whitespace(char c)
 
121
{
 
122
    return (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f' || c == '\v');
 
123
}
 
124
 
 
125
static int
 
126
_is_digit(char c)
 
127
{
 
128
    return (c >= '0' && c <= '9');
 
129
}
 
130
 
 
131
static int
 
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
 
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
 
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
 
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
 
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 *
 
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