Logo Search packages:      
Sourcecode: whysynth version File versions  Download package

common_data.c

/* WhySynth DSSI software synthesizer plugin and GUI
 *
 * Copyright (C) 2004-2006 Sean Bolton and others.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be
 * useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 * PURPOSE.  See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program; if not, write to the Free
 * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307, USA.
 */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

#include "whysynth_types.h"
#include "whysynth.h"
#include "whysynth_voice.h"

y_patch_t y_init_voice = {
    "  <-->",
    "",
    /* -PORTS- */
    { 1, 0, 0, 0.0f, 0, 0.0f, 0.0f, 0.0f, 0, 0.0f, 0, 0.0f, 0.5f, 0.5f },  /* osc1 */
    { 0, 0, 0, 0.0f, 0, 0.0f, 0.0f, 0.0f, 0, 0.0f, 0, 0.0f, 0.5f, 0.5f },  /* osc2 */
    { 0, 0, 0, 0.0f, 0, 0.0f, 0.0f, 0.0f, 0, 0.0f, 0, 0.0f, 0.5f, 0.5f },  /* osc3 */
    { 0, 0, 0, 0.0f, 0, 0.0f, 0.0f, 0.0f, 0, 0.0f, 0, 0.0f, 0.5f, 0.5f },  /* osc4 */
    { 1, 0, 50.0f, 0, 0.0f, 0.0f, 0.0f },                                  /* vcf1 */
    { 0, 0, 50.0f, 0, 0.0f, 0.0f, 0.0f },                                  /* vcf2 */
    0.0f, 0.2f, 0.0f, 0.8f, 0.5f, 0.5f, 0.5f, 0.5f,                        /* mix */
    0.5f,                                                                  /* volume */
    0, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,                           /* effects */
    0.984375f, 2,                                                          /* glide / bend */
    { 1.0f, 0, 0.0f, 0, 0.0f },                                            /* glfo */
    { 1.0f, 0, 0.0f, 0, 0.0f },                                            /* vlfo */
    { 1.0f, 0, 0.0f, 0, 0.0f }, 90.0f, 0.0f,                               /* mlfo */
    { 1, 3, 0.004, 1, 3, 0.001, 1, 3, 0.001, 1, 3, 0.2, 0, 0, 0, 0, 0 },   /* ego */
    { 0, 3, 0.1, 1, 3, 0.1, 1, 3, 0.1, 1, 3, 0.2, 0, 0, 0, 0, 0 },         /* eg1 */
    { 0, 3, 0.1, 1, 3, 0.1, 1, 3, 0.1, 1, 3, 0.2, 0, 0, 0, 0, 0 },         /* eg2 */
    { 0, 3, 0.1, 1, 3, 0.1, 1, 3, 0.1, 1, 3, 0.2, 0, 0, 0, 0, 0 },         /* eg3 */
    { 0, 3, 0.1, 1, 3, 0.1, 1, 3, 0.1, 1, 3, 0.2, 0, 0, 0, 0, 0 },         /* eg4 */
    1.0f, 0, 0.0f, 0, 0.0f                                                 /* modmix */
};

int
y_data_is_comment(char *buf)  /* line is blank, whitespace, or first non-whitespace character is '#' */
{
    int i = 0;

    while (buf[i]) {
        if (buf[i] == '#') return 1;
        if (buf[i] == '\n') return 1;
        if (buf[i] != ' ' && buf[i] != '\t') return 0;
        i++;
    }
    return 1;
}

void
y_data_parse_text(const char *buf, char *name, int maxlen)
{
    int i = 0, o = 0;
    unsigned int t;

    while (buf[i] && o < maxlen) {
        if (buf[i] < 33 || buf[i] > 126) {
            break;
        } else if (buf[i] == '%') {
            if (buf[i + 1] && buf[i + 2] && sscanf(buf + i + 1, "%2x", &t) == 1) {
                name[o++] = (char)t;
                i += 3;
            } else {
                break;
            }
        } else {
            name[o++] = buf[i++];
        }
    }
    /* trim trailing spaces */
    while (o && name[o - 1] == ' ') o--;
    name[o] = '\0';
}

int
y_data_read_patch(FILE *file, y_patch_t *patch)
{
    int i;
    char c, buf[256], buf2[180];
    y_patch_t tmp;

    do {
        if (!fgets(buf, 256, file)) return 0;
    } while (y_data_is_comment(buf));

    if (sscanf(buf, " WhySynth patch format %d begin", &i) != 1 ||
        i != 0)
        return 0;

    memcpy(&tmp, &y_init_voice, sizeof(y_patch_t));

    while (1) {
        
        if (!fgets(buf, 256, file)) return 0;

        /* 'name %20%20<init%20voice>' */
        if (sscanf(buf, " name %90s", buf2) == 1) {
            
            y_data_parse_text(buf2, tmp.name, 30);
            continue;

        /* 'comment %20%20<init%20voice>' */
        } else if (sscanf(buf, " comment %180s", buf2) == 1) {
            
            y_data_parse_text(buf2, tmp.comment, 60);
            continue;

        /* -PORTS- */
        /* 'oscY 1 1 0 0 0 0 0 0 0.5 0 0 0 0 0.5 0.5' */
        /* 'oscY 2 0 0 0 0 0 0 0 0.5 0 0 0 0 0.5 0.5' */
        /* 'oscY 3 0 0 0 0 0 0 0 0.5 0 0 0 0 0.5 0.5' */
        /* 'oscY 4 0 0 0 0 0 0 0 0.5 0 0 0 0 0.5 0.5' */
        } else if (sscanf(buf, " oscY %d", &i) == 1) {

            struct posc *osc;

            switch (i) {
              case 1: osc = &tmp.osc1; break;
              case 2: osc = &tmp.osc2; break;
              case 3: osc = &tmp.osc3; break;
              case 4: osc = &tmp.osc4; break;
              default:
                return 0;
            }
            if (sscanf(buf, " oscY %d %d %d %d %f %d %f %f %f %d %f %d %f %f %f",
                       &i, &osc->mode, &osc->waveform, &osc->pitch,
                       &osc->detune, &osc->pitch_mod_src, &osc->pitch_mod_amt,
                       &osc->mparam1, &osc->mparam2, &osc->mmod_src,
                       &osc->mmod_amt, &osc->amp_mod_src, &osc->amp_mod_amt,
                       &osc->level_a, &osc->level_b) != 15)
                return 0;

            continue;

        /* 'vcfY 1 1 0 50 0 0 0 0' */
        /* 'vcfY 2 0 0 50 0 0 0 0' */
        } else if (sscanf(buf, " vcfY %d", &i) == 1) {

            struct pvcf *vcf;

            switch (i) {
              case 1: vcf = &tmp.vcf1; break;
              case 2: vcf = &tmp.vcf2; break;
              default:
                return 0;
            }
            if (sscanf(buf, " vcfY %d %d %d %f %d %f %f %f",
                       &i, &vcf->mode, &vcf->source, &vcf->frequency,
                       &vcf->freq_mod_src, &vcf->freq_mod_amt, &vcf->qres,
                       &vcf->mparam) != 8)
                return 0;

            continue;

        /* 'mix 0 0.2 0 0.8 0.5 0.5 0.5 0.5' */
        } else if (sscanf(buf, " mix %f %f %f %f %f %f %f %f",
                          &tmp.busa_level, &tmp.busa_pan,
                          &tmp.busb_level, &tmp.busb_pan,
                          &tmp.vcf1_level, &tmp.vcf1_pan,
                          &tmp.vcf2_level, &tmp.vcf2_pan) == 8) {

            continue;

        /* 'volume 0.5' */
        } else if (sscanf(buf, " volume %f", &tmp.volume) == 1) {

            continue;

        /* 'effects 0 0 0 0 0' */
        } else if (sscanf(buf, " effects %d %f %f %f %f %f %f %f",
                          &tmp.effect_mode, &tmp.effect_param1,
                          &tmp.effect_param2, &tmp.effect_param3,
                          &tmp.effect_param4, &tmp.effect_param5,
                          &tmp.effect_param6, &tmp.effect_mix) == 8) {

            continue;

        /* 'glide 0.984375' */
        } else if (sscanf(buf, " glide %f", &tmp.glide_time) == 1) {

            continue;

        /* 'bend 2' */
        } else if (sscanf(buf, " bend %d", &tmp.bend_range) == 1) {

            continue;

        /* 'lfoY g 1 0 0 0 0' */
        /* 'lfoY v 1 0 0 0 0' */
        /* 'lfoY m 1 0 0 0 0' */
        } else if (sscanf(buf, " lfoY %c", &c) == 1) {

            struct plfo *lfo;

            switch (c) {
              case 'g': lfo = &tmp.glfo; break;
              case 'v': lfo = &tmp.vlfo; break;
              case 'm': lfo = &tmp.mlfo; break;
              default:
                return 0;
            }
            if (sscanf(buf, " lfoY %c %f %d %f %d %f",
                       &c, &lfo->frequency, &lfo->waveform, &lfo->delay,
                       &lfo->amp_mod_src, &lfo->amp_mod_amt) != 6)
                return 0;

        /* 'mlfo 90 0' */
        } else if (sscanf(buf, " mlfo %f %f", &tmp.mlfo_phase_spread,
                          &tmp.mlfo_random_freq) == 2) {

            continue;

        /* 'egY o 0 0.1 1 0.1 1 0.1 1 0.2 0.1 1 0 0 0 0 0' */
        /* 'egY 1 0 0.1 1 0.1 1 0.1 1 0.2 0.1 1 0 0 0 0 0' */
        /* 'egY 2 0 0.1 1 0.1 1 0.1 1 0.2 0.1 1 0 0 0 0 0' */
        /* 'egY 3 0 0.1 1 0.1 1 0.1 1 0.2 0.1 1 0 0 0 0 0' */
        /* 'egY 4 0 0.1 1 0.1 1 0.1 1 0.2 0.1 1 0 0 0 0 0' */
        } else if (sscanf(buf, " egY %c", &c) == 1) {

            struct peg *eg;

            switch (c) {
              case 'o': eg = &tmp.ego; break;
              case '1': eg = &tmp.eg1; break;
              case '2': eg = &tmp.eg2; break;
              case '3': eg = &tmp.eg3; break;
              case '4': eg = &tmp.eg4; break;
              default:
                return 0;
            }
            if (sscanf(buf, " egY %c %d %d %f %f %d %f %f %d %f %f %d %f %f %f %f %d %f",
                       &c, &eg->mode,
                       &eg->shape1, &eg->time1, &eg->level1,
                       &eg->shape2, &eg->time2, &eg->level2,
                       &eg->shape3, &eg->time3, &eg->level3,
                       &eg->shape4, &eg->time4,
                       &eg->vel_level_sens, &eg->vel_time_scale,
                       &eg->kbd_time_scale, &eg->amp_mod_src,
                       &eg->amp_mod_amt) != 18)
                return 0;

        /* 'modmix 1 0 0 0 0' */
        } else if (sscanf(buf, " modmix %f %d %f %d %f", &tmp.modmix_bias,
                          &tmp.modmix_mod1_src, &tmp.modmix_mod1_amt,
                          &tmp.modmix_mod2_src, &tmp.modmix_mod2_amt) == 5) {

            continue;

        /* 'WhySynth patch end' */
        } else if (sscanf(buf, " WhySynth patch %3s", buf2) == 1 &&
                 !strcmp(buf2, "end")) {

            break; /* finished */

        } else {

            return 0; /* unrecognized line */
        }
    }

    memcpy(patch, &tmp, sizeof(y_patch_t));

    return 1;  /* -FIX- error handling yet to be implemented */
}

char *
y_data_locate_patch_file(const char *origpath, const char *project_dir)
{
    struct stat statbuf;
    char *path;
    const char *filename;

    if (stat(origpath, &statbuf) == 0)
        return strdup(origpath);
    else if (!project_dir)
      return NULL;
    
    filename = strrchr(origpath, '/');
    
    if (filename) ++filename;
    else filename = origpath;
    if (!*filename) return NULL;
    
    path = (char *)malloc(strlen(project_dir) + strlen(filename) + 2);
    sprintf(path, "%s/%s", project_dir, filename);
    
    if (stat(path, &statbuf) == 0)
        return path;
    
    free(path);
    return NULL;
}


Generated by  Doxygen 1.6.0   Back to index