summaryrefslogtreecommitdiff
path: root/note_compiler
diff options
context:
space:
mode:
Diffstat (limited to 'note_compiler')
-rw-r--r--note_compiler/.depend4
-rw-r--r--note_compiler/IDEE29
-rw-r--r--note_compiler/Makefile9
-rw-r--r--note_compiler/main.cpp29
-rw-r--r--note_compiler/parser.cpp454
-rw-r--r--note_compiler/parser.h40
-rw-r--r--note_compiler/programs.h119
-rw-r--r--note_compiler/util.cpp208
-rw-r--r--note_compiler/util.h31
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