diff options
author | Florian Jung <flo@thinkpad.(none)> | 2010-12-31 16:33:17 +0100 |
---|---|---|
committer | Florian Jung <flo@thinkpad.(none)> | 2010-12-31 16:33:17 +0100 |
commit | ff2f14ab35cf1cb2ded11b4ae86d24dda738b445 (patch) | |
tree | 3e35d112243bf987f66359a53e4ff9261bdc6d1b /note_compiler | |
parent | d46f6ee0a6298ff58c6f4f0647d49fb4a76f9ea9 (diff) |
Add initial code for the note-compiler
The note-compiler now has a Parser class which knows about possible
parameter changes (by controller, velocity or simply user definition).
Furthermore, several files were adapted (by stripping unneeded code,
adding the bool foo_const variables etc.).
Small fix in util.c which causes extract_var("foo") to return "foo"
instead of "".
Fixes in both Makefiles.
Diffstat (limited to 'note_compiler')
-rw-r--r-- | note_compiler/.depend | 4 | ||||
-rw-r--r-- | note_compiler/IDEE | 29 | ||||
-rw-r--r-- | note_compiler/Makefile | 9 | ||||
-rw-r--r-- | note_compiler/main.cpp | 29 | ||||
-rw-r--r-- | note_compiler/parser.cpp | 454 | ||||
-rw-r--r-- | note_compiler/parser.h | 40 | ||||
-rw-r--r-- | note_compiler/programs.h | 119 | ||||
-rw-r--r-- | note_compiler/util.cpp | 208 | ||||
-rw-r--r-- | note_compiler/util.h | 31 |
9 files changed, 919 insertions, 4 deletions
diff --git a/note_compiler/.depend b/note_compiler/.depend new file mode 100644 index 0000000..30001ec --- /dev/null +++ b/note_compiler/.depend @@ -0,0 +1,4 @@ +main.o: main.cpp parser.h ../synth/fixed.h programs.h util.h +parser.o: parser.cpp parser.h ../synth/fixed.h programs.h util.h \ + ../synth/defines.h +util.o: util.cpp util.h programs.h ../synth/fixed.h diff --git a/note_compiler/IDEE b/note_compiler/IDEE new file mode 100644 index 0000000..fc28809 --- /dev/null +++ b/note_compiler/IDEE @@ -0,0 +1,29 @@ +Die Programmdatei wird geparst. Der Parser achtet hierbei auf folgendes: + - Initialwert der Parameter + - werden die Parameter jemals geändert? + +Parameter, die nie geändert werden, werden hardgecodet. +Parameter, die geändert werden können, nicht. + +Wann können Parameter verändert werden? + - per controller (set_param) + - per velocity (pfactor, apply_pfactor etc.) + +get_sample (und letztendlich auch alle anderen funktionen) folgender- +maßen durchgehen: + +z.B. bei if (sync_factor): wenn sync-factor variabel ist, codestelle +so übernehmen. sonst entweder das if rauslassen und nur den nutzteil +übernehmen, oder den ganzen teil rauslassen. + + +bei for (i=0;i<n_oscillators;i++) jeden osc einzeln eincodieren. +jeweils relevante teile übernehmen, rest rauslassen + +bei konstanten werte diese hardcoden + +envelopes können ggf. weggelassen werden, wenn folgendes gilt: +attack=0, decay=egal, sustain=1.0, release>9999 + +arrays werden als viele pointer realisiert. +also nicht oscillator[0], osc[1] etc sondern osc0, osc1 etc diff --git a/note_compiler/Makefile b/note_compiler/Makefile index bc51697..6a08b81 100644 --- a/note_compiler/Makefile +++ b/note_compiler/Makefile @@ -1,8 +1,9 @@ CXX=g++ -CXXFLAGS=-Wall -g -LDFLAGS=-lm +CFLAGS=-Wall -g +CXXFLAGS=$(CFLAGS) +LDFLAGS=-lm `pkg-config --cflags --libs jack` -OBJ=main.o +OBJ=main.o parser.o util.o BIN=compiler DEPENDFILE = .depend @@ -14,7 +15,7 @@ all: $(BIN) $(BIN): $(OBJ) - $(CXX) $(CFLAGS) -o $(BIN) $(OBJ) $(LDFLAGS) + $(CXX) $(CXXFLAGS) -o $(BIN) $(OBJ) $(LDFLAGS) depend dep: $(SRC) diff --git a/note_compiler/main.cpp b/note_compiler/main.cpp new file mode 100644 index 0000000..3d59c3b --- /dev/null +++ b/note_compiler/main.cpp @@ -0,0 +1,29 @@ +#include <iostream> + +#include "parser.h" +#include "programs.h" +#include "util.h" +#include "../synth/fixed.h" + +using namespace std; + +int main(int argc, char** argv) +{ + Parser parser; + program_t p; + + parser.parse("../../velotest.prog"); + + p=parser.get_result(); + + cout << "n_osc="<<p.n_osc<<endl; + for (int i=0;i<p.n_osc;i++) + { + for (int j=0;j<p.n_osc;j++) + { + cout << " "<<i<<" gets modulated by "<<j<<": strength="<<p.osc[i].fm_strength[j]<<", const="<<p.osc[i].fm_strength_const[j]<<endl; + } + } + + return 0; +} diff --git a/note_compiler/parser.cpp b/note_compiler/parser.cpp new file mode 100644 index 0000000..05985de --- /dev/null +++ b/note_compiler/parser.cpp @@ -0,0 +1,454 @@ +#include <cstdlib> +#include <fstream> + +#include "parser.h" +#include "programs.h" +#include "util.h" +#include "../synth/defines.h" + + +Parser::Parser() +{ + n_osc=0; + osc=NULL; + env=NULL; +} + +Parser::~Parser() +{ + uninit_stuff(); +} + +void Parser::init_stuff() +{ + 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; + + osc[i].fm_strength=new fixed_t[n_osc]; + osc[i].fm_strength_const=new bool[n_osc]; + for (int j=0;j<n_osc;j++) + { + osc[i].fm_strength[j]=0; + osc[i].fm_strength_const[j]=true; + } + + osc[i].output=0; + osc[i].output_const=true; + osc[i].waveform=0; + osc[i].waveform_const=true; + osc[i].factor=ONE; + osc[i].factor_const=true; + osc[i].tremolo_depth=0; + osc[i].tremolo_depth_const=true; + osc[i].tremolo_lfo=0; + osc[i].tremolo_lfo_const=true; + osc[i].vibrato_depth=0; + osc[i].vibrato_depth_const=true; + osc[i].vibrato_lfo=0; + osc[i].vibrato_lfo_const=true; + osc[i].have_custom_wave=false; + + + env[i].attack=0; + env[i].attack_const=true; + env[i].decay=0; + env[i].decay_const=true; + env[i].sustain=ONE; + env[i].sustain_const=true; + env[i].release=0; + env[i].release_const=true; + env[i].hold=true; + env[i].hold_const=true; + } + + filter.enabled=false; + filter.enabled_const=true; + filter.env_amount=0; + filter.env_amount_const=true; + filter.env_settings.attack=0; + filter.env_settings.attack_const=true; + filter.env_settings.decay=0; + filter.env_settings.decay_const=true; + filter.env_settings.release=0; + filter.env_settings.release_const=true; + filter.env_settings.sustain=0; + filter.env_settings.sustain_const=true; + filter.env_settings.hold=true; + filter.env_settings.hold_const=true; + + filter.freqfactor_offset=0; + filter.freqfactor_offset_const=true; + filter.resonance=0; + filter.resonance_const=true; + filter.trem_strength=0; + filter.trem_strength_const=true; + filter.trem_lfo=0; + filter.trem_lfo_const=true; +} +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()); +} + +void Parser::parse(string fn) +{ + char buf[2000]; + string line; + string var; + string array; + string strval; + float val; + + parameter_enum p; + + int ind,ind2=0; + + int state; + + uninit_stuff(); + + ifstream f; + f.open(fn.c_str()); + if (f.good()) + { + 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 + { + if (line=="controllers:") + { + state=2; + continue; + } + else if (line=="defaults:") + { + state=3; + continue; + } + else if (line=="velocity:") + { + state=4; + continue; + } + else if (line=="variable:") + { + state=5; + continue; + } + + 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(); + + 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"); + + + switch (p) + { + case MODULATION: + ind2=extract_array_index(var,2); + if (!((ind2>=0) && (ind2<n_osc))) + throw string("out of array bounds"); + + 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 + { + osc[ind].have_custom_wave=true; + } + 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; + break; + case DECAY: + env[ind].decay=val; + break; + case SUSTAIN: + env[ind].sustain=val; + break; + case RELEASE: + env[ind].release=val; + 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; + break; + case FILTER_DECAY: + filter.env_settings.decay=val; + break; + case FILTER_SUSTAIN: + filter.env_settings.sustain=val; + break; + case FILTER_RELEASE: + filter.env_settings.release=val; + 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 5: //read which params shall be variable, even if + //there are currently no controllers which change them + case 4: //read velocity-influence over certain params + 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"); + + if (state==4) //velocity-influence + { + switch (p) + { + case MODULATION: + case OUTPUT: + case FILTER_ENV_AMOUNT: + case FILTER_RESONANCE: + case FILTER_OFFSET: + // everything ok, do nothing + break; + + default: // other params than the above may not be influenced! + throw string("velocity cannot influence parameter '"+array+"'"); + } + } + + + switch (p) + { + case MODULATION: + ind2=extract_array_index(var,2); + if (!((ind2>=0) && (ind2<n_osc))) + throw string("out of array bounds"); + + osc[ind].fm_strength_const[ind2]=false; + break; + case OUTPUT: + osc[ind].output_const=false; break; + case WAVEFORM: + osc[ind].waveform_const=false; break; + case FACTOR: + osc[ind].factor_const=false; break; + case TREMOLO: + osc[ind].tremolo_depth_const=false; break; + case TREM_LFO: + osc[ind].tremolo_lfo_const=false; break; + case VIBRATO: + osc[ind].vibrato_depth_const=false; break; + case VIB_LFO: + osc[ind].vibrato_lfo_const=false; break; + case ATTACK: + env[ind].attack_const=false; break; + case DECAY: + env[ind].decay_const=false; break; + case SUSTAIN: + env[ind].sustain_const=false; break; + case RELEASE: + env[ind].release_const=false; break; + case HOLD: + env[ind].hold_const=false; break; + case KSR: + osc[ind].ksr_const=false; break; + case KSL: + osc[ind].ksl_const=false; break; + case SYNC: + osc[ind].sync_const=false; break; + case FILTER_ENABLED: + filter.enabled_const=false; break; + case FILTER_ENV_AMOUNT: + filter.env_amount_const=false; break; + case FILTER_ATTACK: + filter.env_settings.attack_const=false; break; + case FILTER_DECAY: + filter.env_settings.decay_const=false; break; + case FILTER_SUSTAIN: + filter.env_settings.sustain_const=false; break; + case FILTER_RELEASE: + filter.env_settings.release_const=false; break; + case FILTER_HOLD: + filter.env_settings.hold_const=false; break; + case FILTER_OFFSET: + filter.freqfactor_offset_const=false; break; + case FILTER_RESONANCE: + filter.resonance_const=false; break; + case FILTER_TREMOLO: + filter.trem_strength_const=false; break; + case FILTER_TREM_LFO: + filter.trem_lfo_const=false; break; + case SYNC_FACTOR: + sync_factor_const=false; break; + default: + throw string("unknown variable ('"+array+"')"); + } + + + + break; + + case 3: //read controller default values + //ignored + break; + } + } + } + } + else + throw string ("could not open '"+fn+"'"); +} + + +program_t Parser::get_result() +{ + program_t r; + + r.n_osc=n_osc; + r.osc=osc; + r.env=env; + r.filter=filter; + r.sync_factor=sync_factor; + r.sync_factor_const=sync_factor_const; + + return r; +} diff --git a/note_compiler/parser.h b/note_compiler/parser.h new file mode 100644 index 0000000..3e60051 --- /dev/null +++ b/note_compiler/parser.h @@ -0,0 +1,40 @@ +#ifndef __PARSER_H__ +#define __PARSET_H__ + + +#include <set> +#include <map> +#include <list> +#include <string> + +#include "../synth/fixed.h" +#include "programs.h" + +using namespace std; + +class Parser +{ + public: + Parser(); + ~Parser(); + void parse(string fn); + + program_t get_result(); + + private: + void init_stuff(); + void uninit_stuff(); + static string extract_array_name(string s); + static int extract_array_index(string s, int dim); + + int n_osc; + oscillator_t *osc; + env_settings_t *env; + filter_params_t filter; + + fixed_t sync_factor; + bool sync_factor_const; +}; + + +#endif diff --git a/note_compiler/programs.h b/note_compiler/programs.h new file mode 100644 index 0000000..daf238f --- /dev/null +++ b/note_compiler/programs.h @@ -0,0 +1,119 @@ +#ifndef __PROGRAMS_H__ +#define __PROGRAMS_H__ + + +#include "../synth/fixed.h" + +enum parameter_enum +{ + MODULATION=0, + OUTPUT, + WAVEFORM, + FACTOR, + TREMOLO, + TREM_LFO, + VIBRATO, + VIB_LFO, + ATTACK, + DECAY, + SUSTAIN, + RELEASE, + HOLD, + KSR, + KSL, + SYNC, + FILTER_ENABLED, + FILTER_ENV_AMOUNT, + FILTER_ATTACK, + FILTER_DECAY, + FILTER_SUSTAIN, + FILTER_RELEASE, + FILTER_HOLD, + FILTER_OFFSET, + FILTER_RESONANCE, + FILTER_TREMOLO, + FILTER_TREM_LFO, + SYNC_FACTOR, + + + PARAMETER_N_ENTRIES, + UNKNOWN=-1 +}; + + +struct oscillator_t +{ + fixed_t *fm_strength; + bool *fm_strength_const; + fixed_t output; + bool output_const; + int waveform; + bool waveform_const; + fixed_t factor; + bool factor_const; + + fixed_t tremolo_depth; + bool tremolo_depth_const; + int tremolo_lfo; + bool tremolo_lfo_const; + fixed_t vibrato_depth; + bool vibrato_depth_const; + int vibrato_lfo; + bool vibrato_lfo_const; + + bool have_custom_wave; + + int n_osc; + + float ksl; + bool ksl_const; + float ksr; + bool ksr_const; + + bool sync; + bool sync_const; +}; + +struct env_settings_t +{ + float attack; + bool attack_const; + float decay; + bool decay_const; + float sustain; + bool sustain_const; + float release; + bool release_const; + bool hold; + bool hold_const; +}; + +struct filter_params_t +{ + bool enabled; + bool enabled_const; + float resonance; + bool resonance_const; + float freqfactor_offset; + bool freqfactor_offset_const; + float env_amount; + bool env_amount_const; + int trem_strength; + bool trem_strength_const; + int trem_lfo; + bool trem_lfo_const; + env_settings_t env_settings; +}; + +struct program_t +{ + int n_osc; + oscillator_t *osc; + env_settings_t *env; + filter_params_t filter; + + fixed_t sync_factor; + bool sync_factor_const; +}; + +#endif diff --git a/note_compiler/util.cpp b/note_compiler/util.cpp new file mode 100644 index 0000000..f73b8bb --- /dev/null +++ b/note_compiler/util.cpp @@ -0,0 +1,208 @@ +#include <iostream> +#include <sstream> + +#include "util.h" + +string IntToStr(int i) +{ + ostringstream s; + s<<i; + return s.str(); +} + +string IntToStrHex(int i) +{ + ostringstream s; + s<<std::hex << i; + return s.str(); +} + +bool isnum(string s) +{ + for (size_t i=0;i<s.length();i++) + if (!isdigit(s[i])) + return false; + + return true; +} + +bool isfloat(string s) +{ + return (s.find_first_not_of("0123456789.")==string::npos); +} + + +string remove_all_spaces(string s) +{ + string result; + + for (size_t i=0; i<s.length(); i++) + if ((s[i]!=' ') && (s[i]!='\t')) + result+=s[i]; + + return result; +} + +string trim_spaces(string s) +{ + string result; + int i; + + for (i=0;i<s.length();i++) + if ((s[i]!=' ') && (s[i]!='\t')) + break; + + if (i!=s.length()) + { + result=s.substr(i); + for (i=result.length()-1;i>=0;i--) + if ((result[i]!=' ') && (result[i]!='\t')) + break; + + if (i>=0) + return result.substr(0,i+1); + else + return ""; + } + else + { + return ""; + } +} + +/* +void output_warning(string s) +{ + cout << s << endl; + if (fatal_warnings) throw string(s); +} + +void output_note(string s) +{ + if (!quiet) cout << s << endl; +} + +void output_verbose(string s) +{ + if (verbose) cout << s << endl; +} +*/ + + +bool param_needs_index(parameter_enum p) +{ + switch (p) + { + case FILTER_ENABLED: + + case FILTER_ATTACK: + case FILTER_DECAY: + case FILTER_SUSTAIN: + case FILTER_RELEASE: + case FILTER_HOLD: + case FILTER_ENV_AMOUNT: + + case FILTER_OFFSET: + case FILTER_RESONANCE: + + case FILTER_TREMOLO: + case FILTER_TREM_LFO: + + case SYNC_FACTOR: + return false; + + default: return true; + } +} + +parameter_enum param_to_enum(string param) +{ + if (param=="mod") + return MODULATION; + else if (param=="out") + return OUTPUT; + else if (param=="waveform") + return WAVEFORM; + else if (param=="sync") + return SYNC; + else if (param=="factor") + return FACTOR; + else if (param=="trem") + return TREMOLO; + else if (param=="trem_lfo") + return TREM_LFO; + else if (param=="vib") + return VIBRATO; + else if (param=="vib_lfo") + return VIB_LFO; + else if (param=="attack") + return ATTACK; + else if (param=="decay") + return DECAY; + else if (param=="sustain") + return SUSTAIN; + else if (param=="release") + return RELEASE; + else if (param=="hold") + return HOLD; + else if (param=="ksl") + return KSL; + else if (param=="ksr") + return KSR; + else if (param=="filter.enabled") + return FILTER_ENABLED; + else if (param=="filter.env_amount") + return FILTER_ENV_AMOUNT; + else if (param=="filter.attack") + return FILTER_ATTACK; + else if (param=="filter.decay") + return FILTER_DECAY; + else if (param=="filter.sustain") + return FILTER_SUSTAIN; + else if (param=="filter.release") + return FILTER_RELEASE; + else if (param=="filter.hold") + return FILTER_HOLD; + else if (param=="filter.offset") + return FILTER_OFFSET; + else if (param=="filter.resonance") + return FILTER_RESONANCE; + else if (param=="filter.trem") + return FILTER_TREMOLO; + else if (param=="filter.trem_lfo") + return FILTER_TREM_LFO; + else if (param=="sync_factor") + return SYNC_FACTOR; + else + return UNKNOWN; +} + +string extract_var(string s) +{ + size_t p; + p=s.find('='); + if (p!=string::npos) + return s.substr(0,p); + else + return ""; +} + +string extract_val(string s) +{ + size_t p; + p=s.find('='); + if (p!=string::npos) + return s.substr(p+1); + else + return s; +} + +string fileext(string f) +{ + size_t pos; + pos=f.rfind('.'); + if (pos!=string::npos) + return f.substr(pos+1); + else + return ""; +} diff --git a/note_compiler/util.h b/note_compiler/util.h new file mode 100644 index 0000000..e571c7d --- /dev/null +++ b/note_compiler/util.h @@ -0,0 +1,31 @@ +#ifndef __UTIL_H__ +#define __UTIL_H__ + +#include <string> +#include "programs.h" + +using namespace std; + +string IntToStr(int i); +string IntToStrHex(int i); + +bool isnum(string s); +bool isfloat(string s); + +string remove_all_spaces(string s); +string trim_spaces(string s); + +void output_warning(string s); +void output_note(string s); +void output_verbose(string s); + +bool param_needs_index(parameter_enum p); +parameter_enum param_to_enum(string param); + +string extract_var(string s); +string extract_val(string s); + +string fileext(string f); + + +#endif |