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/.gitignore1
-rw-r--r--note_compiler/IDEE30
-rw-r--r--note_compiler/Makefile34
-rw-r--r--note_compiler/howtocompile.txt4
-rw-r--r--note_compiler/main.cpp779
-rw-r--r--note_compiler/parser.cpp504
-rw-r--r--note_compiler/parser.h16
-rw-r--r--note_compiler/plugin_factory/Makefile34
l---------note_compiler/plugin_factory/channel.cpp1
l---------note_compiler/plugin_factory/channel.h1
l---------note_compiler/plugin_factory/cli.cpp1
l---------note_compiler/plugin_factory/cli.h1
l---------note_compiler/plugin_factory/defines.cpp1
l---------note_compiler/plugin_factory/defines.h1
l---------note_compiler/plugin_factory/envelope.cpp1
l---------note_compiler/plugin_factory/envelope.h1
l---------note_compiler/plugin_factory/filter.cpp1
l---------note_compiler/plugin_factory/filter.h1
l---------note_compiler/plugin_factory/fixed.h1
l---------note_compiler/plugin_factory/globals.cpp1
l---------note_compiler/plugin_factory/globals.h1
-rw-r--r--note_compiler/plugin_factory/infile.cpp392
l---------note_compiler/plugin_factory/jack.cpp1
l---------note_compiler/plugin_factory/jack.h1
l---------note_compiler/plugin_factory/load.cpp1
l---------note_compiler/plugin_factory/load.h1
l---------note_compiler/plugin_factory/main.cpp1
l---------note_compiler/plugin_factory/note.cpp1
l---------note_compiler/plugin_factory/note.h1
l---------note_compiler/plugin_factory/note_funcs.h1
l---------note_compiler/plugin_factory/note_loader.cpp1
l---------note_compiler/plugin_factory/note_loader.h1
l---------note_compiler/plugin_factory/note_skel.cpp1
l---------note_compiler/plugin_factory/note_skel.h1
l---------note_compiler/plugin_factory/parser.cpp1
l---------note_compiler/plugin_factory/parser.h1
l---------note_compiler/plugin_factory/programs.cpp1
l---------note_compiler/plugin_factory/programs.h1
l---------note_compiler/plugin_factory/readwave.cpp1
l---------note_compiler/plugin_factory/readwave.h1
l---------note_compiler/plugin_factory/util.cpp1
l---------note_compiler/plugin_factory/util.h1
-rw-r--r--note_compiler/programs.h121
-rw-r--r--note_compiler/templates/ctor.foot11
-rw-r--r--note_compiler/templates/get_sample.123
-rw-r--r--note_compiler/templates/head.148
-rw-r--r--note_compiler/templates/head.211
-rw-r--r--note_compiler/templates/interface.119
-rw-r--r--note_compiler/templates/set_param.127
-rw-r--r--note_compiler/templates/set_param.filter7
-rw-r--r--note_compiler/templates/set_param.filterenv34
-rw-r--r--note_compiler/templates/set_param.nofilter13
-rw-r--r--note_compiler/templates/set_param.nofilterenv7
-rw-r--r--note_compiler/util.cpp208
-rw-r--r--note_compiler/util.h31
56 files changed, 2391 insertions, 0 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/.gitignore b/note_compiler/.gitignore
new file mode 100644
index 0000000..86a7c8e
--- /dev/null
+++ b/note_compiler/.gitignore
@@ -0,0 +1 @@
+compiler
diff --git a/note_compiler/IDEE b/note_compiler/IDEE
new file mode 100644
index 0000000..01fb251
--- /dev/null
+++ b/note_compiler/IDEE
@@ -0,0 +1,30 @@
+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.)
+ - wenn vom user angegeben ("variable:")
+
+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
new file mode 100644
index 0000000..6a08b81
--- /dev/null
+++ b/note_compiler/Makefile
@@ -0,0 +1,34 @@
+CXX=g++
+CFLAGS=-Wall -g
+CXXFLAGS=$(CFLAGS)
+LDFLAGS=-lm `pkg-config --cflags --libs jack`
+
+OBJ=main.o parser.o util.o
+BIN=compiler
+
+DEPENDFILE = .depend
+
+
+SRC = $(OBJ:%.o=%.cpp)
+
+all: $(BIN)
+
+
+$(BIN): $(OBJ)
+ $(CXX) $(CXXFLAGS) -o $(BIN) $(OBJ) $(LDFLAGS)
+
+
+depend dep: $(SRC)
+ $(CC) -MM $(SRC) > $(DEPENDFILE)
+
+-include $(DEPENDFILE)
+
+
+%.o: %.cpp
+ $(CXX) $(CXXFLAGS) -c $<
+
+.PHONY: clean dep depend
+
+clean:
+ rm -f $(OBJ) $(BIN)
+
diff --git a/note_compiler/howtocompile.txt b/note_compiler/howtocompile.txt
new file mode 100644
index 0000000..3bb6cd8
--- /dev/null
+++ b/note_compiler/howtocompile.txt
@@ -0,0 +1,4 @@
+gcc -fPIC -g -c -Wall a.c
+gcc -fPIC -g -c -Wall b.c
+gcc -shared -fPIC -Wl,-soname,libmystuff.so.1 \
+ -o libmystuff.so.1.0.1 a.o b.o -lc
diff --git a/note_compiler/main.cpp b/note_compiler/main.cpp
new file mode 100644
index 0000000..47ed685
--- /dev/null
+++ b/note_compiler/main.cpp
@@ -0,0 +1,779 @@
+//TODO: auf unbenutzte envelopes achten!
+
+#include <iostream>
+#include <fstream>
+
+#include "parser.h"
+#include "programs.h"
+#include "util.h"
+#include "../synth/fixed.h"
+
+using namespace std;
+
+ostream &out=cout;
+ostream &comment=cout;
+program_t prog;
+
+void write_empty_line()
+{
+ out << "\n";
+}
+
+void include_file(string file)
+{
+ file="templates/"+file;
+
+ ifstream in;
+ in.open(file.c_str());
+ if (!in.good())
+ throw string ("include: could not open '"+file+"'");
+
+ char tempbuf[2000];
+ while (!in.eof())
+ {
+ in.getline(tempbuf, sizeof(tempbuf));
+ out << tempbuf << "\n";
+ }
+}
+
+void write_env_decs()
+{
+ for (int i=0;i<prog.n_osc;i++)
+ if (prog.env[i].enabled)
+ out << "\t\tEnvelope *env"<<i<<";\n";
+ else
+ {
+ comment << "\t\t//envelope"<<i<<" is unused\n";
+ if ( (prog.osc[i].ksl!=0) || (prog.osc[i].ksl_const==false) )
+ out << "\t\tfixed_t kslval"<<i<<";\n";
+ }
+}
+void write_oscval_decs()
+{
+ out << "\t\tfixed_t *oscval;\n"
+ "\t\tfixed_t *old_oscval;\n";
+}
+void write_osc_decs()
+{
+ for (int i=0;i<prog.n_osc;i++)
+ out << "\t\toscillator_t osc"<<i<<";\n";
+}
+void write_osc_decs2()
+{
+ for (int i=0;i<prog.n_osc;i++)
+ out << "\t\t\toscillator_t osc"<<i<<";\n";
+}
+
+void write_sync_decs()
+{
+ if ((prog.sync_factor!=0) || (prog.sync_factor_const==false))
+ out << "\t\tfixed_t sync_factor;\n"
+ "\t\tfixed_t sync_phase;\n";
+ else
+ comment << "\t\t//sync is disabled\n";
+}
+
+void write_filter_decs()
+{
+ if ((prog.filter.enabled==true) || (prog.filter.enabled_const==false))
+ {
+ out << "\t\tLowPassFilter filter;\n"
+ "\t\tfilter_params_t filter_params;\n"
+ "\t\tint filter_update_counter;\n";
+ if (prog.filter.env_settings.enabled==true)
+ out << "\t\tEnvelope *filter_envelope;\n";
+ else
+ comment << "\t\t//filter envelope is disabled\n";
+
+ }
+ else
+ comment << "\t\t//filter is disabled\n";
+}
+
+void write_pfactor_decs()
+{
+ out << "\t\tpfactor_value_t pfactor;\n"
+ "\t\tstruct\n"
+ "\t\t{\n";
+ write_osc_decs2();
+ if ((prog.filter.enabled==true) || (prog.filter.enabled_const==false))
+ out << "\t\t\tfilter_params_t filter_params;\n";
+ else
+ comment << "\t\t\t//filter is disabled\n";
+ out << "\t\t} orig;\n";
+}
+
+
+void write_ctor()
+{
+ int i;
+ string tabtmp="";
+
+ out << "Note::Note(int n, float v, program_t &prg, jack_nframes_t pf, fixed_t pb, int prg_no)\n"
+ "{\n"
+ "\tcurr_prg=&prg;\n"
+ "\t\n"
+ "\toscval=new fixed_t["<< prog.n_osc <<"];\n"
+ "\told_oscval=new fixed_t["<< prog.n_osc <<"];\n"
+ "\tfor (int i=0;i<"<<prog.n_osc<<";i++)\n"
+ "\t\toscval[i]=old_oscval[i]=0;\n"
+ "\t\n"
+ "\tpfactor.out=new fixed_t ["<<prog.n_osc<<"];\n"
+ "\tpfactor.fm=new fixed_t* ["<<prog.n_osc<<"];\n"
+ "\tfor (int i=0;i<"<<prog.n_osc<<";i++)\n"
+ "\t\tpfactor.fm[i]=new fixed_t ["<<prog.n_osc<<"];\n"
+ "\t\n";
+
+ for (i=0;i<prog.n_osc;i++)
+ if (prog.env[i].enabled)
+ out << "\tenv"<<i<<"=new Envelope (prg.env_settings["<<i<<"]);\n";
+ else
+ comment << "\t//envelope"<<i<<" is disabled\n";
+
+ out << "\t\n";
+
+ for (i=0;i<prog.n_osc;i++)
+ {
+ out << "\tosc"<<i<<"=prg.osc_settings["<<i<<"];\n"
+ "\torig.osc"<<i<<"=prg.osc_settings["<<i<<"];\n";
+ }
+
+ out << "\t\n";
+
+ out << "\t//initalize oscillator.phase to multiples of their wave resolution\n";
+ for (i=0;i<prog.n_osc;i++)
+ {
+ out << "\tosc"<<i<<".phase=";
+ if (prog.osc[i].have_custom_wave)
+ out << "init_custom_osc_phase(osc"<<i<<".custom_wave->wave_len, osc"<<i<<".custom_wave->samp_rate);\n";
+ else
+ out << "ONE * PHASE_INIT;\n";
+ }
+
+ out << "\t\n"
+ "\tdo_ksl();\n"
+ "\t\n"
+ "\t\n";
+
+ if ((prog.filter.enabled==true) || (prog.filter.enabled_const==false))
+ {
+ //a filter_params and orig.filter_params member exist
+ out << "\tfilter_params=prg.filter_settings;\n"
+ "\torig.filter_params=prg.filter_settings;\n";
+
+ if (prog.filter.enabled_const==false)
+ {
+ out << "\tif (filter_params.enabled)\n"
+ "\t{\n";
+ tabtmp="\t";
+ }
+ out << tabtmp << "\tfilter_envelope=new Envelope(filter_params.env_settings);\n" <<
+ tabtmp << "\tfilter_update_counter=filter_update_frames;\n";
+ if (prog.filter.enabled_const==false)
+ out << "\t}\n";
+ tabtmp="";
+
+ out << "\t\n"
+ "\t\n";
+ }
+
+
+ if ((prog.sync_factor!=0) || (prog.sync_factor_const==false))
+ out << "\tsync_factor=prg.sync_factor;\n"
+ "\tsync_phase=0;\n"
+ "\t\n"
+ "\t\n";
+
+
+ include_file("ctor.foot");
+}
+
+void write_dtor()
+{
+ int i;
+
+ out << "Note::~Note()\n"
+ "{\n";
+
+ for (i=0;i<prog.n_osc;i++)
+ {
+ out << "\tdelete [] osc"<<i<<".fm_strength;\n";
+
+ if (prog.env[i].enabled)
+ out << "\tdelete env"<<i<<";\n";
+ else
+ comment << "\t//envelope"<<i<<" is disabled\n";
+
+ out << "\tdelete pfactor.fm["<<i<<"];\n";
+
+ out << "\t\n";
+ }
+
+ out << "\t\n"
+ "\tdelete [] oscval;\n"
+ "\tdelete [] old_oscval;\n"
+ "\t\n"
+ "\tdelete [] pfactor.out;\n"
+ "\tdelete [] pfactor.fm;\n"
+ "}\n";
+}
+
+
+void write_recalc_factors()
+{
+ out << "void Note::recalc_factors()\n"
+ "{\n";
+
+ if ((prog.filter.enabled==true) || (prog.filter.enabled_const==false))
+ {
+ out << "\tpfactor.filter_env=calc_pfactor(curr_prg->pfactor.filter_env, vel);\n"
+ "\tpfactor.filter_res=calc_pfactor(curr_prg->pfactor.filter_res, vel);\n"
+ "\tpfactor.filter_offset=calc_pfactor(curr_prg->pfactor.filter_offset, vel);\n"
+ "\t\n";
+ }
+
+ out << "\tfor (int i=0;i<"<<prog.n_osc<<";i++)\n"
+ "\t{\n"
+ "\t\tpfactor.out[i]=calc_pfactor(curr_prg->pfactor.out[i], vel);\n"
+ "\t\t\n"
+ "\t\tfor (int j=0;j<"<<prog.n_osc<<";j++)\n"
+ "\t\t\tpfactor.fm[i][j]=calc_pfactor(curr_prg->pfactor.fm[i][j], vel);\n"
+ "\t}\n";
+
+ out << "}\n";
+}
+
+void write_apply_pfactor()
+{
+ out << "void Note::apply_pfactor()\n"
+ "{\n";
+
+ if ((prog.filter.enabled==true) || (prog.filter.enabled_const==false))
+ out << "\tfilter_params.env_amount=orig.filter_params.env_amount*pfactor.filter_env /ONE;\n"
+ "\tfilter_params.freqfactor_offset=orig.filter_params.freqfactor_offset*pfactor.filter_offset /ONE;\n"
+ "\tfilter_params.resonance=orig.filter_params.resonance*pfactor.filter_res /ONE;\n"
+ "\t\n";
+
+ for (int i=0;i<prog.n_osc;i++)
+ {
+ out << "\tosc"<<i<<".output=orig.osc"<<i<<".output*pfactor.out["<<i<<"] >>SCALE;\n"
+ "\tfor (int i=0;i<"<<prog.n_osc<<";i++)\n"
+ "\t\tosc"<<i<<".fm_strength[i]=orig.osc"<<i<<".fm_strength[i]*pfactor.fm["<<i<<"][i] >>SCALE;\n";
+ }
+
+ out << "}\n";
+}
+
+void write_still_active()
+{
+ out << "bool Note::still_active()\n"
+ "{\n";
+
+ out << "\tif ( ";
+ if (prog.env[0].enabled)
+ out << " ((osc"<<0<<".output>0) && (env"<<0<<"->still_active()))";
+ else
+ out << " // envelope"<<0<<" is disabled";
+
+ for (int i=1;i<prog.n_osc;i++)
+ {
+ if (prog.env[i].enabled)
+ out << "\n\t || ((osc"<<i<<".output>0) && (env"<<i<<"->still_active()))";
+ else
+ out << "\n\t /* envelope"<<i<<" is disabled */";
+ }
+
+ out << " )\n"
+ "\t\treturn true;\n"
+ "\telse\n"
+ "\t\treturn false;\n";
+
+
+ out << "}\n";
+}
+
+void write_release()
+{
+ out << "void Note::release()\n"
+ "{\n";
+
+ for (int i=0;i<prog.n_osc;i++)
+ {
+ if (prog.env[i].enabled)
+ out << "\tenv"<<i<<"->release_key();\n";
+ else
+ comment << "\t//envelope"<<i<<" is disabled\n";
+ }
+
+
+ if (prog.filter.enabled && prog.filter.enabled_const)
+ out << "\n\tfilter_envelope->release_key();\n";
+ else if (prog.filter.enabled_const==false)
+ out << "\n\tif (filter_params.enabled)\n"
+ "\t\tfilter_envelope->release_key();\n";
+
+ out << "}\n";
+}
+
+void write_release_quickly()
+{
+ out << "void Note::release_quickly(jack_nframes_t maxt)\n"
+ "{\n";
+
+ for (int i=0;i<prog.n_osc;i++)
+ {
+ if (prog.env[i].enabled)
+ out << "\tif (env"<<i<<"->get_release() > maxt)\n"
+ "\t\tenv"<<i<<"->set_release(maxt);\n"
+ "\tenv"<<i<<"->release_key();\n"
+ "\t\n";
+ else
+ comment << "\t//envelope"<<i<<" is disabled\n"
+ "\t\n";
+ }
+
+ out << "}\n";
+}
+
+void write_reattack()
+{
+ out << "void Note::reattack()\n"
+ "{\n";
+
+ for (int i=0;i<prog.n_osc;i++)
+ {
+ if (prog.env[i].enabled)
+ out << "\tenv"<<i<<"->reattack();\n";
+ else
+ comment << "\t//envelope"<<i<<" is disabled\n";
+ }
+
+
+ if (prog.filter.enabled && prog.filter.enabled_const)
+ out << "\n\tfilter_envelope->reattack();\n";
+ else if (prog.filter.enabled_const==false)
+ out << "\n\tif (filter_params.enabled)\n"
+ "\t\tfilter_envelope->reattack();\n";
+
+ out << "}\n";
+}
+
+void write_do_ksr()
+{
+ out << "void Note::do_ksr()\n"
+ "{\n";
+
+ for (int i=0;i<prog.n_osc;i++)
+ {
+ if (prog.env[i].enabled)
+ out << "\tenv"<<i<<"->set_ratefactor(1.0 / pow(freq>>SCALE, osc"<<i<<".ksr));\n";
+ else
+ comment << "\t//envelope"<<i<<" is disabled\n";
+ }
+
+ out << "}\n";
+}
+
+void write_do_ksl()
+{
+ bool need_ksl=false;
+
+ out << "void Note::do_ksl()\n"
+ "{\n";
+
+
+ for (int i=0;i<prog.n_osc;i++)
+ if ( (prog.osc[i].ksl!=0) || (prog.osc[i].ksl_const==false) )
+ {
+ need_ksl=true;
+ break;
+ }
+
+ if (need_ksl)
+ {
+ out << "\tdouble tempfreq=double ( freq >> SCALE );\n"
+ "\t\n";
+
+ for (int i=0;i<prog.n_osc;i++)
+ {
+ if ( (prog.osc[i].ksl==0) && (prog.osc[i].ksl_const) )
+ comment << "\t//ksl is disabled for oscillator"<<i<<"\n";
+ else
+ {
+ string kslstring = "( (osc"+IntToStr(i)+".ksl==0) ? ONE : ( fixed_t(double(ONE) / pow(tempfreq, osc"+IntToStr(i)+".ksl)) ) )";
+
+ if (prog.env[i].enabled)
+ out << "\tenv"<<i<<"->set_max( "<<kslstring<<" );\n";
+ else
+ out << "\tkslval"<<i<<"="<<kslstring<<";\n";
+ }
+ }
+ }
+ out << "}\n";
+}
+
+void write_get_sample()
+{
+ string tabtemp="";
+
+ include_file("get_sample.1");
+
+ { //SYNC TODO
+ if (prog.sync_factor_const==false)
+ {
+ out << "\tif (sync_factor)\n"
+ "\t{\n";
+
+ tabtemp="\t";
+ }
+
+ if ( (prog.sync_factor_const==false) || (prog.sync_factor!=0) )
+ {
+ string temp;
+ if (prog.sync_factor_const)
+ temp=IntToStr(prog.sync_factor);
+ else
+ temp="sync_factor";
+
+ out << tabtemp << "\tsync_phase+=(actual_freq*"<<temp<<"/samp_rate) >> SCALE;\n"
+ << tabtemp << "\t\n"
+ << tabtemp << "\tif (sync_phase >= ONE)\n"
+ << tabtemp << "\t{\n"
+ << tabtemp << "\t\tsync_phase-=ONE;\n"
+ << tabtemp << "\t\t\n";
+
+ for (int i=0;i<prog.n_osc;i++)
+ {
+ string initstring;
+ if (prog.osc[i].have_custom_wave)
+ initstring="init_custom_osc_phase(osc"+IntToStr(i)+".custom_wave->wave_len, osc"+IntToStr(i)+".custom_wave->samp_rate)";
+ else
+ initstring="ONE * PHASE_INIT";
+
+ string full_command="osc"+IntToStr(i)+".phase="+initstring+";\n";
+
+ if ( prog.osc[i].sync_const && prog.osc[i].sync )
+ out << tabtemp << "\t\t" << full_command;
+ else if ( prog.osc[i].sync_const && (prog.osc[i].sync==false) )
+ comment << tabtemp << "\t\t//sync is disabled for osc"<<i<<"\n";
+ else //if (prog.osc[i].sync_const==false)
+ out << tabtemp << "\t\tif (osc"<<i<<".sync) " <<full_command;
+ }
+
+ out << tabtemp << "\t}\n";
+
+ }
+ else //if ( (prog.sync_factor_const==true) && (prog.sync_factor==0) )
+ comment << "\t//sync is disabled\n";
+
+ if (prog.sync_factor_const==false)
+ {
+ out << "\t}\n";
+
+ tabtemp="";
+ }
+ out << "\t\n\t\n";
+ } //SYNC TODO
+
+ { //OSCS TODO
+ string outstring_scaled="", outstring_nonscaled="";
+
+ for (int i=0;i<prog.n_osc;i++)
+ {
+ // increment phase
+ string phase_inc_lfo = "( (curr_lfo[osc"+IntToStr(i)+".vibrato_lfo][osc"+IntToStr(i)+".vibrato_depth]*actual_freq >>SCALE)*osc"+IntToStr(i)+".factor/samp_rate)>>SCALE";
+ string phase_inc = "(actual_freq*osc"+IntToStr(i)+".factor/samp_rate)>>SCALE";
+ if (prog.osc[i].vibrato_depth_const == false)
+ out << "\tosc"<<i<<".phase+= ( (osc"<<i<<".vibrato_depth==0) ? ("<<phase_inc<<") : ("<<phase_inc_lfo<<") );\n";
+ else if (prog.osc[i].vibrato_depth == 0)
+ out << "\tosc"<<i<<".phase+= "<<phase_inc<<";\n";
+ else
+ out << "\tosc"<<i<<".phase+= "<<phase_inc_lfo<<";\n";
+
+ // calculate phase modulation
+ string fm=""; //TODO FINDMICH: das >>SCALE fehlt noch!
+ for (int j=0;j<prog.n_osc;j++)
+ {
+ if (prog.osc[i].fm_strength_const[j] == false)
+ fm+="+ (old_oscval["+IntToStr(j)+"] * osc"+IntToStr(i)+".fm_strength["+IntToStr(j)+"]) ";
+ else if (prog.osc[i].fm_strength[j]!=0)
+ fm+="+ (old_oscval["+IntToStr(j)+"] * "+IntToStr(prog.osc[i].fm_strength[j])+") ";
+ }
+
+ // generate string for modulated phase
+ string phase;
+ if (fm!="")
+ phase="( osc"+IntToStr(i)+".phase + ( "+fm+">>SCALE ) )";
+ else
+ phase="osc"+IntToStr(i)+".phase";
+
+ // generate string for wave
+ string wavetemp;
+ if (prog.osc[i].have_custom_wave)
+ {
+ string cw="osc"+IntToStr(i)+".custom_wave";
+ wavetemp=cw+"->wave[ ( "+phase+" * "+cw+"->samp_rate >>(2*SCALE) ) % "+cw+"->wave_len ]";
+ }
+ else
+ {
+ string waveformtemp;
+ if (prog.osc[i].waveform_const)
+ waveformtemp=IntToStr(prog.osc[i].waveform);
+ else
+ waveformtemp="osc"+IntToStr(i)+".waveform";
+
+ wavetemp="wave["+waveformtemp+"][ ( "+phase+" * WAVE_RES >>SCALE ) % WAVE_RES ]";
+ }
+
+ // finally write "oscval[n]=..."
+ out << "\toscval["<<i<<"] = "<<wavetemp;
+ // figure out whether we need to multiply with the env, with ksl or not at all
+ if (prog.env[i].enabled)
+ out<<" * env"<<i<<"->get_level() >>SCALE;\n";
+ else if ( (prog.osc[i].ksl!=0) || (prog.osc[i].ksl_const==false) )
+ // i.e.: if osc[i] has a kslval variable
+ out<<" * kslval"<<i<<" >>SCALE;\n";
+ else //no envelope, no kslval
+ out<<";\n";
+
+
+ // maybe do tremolo
+ string tremlfo;
+ if (prog.osc[i].tremolo_lfo_const==false)
+ tremlfo="osc"+IntToStr(i)+".tremolo_lfo";
+ else
+ tremlfo=IntToStr(prog.osc[i].tremolo_lfo);
+
+ if (prog.osc[i].tremolo_depth_const==false)
+ out << "\tif (osc"<<i<<".tremolo_depth)\n"
+ "\t\toscval["<<i<<"] = oscval["<<i<<"] * curr_lfo["<<tremlfo<<"][osc"<<i<<".tremolo_depth] >>SCALE;\n";
+ else if (prog.osc[i].tremolo_depth!=0)
+ out << "\toscval["<<i<<"] = oscval["<<i<<"] * curr_lfo["<<tremlfo<<"]["<<prog.osc[i].tremolo_depth<<"] >>SCALE;\n";
+ else
+ comment << "\t//oscillator"<<i<<" has no tremolo\n";
+
+ // maybe add this osc to the output
+ if (prog.osc[i].output_const==false)
+ outstring_scaled+="+ osc"+IntToStr(i)+".output*oscval["+IntToStr(i)+"] ";
+ else if (prog.osc[i].output==ONE)
+ outstring_nonscaled+="+ oscval["+IntToStr(i)+"] ";
+ else if (prog.osc[i].output==ONE/2)
+ outstring_nonscaled+="+ oscval["+IntToStr(i)+"]/2 ";
+ else if (prog.osc[i].output==ONE/3)
+ outstring_nonscaled+="+ oscval["+IntToStr(i)+"]/3 ";
+ else if (prog.osc[i].output==ONE/4)
+ outstring_nonscaled+="+ oscval["+IntToStr(i)+"]/4 ";
+ else if (prog.osc[i].output==ONE/5)
+ outstring_nonscaled+="+ oscval["+IntToStr(i)+"]/5 ";
+ else if (prog.osc[i].output==ONE/6)
+ outstring_nonscaled+="+ oscval["+IntToStr(i)+"]/6 ";
+ else if (prog.osc[i].output==ONE/7)
+ outstring_nonscaled+="+ oscval["+IntToStr(i)+"]/7 ";
+ else if (prog.osc[i].output==ONE/8)
+ outstring_nonscaled+="+ oscval["+IntToStr(i)+"]/8 ";
+ else if (prog.osc[i].output==ONE/9)
+ outstring_nonscaled+="+ oscval["+IntToStr(i)+"]/9 ";
+ else if (prog.osc[i].output==ONE/10)
+ outstring_nonscaled+="+ oscval["+IntToStr(i)+"]/10 ";
+ else if (prog.osc[i].output==ONE*2)
+ outstring_nonscaled+="+ oscval["+IntToStr(i)+"]*2 ";
+ else if (prog.osc[i].output==ONE*3)
+ outstring_nonscaled+="+ oscval["+IntToStr(i)+"]*3 ";
+ else if (prog.osc[i].output==ONE*4)
+ outstring_nonscaled+="+ oscval["+IntToStr(i)+"]*4 ";
+ else if (prog.osc[i].output!=0)
+ outstring_scaled+="+ "+IntToStr(prog.osc[i].output)+"*oscval["+IntToStr(i)+"] ";
+ //else: output is 0, ignore it
+
+ out << "\t\n";
+ }
+
+ // generate, check and write the final outstring
+ string outstring="";
+ if (outstring_scaled!="")
+ outstring+="( "+outstring_scaled+" >>SCALE )";
+ if (outstring_nonscaled!="")
+ outstring+=" "+outstring_nonscaled;
+
+ if (outstring=="")
+ throw string ("this instrument has no output at all!");
+
+ out << "\tfixed_t out = "<<outstring<<";\n"
+ "\t\n"
+ "\t\n";
+ } //OSCS TODO
+
+ { //FILTER TODO
+ tabtemp="";
+
+ if (prog.filter.enabled_const==false)
+ {
+ out << "\tif (filter_params.enabled)\n"
+ "\t{\n";
+ tabtemp="\t";
+ }
+
+ if ((prog.filter.enabled_const==false) || (prog.filter.enabled==true))
+ out << tabtemp << "\tfilter_update_counter++;\n"
+ << tabtemp << "\tif (filter_update_counter>=filter_update_frames)\n"
+ << tabtemp << "\t{\n"
+ << tabtemp << "\t\tfilter_update_counter=0;\n"
+ << tabtemp << "\t\t\n"
+ << tabtemp << "\t\tfloat cutoff= float(actual_freq)/ONE * \n"
+ << tabtemp << "\t\t\tfloat(curr_lfo[filter_params.trem_lfo][filter_params.trem_strength])/ONE *\n"
+ << tabtemp << "\t\t\t( filter_params.freqfactor_offset + filter_envelope->get_level() * filter_params.env_amount / float(ONE) );\n"
+ << tabtemp << "\t\tfilter.set_params( cutoff, filter_params.resonance );\n"
+ << tabtemp << "\t}\n"
+ << tabtemp << "\t\n"
+ << tabtemp << "\tfilter.process_sample(&out);\n";
+
+ if (prog.filter.enabled_const==false)
+ {
+ out << "\t}\n";
+ tabtemp="";
+ }
+ out << "\t\n";
+ }
+
+ out << "\treturn out;\n";
+ out << "}\n";
+}
+
+void write_set_param()
+{
+ out << "void Note::set_param(const parameter_t &p, fixed_t v)\n"
+ "{\n"
+ "\toscillator_t* sel_osc=NULL;\n"
+ "\toscillator_t* sel_orig_osc=NULL;\n"
+ "\tEnvelope* sel_env=NULL;\n"
+ "\t\n"
+ "\tswitch (p.osc)\n"
+ "\t{\n";
+
+ for (int i=0;i<prog.n_osc;i++)
+ {
+ out << "\t\tcase "<<i<<": sel_osc=&osc"<<i<<"; sel_orig_osc=&orig.osc"<<i<<"; ";
+
+ if (prog.env[i].enabled)
+ out << "sel_env=env"<<i<<"; ";
+ else
+ comment << "/* envelope"<<i<<" is disabled */ ";
+
+ out << "break;\n";
+ }
+
+ out << "\t\t\n"
+ "\t\tdefault: output_note(\"NOTE: trying to change the nonexistent oscillator\"+IntToStr(p.osc));\n"
+ "\t}\n"
+ "\t\n";
+
+ include_file("set_param.1");
+
+
+ if ((prog.filter.enabled==true) || (prog.filter.enabled_const==false))
+ {
+ include_file("set_param.filter");
+ if (prog.filter.env_settings.enabled)
+ include_file("set_param.filterenv");
+ else
+ include_file("set_param.nofilterenv");
+ }
+ else
+ include_file("set_param.nofilter");
+
+ if ((prog.sync_factor!=0) || (prog.sync_factor_const==false))
+ out << "\t\t\n"
+ "\t\tcase SYNC_FACTOR: sync_factor=v; break;\n";
+ else
+ out << "\t\t\n"
+ "\t\tcase SYNC_FACTOR: output_note(\"NOTE: trying to set sync_factor, but it's disabled\"); break;\n";
+
+ out << "\t\t\n"
+ "\t\tdefault: throw string(\"trying to set an unknown parameter\");\n"
+ "\t}\n"
+ "}\n";
+}
+
+void write_create_note()
+{
+ out << "extern \"C\" NoteSkel* create_note(int n, float v,program_t &prg, jack_nframes_t pf, fixed_t pb, int prg_no)\n"
+ "{\n"
+ "\treturn new Note(n,v,prg,pf,pb,prg_no);\n"
+ "}\n";
+}
+
+void write_destroy()
+{
+ out << "void Note::destroy()\n"
+ "{\n"
+ "\tdelete this;\n"
+ "}\n";
+}
+
+void generate_source()
+{
+ //#includes and definition of class Note
+ include_file("head.1");
+ write_env_decs();
+ write_empty_line();
+ write_oscval_decs();
+ write_empty_line();
+ write_osc_decs();
+ write_empty_line();
+ write_sync_decs();
+ write_empty_line();
+ write_filter_decs();
+ write_empty_line();
+ write_pfactor_decs();
+ include_file("head.2");
+
+
+ //implementation of Note's functions
+ write_ctor();
+ write_dtor();
+ write_destroy();
+ write_empty_line();
+
+ write_recalc_factors();
+ write_apply_pfactor();
+ write_empty_line();
+
+ write_still_active();
+ write_release();
+ write_release_quickly();
+ write_reattack();
+ write_empty_line();
+
+ write_do_ksr();
+ write_do_ksl();
+ write_empty_line();
+
+ write_get_sample();
+ write_empty_line();
+
+ write_set_param();
+
+ write_empty_line();
+ write_empty_line();
+ write_empty_line();
+
+ //implementation of create_note and init_vars
+ include_file("interface.1");
+}
+
+int main(int argc, char** argv)
+{
+ try
+ {
+ cerr << "parsing '"<<argv[1]<<"'..." << endl;
+ prog=parse(argv[1]);
+
+ generate_source();
+ }
+ catch(string err)
+ {
+ cerr << "FATAL: "<<err<<endl;
+ }
+
+ return 0;
+}
diff --git a/note_compiler/parser.cpp b/note_compiler/parser.cpp
new file mode 100644
index 0000000..c89ddd9
--- /dev/null
+++ b/note_compiler/parser.cpp
@@ -0,0 +1,504 @@
+#include <cstdlib>
+#include <fstream>
+
+#include "parser.h"
+#include "programs.h"
+#include "util.h"
+#include "../synth/defines.h"
+#include "../synth/fixed.h"
+
+
+void init_oscs(int n_osc, oscillator_t *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].output_no_pfactor=false;
+ 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;
+ osc[i].sync=false;
+ osc[i].sync_const=true;
+ osc[i].ksr_const=true;
+ osc[i].ksl_const=true;
+ }
+}
+
+void init_envs(int n_osc, env_settings_t *env)
+{
+ for (int i=0;i<n_osc;i++)
+ {
+ env[i].enabled=true;
+ env[i].attack=0;
+ env[i].attack_const=true;
+ env[i].decay=0;
+ env[i].decay_const=true;
+ env[i].sustain=1.0;
+ env[i].sustain_const=true;
+ env[i].release=0;
+ env[i].release_const=true;
+ env[i].hold=true;
+ env[i].hold_const=true;
+ }
+}
+
+void init_filter(filter_params_t &filter)
+{
+ 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;
+}
+
+
+string extract_array_name(string s)
+{
+ size_t p;
+ p=s.find('[');
+ if (p!=string::npos)
+ return s.substr(0,p);
+ else
+ return s;
+}
+
+int 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());
+}
+
+
+
+program_t parse(string fn)
+{
+ int n_osc=0;
+ oscillator_t *osc=NULL;
+ env_settings_t *env=NULL;
+ filter_params_t filter;
+ fixed_t sync_factor=0;
+ bool sync_factor_const=true;
+
+ char buf[2000];
+ string line;
+ string var;
+ string array;
+ string strval;
+ float val;
+
+ parameter_enum p;
+
+ int ind,ind2=0;
+
+ int state;
+
+ program_t result;
+
+
+ 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
+ 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);
+
+ 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:
+ if (state==4) // vel.-influence
+ {
+ if (isfloat(strval)) //is it a plain number, not a formula?
+ osc[ind].output_no_pfactor=true;
+ }
+ else
+ 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;
+ }
+ }
+ }
+
+
+ //some optimizations and checks
+
+ for (int i=0;i<n_osc;i++)
+ if ((env[i].attack==0) && (env[i].sustain==1.0)
+ && (env[i].release>100)) //TODO FINDMICH besseres kriterium?
+ env[i].enabled=false;
+
+ if ( ((filter.env_settings.attack==0) && (filter.env_settings.sustain==1.0)
+ && (filter.env_settings.release>100)) //TODO FINDMICH siehe oben
+ || ((filter.env_amount==0) && (filter.env_amount_const==true)) )
+ filter.env_settings.enabled=false;
+
+ bool use_sync=false;
+ for (int i=0;i<n_osc;i++)
+ if ((osc[i].sync==true) || (osc[i].sync_const==false))
+ {
+ use_sync=true;
+ break;
+ }
+
+ if (!use_sync)
+ {
+ sync_factor=0;
+ sync_factor_const=true;
+ }
+
+ if ((sync_factor==0) && (sync_factor_const==true))
+ for (int i=0;i<n_osc;i++)
+ {
+ osc[i].sync=false;
+ osc[i].sync_const=true;
+ }
+
+
+
+ for (int i=0;i<n_osc;i++)
+ if ( (osc[i].output_no_pfactor==false) && !((osc[i].output==0) && (osc[i].output_const=true)) )
+ osc[i].output_const=false;
+
+ //end optimizations and checks
+
+ result.n_osc=n_osc;
+ result.osc=osc;
+ result.env=env;
+ result.filter=filter;
+ result.sync_factor=sync_factor;
+ result.sync_factor_const=sync_factor_const;
+ }
+ else
+ throw string ("could not open '"+fn+"'");
+
+ return result;
+ //no uninit / free of osc and env here, as it must be done by the caller
+}
+
+
+
diff --git a/note_compiler/parser.h b/note_compiler/parser.h
new file mode 100644
index 0000000..71e7545
--- /dev/null
+++ b/note_compiler/parser.h
@@ -0,0 +1,16 @@
+#ifndef __PARSER_H__
+#define __PARSET_H__
+
+
+#include <set>
+#include <map>
+#include <list>
+#include <string>
+
+#include "programs.h"
+
+using namespace std;
+
+program_t parse(string fn);
+
+#endif
diff --git a/note_compiler/plugin_factory/Makefile b/note_compiler/plugin_factory/Makefile
new file mode 100644
index 0000000..c99645d
--- /dev/null
+++ b/note_compiler/plugin_factory/Makefile
@@ -0,0 +1,34 @@
+CXX=g++
+CFLAGS=-Wall -fpic -O2 -pg
+CXXFLAGS=$(CFLAGS)
+LDFLAGS=-shared -fpic -Wl,-soname,libmystuff.so.1 -lc
+
+OBJ=envelope.o filter.o note_skel.o infile.o programs.o
+LIB=result.so
+
+DEPENDFILE = .depend
+
+
+SRC = $(OBJ:%.o=%.cpp)
+
+all: $(LIB)
+
+
+$(LIB): $(OBJ)
+ $(CXX) $(CXXFLAGS) -o $(LIB) $(OBJ) $(LDFLAGS)
+
+
+depend dep: $(SRC)
+ $(CC) -MM $(SRC) > $(DEPENDFILE)
+
+-include $(DEPENDFILE)
+
+
+%.o: %.cpp
+ $(CXX) $(CXXFLAGS) -c $<
+
+.PHONY: clean dep depend
+
+clean:
+ rm -f $(OBJ) $(LIB)
+
diff --git a/note_compiler/plugin_factory/channel.cpp b/note_compiler/plugin_factory/channel.cpp
new file mode 120000
index 0000000..792f620
--- /dev/null
+++ b/note_compiler/plugin_factory/channel.cpp
@@ -0,0 +1 @@
+../../synth/channel.cpp \ No newline at end of file
diff --git a/note_compiler/plugin_factory/channel.h b/note_compiler/plugin_factory/channel.h
new file mode 120000
index 0000000..6c30b75
--- /dev/null
+++ b/note_compiler/plugin_factory/channel.h
@@ -0,0 +1 @@
+../../synth/channel.h \ No newline at end of file
diff --git a/note_compiler/plugin_factory/cli.cpp b/note_compiler/plugin_factory/cli.cpp
new file mode 120000
index 0000000..93de14b
--- /dev/null
+++ b/note_compiler/plugin_factory/cli.cpp
@@ -0,0 +1 @@
+../../synth/cli.cpp \ No newline at end of file
diff --git a/note_compiler/plugin_factory/cli.h b/note_compiler/plugin_factory/cli.h
new file mode 120000
index 0000000..5a26149
--- /dev/null
+++ b/note_compiler/plugin_factory/cli.h
@@ -0,0 +1 @@
+../../synth/cli.h \ No newline at end of file
diff --git a/note_compiler/plugin_factory/defines.cpp b/note_compiler/plugin_factory/defines.cpp
new file mode 120000
index 0000000..dc04029
--- /dev/null
+++ b/note_compiler/plugin_factory/defines.cpp
@@ -0,0 +1 @@
+../../synth/defines.cpp \ No newline at end of file
diff --git a/note_compiler/plugin_factory/defines.h b/note_compiler/plugin_factory/defines.h
new file mode 120000
index 0000000..89519f4
--- /dev/null
+++ b/note_compiler/plugin_factory/defines.h
@@ -0,0 +1 @@
+../../synth/defines.h \ No newline at end of file
diff --git a/note_compiler/plugin_factory/envelope.cpp b/note_compiler/plugin_factory/envelope.cpp
new file mode 120000
index 0000000..3acf96b
--- /dev/null
+++ b/note_compiler/plugin_factory/envelope.cpp
@@ -0,0 +1 @@
+../../synth/envelope.cpp \ No newline at end of file
diff --git a/note_compiler/plugin_factory/envelope.h b/note_compiler/plugin_factory/envelope.h
new file mode 120000
index 0000000..76975f0
--- /dev/null
+++ b/note_compiler/plugin_factory/envelope.h
@@ -0,0 +1 @@
+../../synth/envelope.h \ No newline at end of file
diff --git a/note_compiler/plugin_factory/filter.cpp b/note_compiler/plugin_factory/filter.cpp
new file mode 120000
index 0000000..04ac153
--- /dev/null
+++ b/note_compiler/plugin_factory/filter.cpp
@@ -0,0 +1 @@
+../../synth/filter.cpp \ No newline at end of file
diff --git a/note_compiler/plugin_factory/filter.h b/note_compiler/plugin_factory/filter.h
new file mode 120000
index 0000000..406f7e6
--- /dev/null
+++ b/note_compiler/plugin_factory/filter.h
@@ -0,0 +1 @@
+../../synth/filter.h \ No newline at end of file
diff --git a/note_compiler/plugin_factory/fixed.h b/note_compiler/plugin_factory/fixed.h
new file mode 120000
index 0000000..e6e1fb0
--- /dev/null
+++ b/note_compiler/plugin_factory/fixed.h
@@ -0,0 +1 @@
+../../synth/fixed.h \ No newline at end of file
diff --git a/note_compiler/plugin_factory/globals.cpp b/note_compiler/plugin_factory/globals.cpp
new file mode 120000
index 0000000..b38aed3
--- /dev/null
+++ b/note_compiler/plugin_factory/globals.cpp
@@ -0,0 +1 @@
+../../synth/globals.cpp \ No newline at end of file
diff --git a/note_compiler/plugin_factory/globals.h b/note_compiler/plugin_factory/globals.h
new file mode 120000
index 0000000..0e3a295
--- /dev/null
+++ b/note_compiler/plugin_factory/globals.h
@@ -0,0 +1 @@
+../../synth/globals.h \ No newline at end of file
diff --git a/note_compiler/plugin_factory/infile.cpp b/note_compiler/plugin_factory/infile.cpp
new file mode 100644
index 0000000..3523fd8
--- /dev/null
+++ b/note_compiler/plugin_factory/infile.cpp
@@ -0,0 +1,392 @@
+#include <jack/jack.h>
+
+#include <cmath>
+#include <string>
+
+#include "defines.h"
+#include "programs.h"
+#include "envelope.h"
+#include "fixed.h"
+#include "filter.h"
+#include "note_skel.h"
+
+using namespace std;
+
+int filter_update_frames=0;
+int samp_rate=0;
+fixed_t** wave=NULL;
+fixed_t** curr_lfo=NULL;
+
+typedef void output_note_func_t(string s);
+typedef string IntToStr_func_t(int i);
+
+output_note_func_t* output_note=NULL;
+IntToStr_func_t* IntToStr=NULL;
+
+class Note : public NoteSkel
+{
+ public:
+ Note(int n, float v,program_t &prg, jack_nframes_t pf, fixed_t pb, int prg_no);
+ ~Note();
+ fixed_t get_sample();
+
+ void release_quickly(jack_nframes_t maxt);
+ void release();
+ void reattack();
+ bool still_active();
+ void set_param(const parameter_t &p, fixed_t v);
+
+ void destroy();
+
+ private:
+ void do_ksl();
+ void do_ksr();
+
+ void recalc_factors();
+ void apply_pfactor();
+
+// member variables begin here
+
+ Envelope *env0;
+ Envelope *env1;
+
+ fixed_t *oscval;
+ fixed_t *old_oscval;
+
+ oscillator_t osc0;
+ oscillator_t osc1;
+
+ //sync is disabled
+
+ LowPassFilter filter;
+ filter_params_t filter_params;
+ int filter_update_counter;
+ Envelope *filter_envelope;
+
+ pfactor_value_t pfactor;
+ struct
+ {
+ oscillator_t osc0;
+ oscillator_t osc1;
+ filter_params_t filter_params;
+ } orig;
+// member variables end here
+};
+
+//this function returns the smallest phase_init possible for a
+//given custom_wave which is greater or equal than PHASE_INIT
+#define PHASE_INIT 100
+inline fixed_t init_custom_osc_phase(int len, fixed_t sr)
+{
+ return ( (fixed_t(ceil( float(PHASE_INIT) * sr / len / ONE )) *len << (2*SCALE)) / sr);
+}
+
+
+Note::Note(int n, float v, program_t &prg, jack_nframes_t pf, fixed_t pb, int prg_no)
+{
+ curr_prg=&prg;
+
+ oscval=new fixed_t[2];
+ old_oscval=new fixed_t[2];
+ for (int i=0;i<2;i++)
+ oscval[i]=old_oscval[i]=0;
+
+ pfactor.out=new fixed_t [2];
+ pfactor.fm=new fixed_t* [2];
+ for (int i=0;i<2;i++)
+ pfactor.fm[i]=new fixed_t [2];
+
+ env0=new Envelope (prg.env_settings[0]);
+ env1=new Envelope (prg.env_settings[1]);
+
+ osc0=prg.osc_settings[0];
+ orig.osc0=prg.osc_settings[0];
+ osc1=prg.osc_settings[1];
+ orig.osc1=prg.osc_settings[1];
+
+ //initalize oscillator.phase to multiples of their wave resolution
+ osc0.phase=ONE * PHASE_INIT;
+ osc1.phase=init_custom_osc_phase(osc1.custom_wave->wave_len, osc1.custom_wave->samp_rate);
+
+ do_ksl();
+
+
+ filter_params=prg.filter_settings;
+ orig.filter_params=prg.filter_settings;
+ filter_envelope=new Envelope(filter_params.env_settings);
+ filter_update_counter=filter_update_frames;
+
+
+ portamento_frames=0;
+ set_portamento_frames(pf);
+
+ set_note(n);
+ freq=dest_freq;
+ set_vel(v);
+
+ pitchbend=pb;
+
+ program=prg_no;
+}
+
+Note::~Note()
+{
+ delete [] osc0.fm_strength;
+ delete env0;
+ delete pfactor.fm[0];
+
+ delete [] osc1.fm_strength;
+ delete env1;
+ delete pfactor.fm[1];
+
+
+ delete [] oscval;
+ delete [] old_oscval;
+
+ delete [] pfactor.out;
+ delete [] pfactor.fm;
+}
+void Note::destroy()
+{
+ delete this;
+}
+
+void Note::recalc_factors()
+{
+ pfactor.filter_env=calc_pfactor(curr_prg->pfactor.filter_env, vel);
+ pfactor.filter_res=calc_pfactor(curr_prg->pfactor.filter_res, vel);
+ pfactor.filter_offset=calc_pfactor(curr_prg->pfactor.filter_offset, vel);
+
+ for (int i=0;i<2;i++)
+ {
+ pfactor.out[i]=calc_pfactor(curr_prg->pfactor.out[i], vel);
+
+ for (int j=0;j<2;j++)
+ pfactor.fm[i][j]=calc_pfactor(curr_prg->pfactor.fm[i][j], vel);
+ }
+}
+void Note::apply_pfactor()
+{
+ filter_params.env_amount=orig.filter_params.env_amount*pfactor.filter_env /ONE;
+ filter_params.freqfactor_offset=orig.filter_params.freqfactor_offset*pfactor.filter_offset /ONE;
+ filter_params.resonance=orig.filter_params.resonance*pfactor.filter_res /ONE;
+
+ osc0.output=orig.osc0.output*pfactor.out[0] >>SCALE;
+ for (int i=0;i<2;i++)
+ osc0.fm_strength[i]=orig.osc0.fm_strength[i]*pfactor.fm[0][i] >>SCALE;
+ osc1.output=orig.osc1.output*pfactor.out[1] >>SCALE;
+ for (int i=0;i<2;i++)
+ osc1.fm_strength[i]=orig.osc1.fm_strength[i]*pfactor.fm[1][i] >>SCALE;
+}
+
+bool Note::still_active()
+{
+ if ( ((osc0.output>0) && (env0->still_active()))
+ || ((osc1.output>0) && (env1->still_active())) )
+ return true;
+ else
+ return false;
+}
+void Note::release()
+{
+ env0->release_key();
+ env1->release_key();
+
+ filter_envelope->release_key();
+}
+void Note::release_quickly(jack_nframes_t maxt)
+{
+ if (env0->get_release() > maxt)
+ env0->set_release(maxt);
+ env0->release_key();
+
+ if (env1->get_release() > maxt)
+ env1->set_release(maxt);
+ env1->release_key();
+
+}
+void Note::reattack()
+{
+ env0->reattack();
+ env1->reattack();
+
+ filter_envelope->reattack();
+}
+
+void Note::do_ksr()
+{
+ env0->set_ratefactor(1.0 / pow(freq>>SCALE, osc0.ksr));
+ env1->set_ratefactor(1.0 / pow(freq>>SCALE, osc1.ksr));
+}
+void Note::do_ksl()
+{
+}
+
+fixed_t Note::get_sample()
+{
+ if (freq!=dest_freq)
+ {
+ // the div.by.zero if p_frames=0 is avoided because then the
+ // if-condition below is always true
+ if (portamento_t>=portamento_frames)
+ freq=dest_freq;
+ else //will only happen if p_t < p_frames -> p_frames is always > 0 -> div. ok
+ freq = old_freq + (dest_freq-old_freq)*portamento_t/portamento_frames;
+
+ do_ksl();
+
+ portamento_t++;
+ }
+
+ fixed_t actual_freq=freq*pitchbend >>SCALE;
+
+ fixed_t *temp;
+ temp=old_oscval; //swap the current and old oscval-pointers
+ old_oscval=oscval;
+ oscval=temp;
+
+
+ //sync is disabled
+
+
+ osc0.phase+= (actual_freq*osc0.factor/samp_rate)>>SCALE;
+ oscval[0] = wave[0][ ( ( osc0.phase + ( + (old_oscval[1] * osc0.fm_strength[1]) >>SCALE ) ) * WAVE_RES >>SCALE ) % WAVE_RES ] * env0->get_level() >>SCALE;
+ //oscillator0 has no tremolo
+
+ osc1.phase+= (actual_freq*osc1.factor/samp_rate)>>SCALE;
+ oscval[1] = osc1.custom_wave->wave[ ( osc1.phase * osc1.custom_wave->samp_rate >>(2*SCALE) ) % osc1.custom_wave->wave_len ] * env1->get_level() >>SCALE;
+ //oscillator1 has no tremolo
+
+ fixed_t out = ( + osc0.output*oscval[0] + osc1.output*oscval[1] >>SCALE );
+
+
+ filter_update_counter++;
+ if (filter_update_counter>=filter_update_frames)
+ {
+ filter_update_counter=0;
+
+ float cutoff= float(actual_freq)/ONE *
+ float(curr_lfo[filter_params.trem_lfo][filter_params.trem_strength])/ONE *
+ ( filter_params.freqfactor_offset + filter_envelope->get_level() * filter_params.env_amount / float(ONE) );
+ filter.set_params( cutoff, filter_params.resonance );
+ }
+
+ filter.process_sample(&out);
+
+ return out;
+}
+
+void Note::set_param(const parameter_t &p, fixed_t v)
+{
+ oscillator_t* sel_osc=NULL;
+ oscillator_t* sel_orig_osc=NULL;
+ Envelope* sel_env=NULL;
+
+ switch (p.osc)
+ {
+ case 0: sel_osc=&osc0; sel_orig_osc=&orig.osc0; sel_env=env0; break;
+ case 1: sel_osc=&osc1; sel_orig_osc=&orig.osc1; sel_env=env1; break;
+
+ default: output_note("NOTE: trying to change the nonexistent oscillator"+IntToStr(p.osc));
+ }
+
+ if ( ((p.par==ATTACK) || (p.par==DECAY) || (p.par==SUSTAIN) ||
+ (p.par==RELEASE) || (p.par==HOLD)) && sel_env==NULL )
+ {
+ output_note("NOTE: cannot change parameter for envelope"+IntToStr(p.osc)+" because it's disabled");
+ return;
+ }
+
+ switch(p.par)
+ {
+ case ATTACK: sel_env->set_attack(v*samp_rate >>SCALE); break;
+ case DECAY: sel_env->set_decay(v*samp_rate >>SCALE); break;
+ case SUSTAIN: sel_env->set_sustain(v); break;
+ case RELEASE: sel_env->set_release(v*samp_rate >>SCALE); break;
+ case HOLD: sel_env->set_hold(v!=0); break;
+
+ case KSR: sel_osc->ksr=float(v)/ONE; break;
+ case KSL: sel_osc->ksl=float(v)/ONE; break;
+
+ case FACTOR: sel_osc->factor=v; break;
+ case TREMOLO: sel_osc->tremolo_depth=v; break;
+ case TREM_LFO: sel_osc->tremolo_lfo=v; break;
+ case VIBRATO: sel_osc->vibrato_depth=v; break;
+ case VIB_LFO: sel_osc->vibrato_lfo=v; break;
+ case WAVEFORM: sel_osc->waveform=v; break;
+ case SYNC: sel_osc->sync=(v!=0); break;
+ case MODULATION: sel_orig_osc->fm_strength[p.index]=v; apply_pfactor(); break;
+ case OUTPUT: sel_orig_osc->output=v; apply_pfactor(); break;
+
+
+ case FILTER_ENABLED: output_note("NOTE: cannot enable filter in playing notes"); break;
+ case FILTER_ENV_AMOUNT: orig.filter_params.env_amount=float(v)/ONE; apply_pfactor(); break;
+ case FILTER_OFFSET: orig.filter_params.freqfactor_offset=float(v)/ONE; apply_pfactor(); break;
+ case FILTER_RESONANCE: orig.filter_params.resonance=float(v)/ONE; apply_pfactor(); break;
+ case FILTER_TREMOLO: filter_params.trem_strength=v; break;
+ case FILTER_TREM_LFO: filter_params.trem_lfo=v; break;
+
+ case FILTER_ATTACK:
+ if (filter_params.enabled)
+ filter_envelope->set_attack(v*samp_rate/filter_update_frames >>SCALE);
+ else
+ output_note("NOTE: cannot set filter-attack when filter is disabled");
+ break;
+
+ case FILTER_DECAY:
+ if (filter_params.enabled)
+ filter_envelope->set_decay(v*samp_rate/filter_update_frames >>SCALE);
+ else
+ output_note("NOTE: cannot set filter-decay when filter is disabled");
+ break;
+
+ case FILTER_SUSTAIN:
+ if (filter_params.enabled)
+ filter_envelope->set_sustain(v);
+ else
+ output_note("NOTE: cannot set filter-sustain when filter is disabled");
+ break;
+
+ case FILTER_RELEASE:
+ if (filter_params.enabled)
+ filter_envelope->set_release(v*samp_rate/filter_update_frames >>SCALE);
+ else
+ output_note("NOTE: cannot set filter-release when filter is disabled");
+ break;
+
+ case FILTER_HOLD:
+ if (filter_params.enabled)
+ filter_envelope->set_hold(v!=0);
+ else
+ output_note("NOTE: cannot set filter-hold when filter is disabled");
+ break;
+
+
+ case SYNC_FACTOR: output_note("NOTE: trying to set sync_factor, but it's disabled"); break;
+
+ default: throw string("trying to set an unknown parameter");
+ }
+}
+
+
+
+extern "C" NoteSkel* create_note(int n, float v,program_t &prg, jack_nframes_t pf, fixed_t pb, int prg_no)
+{
+ if (wave==NULL)
+ throw string("FATAL: trying to create a new note from a shared object without initalizing\n"
+ " the object first! this should /never/ happen, please contact the developer");
+
+ return new Note(n,v,prg,pf,pb,prg_no);
+}
+
+extern "C" void init_vars(int sr, int fupfr, fixed_t **w, fixed_t **clfo, output_note_func_t* out_n, IntToStr_func_t* its)
+{
+ samp_rate=sr;
+ filter_update_frames=fupfr;
+ wave=w;
+ curr_lfo=clfo;
+ IntToStr=its;
+ output_note=out_n;
+}
+
+
diff --git a/note_compiler/plugin_factory/jack.cpp b/note_compiler/plugin_factory/jack.cpp
new file mode 120000
index 0000000..83a42b1
--- /dev/null
+++ b/note_compiler/plugin_factory/jack.cpp
@@ -0,0 +1 @@
+../../synth/jack.cpp \ No newline at end of file
diff --git a/note_compiler/plugin_factory/jack.h b/note_compiler/plugin_factory/jack.h
new file mode 120000
index 0000000..5c4c8cf
--- /dev/null
+++ b/note_compiler/plugin_factory/jack.h
@@ -0,0 +1 @@
+../../synth/jack.h \ No newline at end of file
diff --git a/note_compiler/plugin_factory/load.cpp b/note_compiler/plugin_factory/load.cpp
new file mode 120000
index 0000000..c08bf33
--- /dev/null
+++ b/note_compiler/plugin_factory/load.cpp
@@ -0,0 +1 @@
+../../synth/load.cpp \ No newline at end of file
diff --git a/note_compiler/plugin_factory/load.h b/note_compiler/plugin_factory/load.h
new file mode 120000
index 0000000..3f30401
--- /dev/null
+++ b/note_compiler/plugin_factory/load.h
@@ -0,0 +1 @@
+../../synth/load.h \ No newline at end of file
diff --git a/note_compiler/plugin_factory/main.cpp b/note_compiler/plugin_factory/main.cpp
new file mode 120000
index 0000000..b9733e2
--- /dev/null
+++ b/note_compiler/plugin_factory/main.cpp
@@ -0,0 +1 @@
+../../synth/main.cpp \ No newline at end of file
diff --git a/note_compiler/plugin_factory/note.cpp b/note_compiler/plugin_factory/note.cpp
new file mode 120000
index 0000000..2b806ab
--- /dev/null
+++ b/note_compiler/plugin_factory/note.cpp
@@ -0,0 +1 @@
+../../synth/note.cpp \ No newline at end of file
diff --git a/note_compiler/plugin_factory/note.h b/note_compiler/plugin_factory/note.h
new file mode 120000
index 0000000..200f314
--- /dev/null
+++ b/note_compiler/plugin_factory/note.h
@@ -0,0 +1 @@
+../../synth/note.h \ No newline at end of file
diff --git a/note_compiler/plugin_factory/note_funcs.h b/note_compiler/plugin_factory/note_funcs.h
new file mode 120000
index 0000000..685d295
--- /dev/null
+++ b/note_compiler/plugin_factory/note_funcs.h
@@ -0,0 +1 @@
+../../synth/note_funcs.h \ No newline at end of file
diff --git a/note_compiler/plugin_factory/note_loader.cpp b/note_compiler/plugin_factory/note_loader.cpp
new file mode 120000
index 0000000..e5cca64
--- /dev/null
+++ b/note_compiler/plugin_factory/note_loader.cpp
@@ -0,0 +1 @@
+../../synth/note_loader.cpp \ No newline at end of file
diff --git a/note_compiler/plugin_factory/note_loader.h b/note_compiler/plugin_factory/note_loader.h
new file mode 120000
index 0000000..9155410
--- /dev/null
+++ b/note_compiler/plugin_factory/note_loader.h
@@ -0,0 +1 @@
+../../synth/note_loader.h \ No newline at end of file
diff --git a/note_compiler/plugin_factory/note_skel.cpp b/note_compiler/plugin_factory/note_skel.cpp
new file mode 120000
index 0000000..e85be17
--- /dev/null
+++ b/note_compiler/plugin_factory/note_skel.cpp
@@ -0,0 +1 @@
+../../synth/note_skel.cpp \ No newline at end of file
diff --git a/note_compiler/plugin_factory/note_skel.h b/note_compiler/plugin_factory/note_skel.h
new file mode 120000
index 0000000..780165e
--- /dev/null
+++ b/note_compiler/plugin_factory/note_skel.h
@@ -0,0 +1 @@
+../../synth/note_skel.h \ No newline at end of file
diff --git a/note_compiler/plugin_factory/parser.cpp b/note_compiler/plugin_factory/parser.cpp
new file mode 120000
index 0000000..b849baf
--- /dev/null
+++ b/note_compiler/plugin_factory/parser.cpp
@@ -0,0 +1 @@
+../../synth/parser.cpp \ No newline at end of file
diff --git a/note_compiler/plugin_factory/parser.h b/note_compiler/plugin_factory/parser.h
new file mode 120000
index 0000000..c303d77
--- /dev/null
+++ b/note_compiler/plugin_factory/parser.h
@@ -0,0 +1 @@
+../../synth/parser.h \ No newline at end of file
diff --git a/note_compiler/plugin_factory/programs.cpp b/note_compiler/plugin_factory/programs.cpp
new file mode 120000
index 0000000..4a5fa05
--- /dev/null
+++ b/note_compiler/plugin_factory/programs.cpp
@@ -0,0 +1 @@
+../../synth/programs.cpp \ No newline at end of file
diff --git a/note_compiler/plugin_factory/programs.h b/note_compiler/plugin_factory/programs.h
new file mode 120000
index 0000000..77c6b54
--- /dev/null
+++ b/note_compiler/plugin_factory/programs.h
@@ -0,0 +1 @@
+../../synth/programs.h \ No newline at end of file
diff --git a/note_compiler/plugin_factory/readwave.cpp b/note_compiler/plugin_factory/readwave.cpp
new file mode 120000
index 0000000..d422f94
--- /dev/null
+++ b/note_compiler/plugin_factory/readwave.cpp
@@ -0,0 +1 @@
+../../synth/readwave.cpp \ No newline at end of file
diff --git a/note_compiler/plugin_factory/readwave.h b/note_compiler/plugin_factory/readwave.h
new file mode 120000
index 0000000..74f5e95
--- /dev/null
+++ b/note_compiler/plugin_factory/readwave.h
@@ -0,0 +1 @@
+../../synth/readwave.h \ No newline at end of file
diff --git a/note_compiler/plugin_factory/util.cpp b/note_compiler/plugin_factory/util.cpp
new file mode 120000
index 0000000..452cd9e
--- /dev/null
+++ b/note_compiler/plugin_factory/util.cpp
@@ -0,0 +1 @@
+../../synth/util.cpp \ No newline at end of file
diff --git a/note_compiler/plugin_factory/util.h b/note_compiler/plugin_factory/util.h
new file mode 120000
index 0000000..56353d9
--- /dev/null
+++ b/note_compiler/plugin_factory/util.h
@@ -0,0 +1 @@
+../../synth/util.h \ No newline at end of file
diff --git a/note_compiler/programs.h b/note_compiler/programs.h
new file mode 100644
index 0000000..9025ba1
--- /dev/null
+++ b/note_compiler/programs.h
@@ -0,0 +1,121 @@
+#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;
+ bool output_no_pfactor;
+ 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
+{
+ bool enabled;
+ 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/templates/ctor.foot b/note_compiler/templates/ctor.foot
new file mode 100644
index 0000000..05d4421
--- /dev/null
+++ b/note_compiler/templates/ctor.foot
@@ -0,0 +1,11 @@
+ portamento_frames=0;
+ set_portamento_frames(pf);
+
+ set_note(n);
+ freq=dest_freq;
+ set_vel(v);
+
+ pitchbend=pb;
+
+ program=prg_no;
+}
diff --git a/note_compiler/templates/get_sample.1 b/note_compiler/templates/get_sample.1
new file mode 100644
index 0000000..3d73052
--- /dev/null
+++ b/note_compiler/templates/get_sample.1
@@ -0,0 +1,23 @@
+fixed_t Note::get_sample()
+{
+ if (freq!=dest_freq)
+ {
+ // the div.by.zero if p_frames=0 is avoided because then the
+ // if-condition below is always true
+ if (portamento_t>=portamento_frames)
+ freq=dest_freq;
+ else //will only happen if p_t < p_frames -> p_frames is always > 0 -> div. ok
+ freq = old_freq + (dest_freq-old_freq)*portamento_t/portamento_frames;
+
+ do_ksl();
+
+ portamento_t++;
+ }
+
+ fixed_t actual_freq=freq*pitchbend >>SCALE;
+
+ fixed_t *temp;
+ temp=old_oscval; //swap the current and old oscval-pointers
+ old_oscval=oscval;
+ oscval=temp;
+
diff --git a/note_compiler/templates/head.1 b/note_compiler/templates/head.1
new file mode 100644
index 0000000..6759f56
--- /dev/null
+++ b/note_compiler/templates/head.1
@@ -0,0 +1,48 @@
+#include <jack/jack.h>
+
+#include <cmath>
+#include <string>
+
+#include "defines.h"
+#include "programs.h"
+#include "envelope.h"
+#include "fixed.h"
+#include "filter.h"
+#include "note_skel.h"
+
+using namespace std;
+
+int filter_update_frames=0;
+int samp_rate=0;
+fixed_t** wave=NULL;
+fixed_t** curr_lfo=NULL;
+
+typedef void output_note_func_t(string s);
+typedef string IntToStr_func_t(int i);
+
+output_note_func_t* output_note=NULL;
+IntToStr_func_t* IntToStr=NULL;
+
+class Note : public NoteSkel
+{
+ public:
+ Note(int n, float v,program_t &prg, jack_nframes_t pf, fixed_t pb, int prg_no);
+ ~Note();
+ fixed_t get_sample();
+
+ void release_quickly(jack_nframes_t maxt);
+ void release();
+ void reattack();
+ bool still_active();
+ void set_param(const parameter_t &p, fixed_t v);
+
+ void destroy();
+
+ private:
+ void do_ksl();
+ void do_ksr();
+
+ void recalc_factors();
+ void apply_pfactor();
+
+// member variables begin here
diff --git a/note_compiler/templates/head.2 b/note_compiler/templates/head.2
new file mode 100644
index 0000000..917030c
--- /dev/null
+++ b/note_compiler/templates/head.2
@@ -0,0 +1,11 @@
+// member variables end here
+};
+
+//this function returns the smallest phase_init possible for a
+//given custom_wave which is greater or equal than PHASE_INIT
+#define PHASE_INIT 100
+inline fixed_t init_custom_osc_phase(int len, fixed_t sr)
+{
+ return ( (fixed_t(ceil( float(PHASE_INIT) * sr / len / ONE )) *len << (2*SCALE)) / sr);
+}
+
diff --git a/note_compiler/templates/interface.1 b/note_compiler/templates/interface.1
new file mode 100644
index 0000000..cacc175
--- /dev/null
+++ b/note_compiler/templates/interface.1
@@ -0,0 +1,19 @@
+extern "C" NoteSkel* create_note(int n, float v,program_t &prg, jack_nframes_t pf, fixed_t pb, int prg_no)
+{
+ if (wave==NULL)
+ throw string("FATAL: trying to create a new note from a shared object without initalizing\n"
+ " the object first! this should /never/ happen, please contact the developer");
+
+ return new Note(n,v,prg,pf,pb,prg_no);
+}
+
+extern "C" void init_vars(int sr, int fupfr, fixed_t **w, fixed_t **clfo, output_note_func_t* out_n, IntToStr_func_t* its)
+{
+ samp_rate=sr;
+ filter_update_frames=fupfr;
+ wave=w;
+ curr_lfo=clfo;
+ IntToStr=its;
+ output_note=out_n;
+}
+
diff --git a/note_compiler/templates/set_param.1 b/note_compiler/templates/set_param.1
new file mode 100644
index 0000000..21fc983
--- /dev/null
+++ b/note_compiler/templates/set_param.1
@@ -0,0 +1,27 @@
+ if ( ((p.par==ATTACK) || (p.par==DECAY) || (p.par==SUSTAIN) ||
+ (p.par==RELEASE) || (p.par==HOLD)) && sel_env==NULL )
+ {
+ output_note("NOTE: cannot change parameter for envelope"+IntToStr(p.osc)+" because it's disabled");
+ return;
+ }
+
+ switch(p.par)
+ {
+ case ATTACK: sel_env->set_attack(v*samp_rate >>SCALE); break;
+ case DECAY: sel_env->set_decay(v*samp_rate >>SCALE); break;
+ case SUSTAIN: sel_env->set_sustain(v); break;
+ case RELEASE: sel_env->set_release(v*samp_rate >>SCALE); break;
+ case HOLD: sel_env->set_hold(v!=0); break;
+
+ case KSR: sel_osc->ksr=float(v)/ONE; break;
+ case KSL: sel_osc->ksl=float(v)/ONE; break;
+
+ case FACTOR: sel_osc->factor=v; break;
+ case TREMOLO: sel_osc->tremolo_depth=v; break;
+ case TREM_LFO: sel_osc->tremolo_lfo=v; break;
+ case VIBRATO: sel_osc->vibrato_depth=v; break;
+ case VIB_LFO: sel_osc->vibrato_lfo=v; break;
+ case WAVEFORM: sel_osc->waveform=v; break;
+ case SYNC: sel_osc->sync=(v!=0); break;
+ case MODULATION: sel_orig_osc->fm_strength[p.index]=v; apply_pfactor(); break;
+ case OUTPUT: sel_orig_osc->output=v; apply_pfactor(); break;
diff --git a/note_compiler/templates/set_param.filter b/note_compiler/templates/set_param.filter
new file mode 100644
index 0000000..797d30b
--- /dev/null
+++ b/note_compiler/templates/set_param.filter
@@ -0,0 +1,7 @@
+
+ case FILTER_ENABLED: output_note("NOTE: cannot enable filter in playing notes"); break;
+ case FILTER_ENV_AMOUNT: orig.filter_params.env_amount=float(v)/ONE; apply_pfactor(); break;
+ case FILTER_OFFSET: orig.filter_params.freqfactor_offset=float(v)/ONE; apply_pfactor(); break;
+ case FILTER_RESONANCE: orig.filter_params.resonance=float(v)/ONE; apply_pfactor(); break;
+ case FILTER_TREMOLO: filter_params.trem_strength=v; break;
+ case FILTER_TREM_LFO: filter_params.trem_lfo=v; break;
diff --git a/note_compiler/templates/set_param.filterenv b/note_compiler/templates/set_param.filterenv
new file mode 100644
index 0000000..aaa21b4
--- /dev/null
+++ b/note_compiler/templates/set_param.filterenv
@@ -0,0 +1,34 @@
+ case FILTER_ATTACK:
+ if (filter_params.enabled)
+ filter_envelope->set_attack(v*samp_rate/filter_update_frames >>SCALE);
+ else
+ output_note("NOTE: cannot set filter-attack when filter is disabled");
+ break;
+
+ case FILTER_DECAY:
+ if (filter_params.enabled)
+ filter_envelope->set_decay(v*samp_rate/filter_update_frames >>SCALE);
+ else
+ output_note("NOTE: cannot set filter-decay when filter is disabled");
+ break;
+
+ case FILTER_SUSTAIN:
+ if (filter_params.enabled)
+ filter_envelope->set_sustain(v);
+ else
+ output_note("NOTE: cannot set filter-sustain when filter is disabled");
+ break;
+
+ case FILTER_RELEASE:
+ if (filter_params.enabled)
+ filter_envelope->set_release(v*samp_rate/filter_update_frames >>SCALE);
+ else
+ output_note("NOTE: cannot set filter-release when filter is disabled");
+ break;
+
+ case FILTER_HOLD:
+ if (filter_params.enabled)
+ filter_envelope->set_hold(v!=0);
+ else
+ output_note("NOTE: cannot set filter-hold when filter is disabled");
+ break;
diff --git a/note_compiler/templates/set_param.nofilter b/note_compiler/templates/set_param.nofilter
new file mode 100644
index 0000000..e9ee336
--- /dev/null
+++ b/note_compiler/templates/set_param.nofilter
@@ -0,0 +1,13 @@
+ case FILTER_ENABLED:
+ case FILTER_ENV_AMOUNT:
+ case FILTER_ATTACK:
+ case FILTER_DECAY:
+ case FILTER_SUSTAIN:
+ case FILTER_RELEASE:
+ case FILTER_HOLD:
+ case FILTER_OFFSET:
+ case FILTER_RESONANCE:
+ case FILTER_TREMOLO:
+ case FILTER_TREM_LFO:
+ output_note("NOTE: trying to set some filter-param, but filter is disabled");
+ break;
diff --git a/note_compiler/templates/set_param.nofilterenv b/note_compiler/templates/set_param.nofilterenv
new file mode 100644
index 0000000..23ad36d
--- /dev/null
+++ b/note_compiler/templates/set_param.nofilterenv
@@ -0,0 +1,7 @@
+ case FILTER_ATTACK:
+ case FILTER_DECAY:
+ case FILTER_SUSTAIN:
+ case FILTER_RELEASE:
+ case FILTER_HOLD:
+ output_note("NOTE: trying to change filter envelope, but that envelope is disabled");
+ break;
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