summaryrefslogtreecommitdiff
path: root/synth/parser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'synth/parser.cpp')
-rw-r--r--synth/parser.cpp673
1 files changed, 348 insertions, 325 deletions
diff --git a/synth/parser.cpp b/synth/parser.cpp
index 52717a5..96648d6 100644
--- a/synth/parser.cpp
+++ b/synth/parser.cpp
@@ -1,3 +1,5 @@
+//uniniten
+
#include <cstdlib>
#include <fstream>
@@ -9,21 +11,32 @@
#include "readwave.h"
-Parser::Parser()
+string extract_array_name(string s)
{
- n_osc=0;
- osc=NULL;
- env=NULL;
- for (int i=0;i<128;i++)
- controller_default[i]=0;
+ size_t p;
+ p=s.find('[');
+ if (p!=string::npos)
+ return s.substr(0,p);
+ else
+ return s;
}
-Parser::~Parser()
+int extract_array_index(string s, int dim)
{
- uninit_stuff();
+ size_t p=-1,p2;
+ for (int i=0;i<dim;i++)
+ {
+ p=s.find('[',p+1);
+ if (p==string::npos) return -1;
+ }
+
+ p2=s.find(']',p+1);
+ if (p2==string::npos) return -1;
+
+ return atoi(s.substr(p+1,p2-p-1).c_str());
}
-list<string> Parser::extract_terms(string s)
+list<string> extract_terms(string s)
{
list<string> result;
@@ -43,7 +56,7 @@ list<string> Parser::extract_terms(string s)
return result;
}
-list<string> Parser::extract_factors(string s)
+list<string> extract_factors(string s)
{
list<string> result;
@@ -63,7 +76,7 @@ list<string> Parser::extract_factors(string s)
return result;
}
-list<term_t> Parser::extract_formula(string s)
+list<term_t> extract_formula(string s)
{
list<term_t> result;
term_t tmp;
@@ -116,7 +129,7 @@ list<term_t> Parser::extract_formula(string s)
return result;
}
-param_factor_t Parser::parse_pfactor(string s) //TODO fast dasselbe wie oben. mergen?
+param_factor_t parse_pfactor(string s) //TODO fast dasselbe wie oben. mergen?
{ //TODO cont müsste vel heißen FINDMICH ---> ^ ^ ^
param_factor_t result;
result.offset=0;
@@ -169,10 +182,8 @@ param_factor_t Parser::parse_pfactor(string s) //TODO fast dasselbe wie oben. me
return result;
}
-void Parser::init_stuff()
+void init_oscs(int n_osc, oscillator_t *osc)
{
- env=new env_settings_t[n_osc];
- osc=new oscillator_t[n_osc];
for (int i=0;i<n_osc;i++)
{
osc[i].n_osc=n_osc;
@@ -189,15 +200,23 @@ void Parser::init_stuff()
osc[i].vibrato_depth=0;
osc[i].vibrato_lfo=0;
osc[i].custom_wave=NULL;
-
-
+ }
+}
+
+void init_envs(int n_osc, env_settings_t *env)
+{
+ for (int i=0;i<n_osc;i++)
+ {
env[i].attack=0;
env[i].decay=0;
env[i].sustain=ONE;
env[i].release=0;
env[i].hold=true;
}
+}
+void init_filter(filter_params_t &filter)
+{
filter.enabled=false;
filter.env_amount=0;
filter.env_settings.attack=filter.env_settings.decay=
@@ -209,9 +228,10 @@ void Parser::init_stuff()
filter.resonance=0;
filter.trem_strength=0;
filter.trem_lfo=0;
-
-
-
+}
+
+void init_pfactors(int n_osc, pfactor_formula_t &pfactor)
+{
pfactor.out=new param_factor_t [n_osc];
pfactor.fm=new param_factor_t* [n_osc];
@@ -236,46 +256,12 @@ void Parser::init_stuff()
pfactor.fm[i][j].vel_amount=0;
}
}
-
-}
-void Parser::uninit_stuff()
-{
- if (osc)
- {
- for (int i=0;i<n_osc;i++)
- delete [] osc[i].fm_strength;
-
- delete [] osc;
- osc=NULL;
- }
- if (env)
- delete [] env;
}
-string Parser::extract_array_name(string s)
-{
- size_t p;
- p=s.find('[');
- if (p!=string::npos)
- return s.substr(0,p);
- else
- return s;
-}
-int Parser::extract_array_index(string s, int dim)
-{
- size_t p=-1,p2;
- for (int i=0;i<dim;i++)
- {
- p=s.find('[',p+1);
- if (p==string::npos) return -1;
- }
-
- p2=s.find(']',p+1);
- if (p2==string::npos) return -1;
-
- return atoi(s.substr(p+1,p2-p-1).c_str());
-}
+
+
+
//if this function fails, this WILL BE fatal if unhandled in the
//caller function. so this function throws errors
@@ -283,8 +269,28 @@ int Parser::extract_array_index(string s, int dim)
//state. if these settings are given to some oscillator_t by
//operator=, it will probably die while trying to create an array
//with size 0 or so.
-void Parser::parse(string fn)
+program_t parse(string fn)
{
+ int n_osc=0;
+ oscillator_t *osc=NULL;
+ env_settings_t *env=NULL;
+
+ set<parameter_t> affect[128];
+ map< parameter_t, list<term_t> > formula;
+ int controller_default[128];
+
+ for (int i=0;i<128;i++)
+ controller_default[i]=0;
+
+ filter_params_t filter;
+
+ pfactor_formula_t pfactor;
+
+ fixed_t sync_factor;
+
+
+
+
char buf[2000];
list<term_t> terms;
string line;
@@ -299,298 +305,299 @@ void Parser::parse(string fn)
int state;
- uninit_stuff();
-
ifstream f;
f.open(fn.c_str());
- if (f.good())
+ if (!f.good())
+ throw string ("could not open '"+fn+"'");
+ //else
+
+ state=0;
+ while (!f.eof())
{
- state=0;
- while (!f.eof())
+ f.getline(buf,sizeof(buf)/sizeof(*buf)-1);
+ line=buf;
+ line=remove_all_spaces(buf);
+ if ((line!="") && (line[0]!='#')) //ignore comments and empty lines
{
- f.getline(buf,sizeof(buf)/sizeof(*buf)-1);
- line=buf;
- line=remove_all_spaces(buf);
- if ((line!="") && (line[0]!='#')) //ignore comments and empty lines
+ if (line=="controllers:")
{
- if (line=="controllers:")
- {
- state=2;
- continue;
- }
- else if (line=="defaults:")
- {
- state=3;
- continue;
- }
- else if (line=="velocity:")
- {
- state=4;
- continue;
- }
+ state=2;
+ continue;
+ }
+ else if (line=="defaults:")
+ {
+ state=3;
+ continue;
+ }
+ else if (line=="velocity:")
+ {
+ state=4;
+ continue;
+ }
- var=extract_var(line);
- array=extract_array_name(var);
- strval=extract_val(line);
- val=atof(strval.c_str());
+ var=extract_var(line);
+ array=extract_array_name(var);
+ strval=extract_val(line);
+ val=atof(strval.c_str());
+
+ switch (state)
+ {
+ case 0: //expect and read number of oscillators
+ if (var!="oscillators")
+ throw string("need to know number of oscillators");
+ else
+ n_osc=val;
+
+ if (n_osc<=0) throw string("invalid number of oscillators");
+
+ //init stuff
+ env=new env_settings_t[n_osc];
+ osc=new oscillator_t[n_osc];
+ init_oscs(n_osc,osc);
+ init_envs(n_osc,env);
+ init_filter(filter);
+ init_pfactors(n_osc,pfactor);
+
+ state=1;
+ break;
- switch (state)
- {
- case 0: //expect and read number of oscillators
- if (var!="oscillators")
- throw string("need to know number of oscillators");
- else
- n_osc=val;
-
- if (n_osc<=0) throw string("invalid number of oscillators");
-
- init_stuff();
-
- state=1;
- break;
+ case 1: //read and set information about oscillator settings
+ p=param_to_enum(array);
+
+ ind=extract_array_index(var,1);
+ if ( param_needs_index(p) && (!((ind>=0) && (ind<n_osc))) )
+ throw string("out of array bounds");
+
- case 1: //read and set information about oscillator settings
- p=param_to_enum(array);
+ switch (p)
+ {
+ case MODULATION:
+ ind2=extract_array_index(var,2);
+ if (!((ind2>=0) && (ind2<n_osc)))
+ throw string("out of array bounds");
- ind=extract_array_index(var,1);
- if ( param_needs_index(p) && (!((ind>=0) && (ind<n_osc))) )
+ osc[ind].fm_strength[ind2]=val*ONE;
+ break;
+ case OUTPUT:
+ osc[ind].output=val*ONE;
+ break;
+ case WAVEFORM:
+ if (isfloat(strval))
+ {
+ osc[ind].waveform=int(val);
+ }
+ else
+ {
+ size_t pos=strval.find(':');
+ if (pos==string::npos)
+ throw string("expected 'freq:file.wav', found no ':'");
+
+ float given_freq=atof(strval.substr(0,pos).c_str());
+ string wavefile=strval.substr(pos+1);
+
+ if (given_freq<=0)
+ throw string("illegal freq specified for custom wave '"+wavefile+"'");
+
+ osc[ind].custom_wave=new custom_wave_t;
+ read_wave(wavefile.c_str(), osc[ind].custom_wave);
+ osc[ind].custom_wave->samp_rate/=given_freq;
+ }
+ break;
+ case FACTOR:
+ osc[ind].factor=val*ONE;
+ break;
+ case TREMOLO:
+ osc[ind].tremolo_depth=int(val);
+ break;
+ case TREM_LFO:
+ if (strval=="snh")
+ osc[ind].tremolo_lfo=SNH_LFO;
+ else
+ {
+ osc[ind].tremolo_lfo= int(val);
+ if ((val<0) || (val>=N_LFOS))
+ throw string("invalid value for tremolo_lfo");
+ }
+ break;
+ case VIBRATO:
+ osc[ind].vibrato_depth=val;
+ break;
+ case VIB_LFO:
+ if (strval=="snh")
+ osc[ind].vibrato_lfo= SNH_LFO;
+ else
+ {
+ osc[ind].vibrato_lfo= int(val);
+ if ((val<0) || (val>=N_LFOS))
+ throw string("invalid value for vibrato_lfo");
+ }
+ break;
+ case ATTACK:
+ env[ind].attack=val*samp_rate;
+ break;
+ case DECAY:
+ env[ind].decay=val*samp_rate;
+ break;
+ case SUSTAIN:
+ env[ind].sustain=val*ONE;
+ break;
+ case RELEASE:
+ env[ind].release=val*samp_rate;
+ break;
+ case HOLD:
+ env[ind].hold=(val!=0);
+ break;
+ case KSR:
+ osc[ind].ksr=val;
+ break;
+ case KSL:
+ osc[ind].ksl=val;
+ break;
+ case SYNC:
+ osc[ind].sync=(val!=0);
+ break;
+ case FILTER_ENABLED:
+ filter.enabled=(val!=0);
+ break;
+ case FILTER_ENV_AMOUNT:
+ filter.env_amount=val;
+ break;
+ case FILTER_ATTACK:
+ filter.env_settings.attack=val*samp_rate/filter_update_frames;
+ break;
+ case FILTER_DECAY:
+ filter.env_settings.decay=val*samp_rate/filter_update_frames;
+ break;
+ case FILTER_SUSTAIN:
+ filter.env_settings.sustain=val*ONE;
+ break;
+ case FILTER_RELEASE:
+ filter.env_settings.release=val*samp_rate/filter_update_frames;
+ break;
+ case FILTER_HOLD:
+ filter.env_settings.hold=(val!=0);
+ break;
+ case FILTER_OFFSET:
+ filter.freqfactor_offset=val;
+ break;
+ case FILTER_RESONANCE:
+ filter.resonance=val;
+ break;
+ case FILTER_TREMOLO:
+ filter.trem_strength=int(val);
+ break;
+ case FILTER_TREM_LFO:
+ if (strval=="snh")
+ filter.trem_lfo=SNH_LFO;
+ else
+ {
+ filter.trem_lfo=int(val);
+ if ((val<0) || (val>=N_LFOS))
+ throw string("invalid value for filter_trem_lfo");
+ }
+ break;
+ case SYNC_FACTOR:
+ sync_factor=val*ONE;
+ break;
+ default:
+ throw string("unknown variable ('"+array+"')");
+ }
+ break;
+
+ case 2: //read how controllers influence parameters
+ p=param_to_enum(array);
+
+ ind=extract_array_index(var,1);
+ if ( param_needs_index(p) && (!((ind>=0) && (ind<n_osc))) )
+ throw string("out of array bounds");
+
+ parameter_t par;
+ par.par=p;
+
+ if (par.par==UNKNOWN)
+ throw string("unknown variable ('"+array+"')");
+
+ if (par.par==MODULATION)
+ {
+ ind2=extract_array_index(var,2);
+ if (!((ind2>=0) && (ind2<n_osc)))
throw string("out of array bounds");
+ }
+
+ par.osc=ind;
+ par.index=ind2;
+
+ terms=extract_formula(strval);
+ for (list<term_t>::iterator it=terms.begin(); it!=terms.end(); it++)
+ if (it->c!=NO_CONT)
+ affect[it->c].insert(par);
+
+
+ formula[par]=terms;
+ break;
+
+ case 3: //read controller default values
+ if (array=="cont")
+ {
+ ind=extract_array_index(var,1);
+ if ((ind<0) || (ind>127))
+ throw string("out of array bounds");
- switch (p)
- {
- case MODULATION:
- ind2=extract_array_index(var,2);
- if (!((ind2>=0) && (ind2<n_osc)))
- throw string("out of array bounds");
+ if ((val<0) || (val>127))
+ throw string("value out of range");
- osc[ind].fm_strength[ind2]=val*ONE;
- break;
- case OUTPUT:
- osc[ind].output=val*ONE;
- break;
- case WAVEFORM:
- if (isfloat(strval))
- {
- osc[ind].waveform=int(val);
- }
- else
- {
- size_t pos=strval.find(':');
- if (pos==string::npos)
- throw string("expected 'freq:file.wav', found no ':'");
-
- float given_freq=atof(strval.substr(0,pos).c_str());
- string wavefile=strval.substr(pos+1);
-
- if (given_freq<=0)
- throw string("illegal freq specified for custom wave '"+wavefile+"'");
-
- osc[ind].custom_wave=new custom_wave_t;
- read_wave(wavefile.c_str(), osc[ind].custom_wave);
- osc[ind].custom_wave->samp_rate/=given_freq;
- }
- break;
- case FACTOR:
- osc[ind].factor=val*ONE;
- break;
- case TREMOLO:
- osc[ind].tremolo_depth=int(val);
- break;
- case TREM_LFO:
- if (strval=="snh")
- osc[ind].tremolo_lfo=SNH_LFO;
- else
- {
- osc[ind].tremolo_lfo= int(val);
- if ((val<0) || (val>=N_LFOS))
- throw string("invalid value for tremolo_lfo");
- }
- break;
- case VIBRATO:
- osc[ind].vibrato_depth=val;
- break;
- case VIB_LFO:
- if (strval=="snh")
- osc[ind].vibrato_lfo= SNH_LFO;
- else
- {
- osc[ind].vibrato_lfo= int(val);
- if ((val<0) || (val>=N_LFOS))
- throw string("invalid value for vibrato_lfo");
- }
- break;
- case ATTACK:
- env[ind].attack=val*samp_rate;
- break;
- case DECAY:
- env[ind].decay=val*samp_rate;
- break;
- case SUSTAIN:
- env[ind].sustain=val*ONE;
- break;
- case RELEASE:
- env[ind].release=val*samp_rate;
- break;
- case HOLD:
- env[ind].hold=(val!=0);
- break;
- case KSR:
- osc[ind].ksr=val;
- break;
- case KSL:
- osc[ind].ksl=val;
- break;
- case SYNC:
- osc[ind].sync=(val!=0);
- break;
- case FILTER_ENABLED:
- filter.enabled=(val!=0);
- break;
- case FILTER_ENV_AMOUNT:
- filter.env_amount=val;
- break;
- case FILTER_ATTACK:
- filter.env_settings.attack=val*samp_rate/filter_update_frames;
- break;
- case FILTER_DECAY:
- filter.env_settings.decay=val*samp_rate/filter_update_frames;
- break;
- case FILTER_SUSTAIN:
- filter.env_settings.sustain=val*ONE;
- break;
- case FILTER_RELEASE:
- filter.env_settings.release=val*samp_rate/filter_update_frames;
- break;
- case FILTER_HOLD:
- filter.env_settings.hold=(val!=0);
- break;
- case FILTER_OFFSET:
- filter.freqfactor_offset=val;
- break;
- case FILTER_RESONANCE:
- filter.resonance=val;
- break;
- case FILTER_TREMOLO:
- filter.trem_strength=int(val);
- break;
- case FILTER_TREM_LFO:
- if (strval=="snh")
- filter.trem_lfo=SNH_LFO;
- else
- {
- filter.trem_lfo=int(val);
- if ((val<0) || (val>=N_LFOS))
- throw string("invalid value for filter_trem_lfo");
- }
- break;
- case SYNC_FACTOR:
- sync_factor=val*ONE;
- break;
- default:
- throw string("unknown variable ('"+array+"')");
- }
- break;
-
- case 2: //read how controllers influence parameters
- p=param_to_enum(array);
-
- ind=extract_array_index(var,1);
- if ( param_needs_index(p) && (!((ind>=0) && (ind<n_osc))) )
- throw string("out of array bounds");
-
- parameter_t par;
- par.par=p;
-
- if (par.par==UNKNOWN)
- throw string("unknown variable ('"+array+"')");
+ controller_default[ind]=val;
+ }
+ else
+ throw string("expected cont, found '"+array+"'");
+
+ break;
+
+ case 4: //read velocity-influence over certain params
+ p=param_to_enum(array);
- if (par.par==MODULATION)
- {
+ ind=extract_array_index(var,1);
+ if ( param_needs_index(p) && (!((ind>=0) && (ind<n_osc))) )
+ throw string("out of array bounds");
+
+ switch(p)
+ {
+ case MODULATION:
ind2=extract_array_index(var,2);
if (!((ind2>=0) && (ind2<n_osc)))
throw string("out of array bounds");
- }
-
- par.osc=ind;
- par.index=ind2;
- terms=extract_formula(strval);
- for (list<term_t>::iterator it=terms.begin(); it!=terms.end(); it++)
- if (it->c!=NO_CONT)
- affect[it->c].insert(par);
-
-
- formula[par]=terms;
- break;
-
- case 3: //read controller default values
- if (array=="cont")
- {
- ind=extract_array_index(var,1);
+ pfactor.fm[ind][ind2]=parse_pfactor(strval);
+ break;
- if ((ind<0) || (ind>127))
- throw string("out of array bounds");
+ case OUTPUT:
+ pfactor.out[ind]=parse_pfactor(strval);
+ break;
- if ((val<0) || (val>127))
- throw string("value out of range");
-
- controller_default[ind]=val;
- }
- else
- throw string("expected cont, found '"+array+"'");
-
- break;
-
- case 4: //read velocity-influence over certain params
- p=param_to_enum(array);
-
- ind=extract_array_index(var,1);
- if ( param_needs_index(p) && (!((ind>=0) && (ind<n_osc))) )
- throw string("out of array bounds");
-
- switch(p)
- {
- case MODULATION:
- ind2=extract_array_index(var,2);
- if (!((ind2>=0) && (ind2<n_osc)))
- throw string("out of array bounds");
-
- pfactor.fm[ind][ind2]=parse_pfactor(strval);
- break;
-
- case OUTPUT:
- pfactor.out[ind]=parse_pfactor(strval);
- break;
-
- case FILTER_ENV_AMOUNT:
- pfactor.filter_env=parse_pfactor(strval);
- break;
-
- case FILTER_RESONANCE:
- pfactor.filter_res=parse_pfactor(strval);
- break;
-
- case FILTER_OFFSET:
- pfactor.filter_offset=parse_pfactor(strval);
- break;
-
- default:
- throw string("velocity cannot influence parameter '"+array+"'");
-
+ case FILTER_ENV_AMOUNT:
+ pfactor.filter_env=parse_pfactor(strval);
+ break;
+
+ case FILTER_RESONANCE:
+ pfactor.filter_res=parse_pfactor(strval);
+ break;
+
+ case FILTER_OFFSET:
+ pfactor.filter_offset=parse_pfactor(strval);
+ break;
+
+ default:
+ throw string("velocity cannot influence parameter '"+array+"'");
+
- }
- }
+ }
}
}
}
- else
- throw string ("could not open '"+fn+"'");
-}
-
-program_t Parser::get_results() const
-{
+
+
program_t result;
result.n_osc=n_osc;
@@ -613,6 +620,22 @@ program_t Parser::get_results() const
result.sync_factor=sync_factor;
result.pfactor=pfactor;
+
+
+
+ //clean up a bit
+
+ for (int i=0;i<n_osc;i++)
+ delete [] osc[i].fm_strength;
+
+ delete [] osc;
+ delete [] env;
+
+
+
+
return result;
}
+
+