diff options
Diffstat (limited to 'synth/parser.cpp')
-rw-r--r-- | synth/parser.cpp | 673 |
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; } + + |