summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Jung <flo@thinkpad.(none)>2011-01-06 20:16:19 +0100
committerFlorian Jung <flo@thinkpad.(none)>2011-01-06 20:16:19 +0100
commite78131ccbbcb81da94e5992f788c6ea291a2050d (patch)
treeae15e6f8d77be250f168f1871c5a4de34c990abb
parente8382521c1a35ad59efea5e8cebb915a67c0008e (diff)
The synthesizer can now load the compiled notes
There are still issues: - filtertest.prog.so: output_note-message which is not true - huge size of the .so (48K are too much!)
-rw-r--r--TODO7
-rw-r--r--note_compiler/howtocompile.txt4
-rw-r--r--note_compiler/main.cpp12
-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.cpp362
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/templates/head.116
-rw-r--r--note_compiler/templates/interface.119
-rw-r--r--synth/Makefile4
-rw-r--r--synth/channel.cpp50
-rw-r--r--synth/globals.cpp2
-rw-r--r--synth/globals.h2
-rw-r--r--synth/jack.cpp4
-rw-r--r--synth/main.cpp23
-rw-r--r--synth/note.cpp5
-rw-r--r--synth/note.h2
-rw-r--r--synth/note_funcs.h20
-rw-r--r--synth/note_loader.cpp44
-rw-r--r--synth/note_loader.h13
-rw-r--r--synth/note_skel.h2
-rw-r--r--synth/programs.cpp7
-rw-r--r--synth/programs.h6
54 files changed, 641 insertions, 30 deletions
diff --git a/TODO b/TODO
index 883a589..a86f48f 100644
--- a/TODO
+++ b/TODO
@@ -1,4 +1,10 @@
TODO für den synth
+ o .so unloaden!
+ o envelope, filter, ggf. auch alles aus program.o im hauptprogramm
+ lassen? d.h. via init funktionspointer übergeben oder virtuelle
+ interfaceklassen benutzen (für envelope/filter z.B.)
+ o wave auf int*[] mit wave[i]=new int[] umbauen
+
!!!o BUG: bei Note::set_param sollte statt dem eigentlichen param
der orig gesetzt werden und dann neu berechnet werden!
!!!o BUG: bei release und reattack: BEIDE male die filter-envelope beachten!
@@ -10,6 +16,7 @@ TODO für den synth
o in get_sample(), beim aufaddieren zum out (und vmtl auf fm-)wert:
erst nach dem addieren scalen, statt für jeden faktor einzeln
o wenn sync global aus ist, kann auch osc.sync genullt werden
+ o beim default_program vielleicht auch ein optimiertes objekt benutzen?
o filter_envelope könnte mit anderem ctor geinitet werden (weniger schreibarbeit)
o notes compilieren und als .so-datei laden
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
index 8612bd2..3015551 100644
--- a/note_compiler/main.cpp
+++ b/note_compiler/main.cpp
@@ -741,11 +741,11 @@ void write_create_note()
"}\n";
}
-void write_destroy_note()
+void write_destroy()
{
- out << "extern \"C\" void destroy_note(NoteSkel* obj)\n"
+ out << "void Note::destroy()\n"
"{\n"
- "\tdelete obj;\n"
+ "\tdelete this;\n"
"}\n";
}
@@ -770,6 +770,7 @@ void generate_source()
//implementation of Note's functions
write_ctor();
write_dtor();
+ write_destroy();
write_empty_line();
write_recalc_factors();
@@ -795,9 +796,8 @@ void generate_source()
write_empty_line();
write_empty_line();
- //implementation of create_new_note and destroy_note
- write_create_note();
- write_destroy_note();
+ //implementation of create_note and init_vars
+ include_file("interface.1");
}
int main(int argc, char** argv)
diff --git a/note_compiler/plugin_factory/Makefile b/note_compiler/plugin_factory/Makefile
new file mode 100644
index 0000000..5446327
--- /dev/null
+++ b/note_compiler/plugin_factory/Makefile
@@ -0,0 +1,34 @@
+CXX=g++
+CFLAGS=-Wall -fpic -O2
+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..aca9ff1
--- /dev/null
+++ b/note_compiler/plugin_factory/infile.cpp
@@ -0,0 +1,362 @@
+#include <jack/jack.h>
+
+#include <cmath>
+#include <string>
+#include <iostream>
+
+#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;
+
+ //pfactors/velocity influence are disabled
+// 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];
+ 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;
+ 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 [] osc1.fm_strength;
+ delete env1;
+
+
+ delete [] oscval;
+ delete [] old_oscval;
+}
+void Note::destroy()
+{
+ delete this;
+}
+
+void Note::recalc_factors()
+{
+}
+void Note::apply_pfactor()
+{
+}
+
+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()
+{
+ double tempfreq=double ( freq >> SCALE );
+
+ env0->set_max( ( (osc0.ksl==0) ? ONE : ( fixed_t(double(ONE) / pow(tempfreq, osc0.ksl)) ) ) );
+ env1->set_max( ( (osc1.ksl==0) ? ONE : ( fixed_t(double(ONE) / pow(tempfreq, osc1.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] >>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;
+ Envelope *sel_env=NULL;
+
+ switch (p.osc)
+ {
+ case 0: sel_osc=&osc0; sel_env=env0; break;
+ case 1: sel_osc=&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_osc->fm_strength[p.index]=v; break;
+ case OUTPUT: sel_osc->output=v; break;
+
+ case FILTER_ENABLED: output_note("NOTE: cannot enable filter in playing notes"); 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 FILTER_ENV_AMOUNT: filter_params.env_amount=float(v)/ONE; break;
+ case FILTER_OFFSET: filter_params.freqfactor_offset=float(v)/ONE; break;
+ case FILTER_RESONANCE: filter_params.resonance=float(v)/ONE; break;
+ case FILTER_TREMOLO: filter_params.trem_strength=v; break;
+ case FILTER_TREM_LFO: filter_params.trem_lfo=v; 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)
+{
+ cout << "test" << endl;
+ 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)
+{
+ cout << "inited." << endl;
+ 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/templates/head.1 b/note_compiler/templates/head.1
index 3d9e903..af3c227 100644
--- a/note_compiler/templates/head.1
+++ b/note_compiler/templates/head.1
@@ -1,17 +1,29 @@
#include <jack/jack.h>
#include <cmath>
+#include <string>
-#include "globals.h"
#include "defines.h"
#include "programs.h"
#include "envelope.h"
#include "fixed.h"
#include "filter.h"
#include "note_skel.h"
+#include "util.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:
@@ -25,6 +37,8 @@ class Note : public NoteSkel
bool still_active();
void set_param(const parameter_t &p, fixed_t v);
+ void destroy();
+
private:
void do_ksl();
void do_ksr();
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/synth/Makefile b/synth/Makefile
index f84441c..c1d6dab 100644
--- a/synth/Makefile
+++ b/synth/Makefile
@@ -1,9 +1,9 @@
CXX=g++
-CFLAGS=-Wall -g
+CFLAGS=-Wall -O2
CXXFLAGS=$(CFLAGS)
LDFLAGS=-lm `pkg-config --cflags --libs jack`
-OBJ=channel.o cli.o defines.o envelope.o filter.o globals.o jack.o load.o main.o note.o note_skel.o parser.o programs.o readwave.o util.o
+OBJ=channel.o cli.o defines.o envelope.o filter.o globals.o jack.o load.o main.o note.o note_skel.o parser.o programs.o readwave.o util.o note_loader.o
BIN=synth
DEPENDFILE = .depend
diff --git a/synth/channel.cpp b/synth/channel.cpp
index ddad9fe..d70b199 100644
--- a/synth/channel.cpp
+++ b/synth/channel.cpp
@@ -5,6 +5,8 @@
#include "note.h"
+#include "note_funcs.h"
+
Channel::Channel()
{
@@ -34,7 +36,7 @@ void Channel::cleanup()
for (it=notes.begin(); it!=notes.end(); it++)
if ((*it)->still_active()==false)
{
- delete *it;
+ (*it)->destroy();
it=notes.erase(it);
}
}
@@ -86,15 +88,22 @@ void Channel::note_on(int note, int vel)
{
//if the program has changed, kill the previous note and
//create a new one
- delete n;
+ n->destroy();
notes.clear();
- notes.push_back( new Note(note,(float)vel/128.0,
- curr_prg,
- portamento_frames,
- pitchbend,
- program) );
-
+ NoteSkel *newnote=NULL;
+ if (curr_prg.create_func==NULL)
+ newnote = new Note(note,(float)vel/128.0,
+ curr_prg,
+ portamento_frames, pitchbend,
+ program);
+ else
+ newnote = curr_prg.create_func(note,(float)vel/128.0,
+ curr_prg,
+ portamento_frames, pitchbend,
+ program);
+
+ notes.push_back(newnote);
}
else //program did not change
{
@@ -122,11 +131,22 @@ void Channel::note_on(int note, int vel)
}
}
if (neednewnote)
- notes.push_back( new Note(note,(float)vel/128.0,
- curr_prg,
- portamento_frames,
- pitchbend,
- program) );
+ {
+ NoteSkel *newnote=NULL;
+ if (curr_prg.create_func==NULL)
+ newnote = new Note(note,(float)vel/128.0,
+ curr_prg,
+ portamento_frames, pitchbend,
+ program);
+ else
+ newnote = curr_prg.create_func(note,(float)vel/128.0,
+ curr_prg,
+ portamento_frames, pitchbend,
+ program);
+
+ notes.push_back(newnote);
+ }
+
apply_voice_limit();
}
}
@@ -167,7 +187,7 @@ void Channel::apply_voice_limit()
else
for (int i=0;i<diff;i++)
{
- delete (*it);
+ (*it)->destroy();
it=notes.erase(it);
}
}
@@ -313,7 +333,7 @@ void Channel::panic()
list<NoteSkel*>::iterator it;
for (it=notes.begin(); it!=notes.end();)
{
- delete *it;
+ (*it)->destroy();
it=notes.erase(it);
}
}
diff --git a/synth/globals.cpp b/synth/globals.cpp
index 5b256b3..d6af5f2 100644
--- a/synth/globals.cpp
+++ b/synth/globals.cpp
@@ -3,7 +3,7 @@
fixed_t **lfo[N_LFOS];
fixed_t *curr_lfo[N_LFOS+1];
-fixed_t wave[N_WAVEFORMS][WAVE_RES];
+fixed_t* wave[N_WAVEFORMS];
fixed_t sample_and_hold[N_LFO_LEVELS];
diff --git a/synth/globals.h b/synth/globals.h
index b7c9109..ad921c2 100644
--- a/synth/globals.h
+++ b/synth/globals.h
@@ -14,7 +14,7 @@ using namespace std;
extern fixed_t **lfo[N_LFOS];
extern fixed_t *curr_lfo[N_LFOS+1];
-extern fixed_t wave[N_WAVEFORMS][WAVE_RES];
+extern fixed_t* wave[N_WAVEFORMS];
extern fixed_t sample_and_hold[N_LFO_LEVELS];
diff --git a/synth/jack.cpp b/synth/jack.cpp
index 1c434f9..8d599de 100644
--- a/synth/jack.cpp
+++ b/synth/jack.cpp
@@ -329,8 +329,8 @@ int process_callback(jack_nframes_t nframes, void *notused)
if (lastframe>tmp+44100*4)
{
tmp2=2;
- channel[0]->event(0x90,87,5);
- channel[0]->set_controller(57, 127);
+ //channel[0]->event(0x90,87,5);
+ channel[0]->set_controller(58, 0);
cout << "BÄÄM2" << endl;
}
}
diff --git a/synth/main.cpp b/synth/main.cpp
index ae2e0d8..56c47b9 100644
--- a/synth/main.cpp
+++ b/synth/main.cpp
@@ -12,6 +12,7 @@
#include "programs.h"
#include "defines.h"
#include "globals.h"
+#include "note_loader.h"
using namespace std;
@@ -104,6 +105,24 @@ int main(int argc, char** argv)
try
{
program_settings[i]=parse(programfile[i]);
+
+ // try to load the appropriate .so file
+ if (access( (programfile[i]+".so").c_str(), R_OK ) == 0)
+ {
+ try
+ {
+ cout << "trying to load..."<<endl;
+ load_note_from_so(programfile[i]+".so", program_settings[i]);
+ }
+ catch (string err)
+ {
+ output_note("NOTE: could not load shared object '"+programfile[i]+".so"+"':\n"
+ " "+err+"\n"
+ " this is not fatal, the note has been loaded properly, but generic\n"
+ " unoptimized (slow) code will be used.");
+ }
+ }
+
}
catch (string err)
{
@@ -119,7 +138,9 @@ int main(int argc, char** argv)
}
}
-
+ for (i=0;i<N_WAVEFORMS;i++)
+ wave[i]=new fixed_t[WAVE_RES];
+
for (i=0;i<WAVE_RES;i++)
{
wave[0][i]=sin(i*2.0*3.141592654/WAVE_RES)*ONE;
diff --git a/synth/note.cpp b/synth/note.cpp
index 2f192f2..a0d6226 100644
--- a/synth/note.cpp
+++ b/synth/note.cpp
@@ -393,3 +393,8 @@ fixed_t Note::get_sample()
return out;
}
}
+
+void Note::destroy()
+{
+ delete this;
+}
diff --git a/synth/note.h b/synth/note.h
index aab471c..7c36d69 100644
--- a/synth/note.h
+++ b/synth/note.h
@@ -22,6 +22,8 @@ class Note : public NoteSkel
bool still_active();
void set_param(const parameter_t &p, fixed_t v);
+ void destroy();
+
private:
void do_ksl();
void do_ksr();
diff --git a/synth/note_funcs.h b/synth/note_funcs.h
new file mode 100644
index 0000000..2a9d3c0
--- /dev/null
+++ b/synth/note_funcs.h
@@ -0,0 +1,20 @@
+#ifndef __NOTE_FUNCS_H
+#define __NOTE_FUNCS_H
+
+#include <jack/jack.h>
+
+#include "fixed.h"
+#include <string>
+
+using namespace std;
+
+class NoteSkel;
+struct program_t;
+
+typedef void output_note_func_t(string s);
+typedef string IntToStr_func_t(int i);
+
+typedef NoteSkel* create_func_t (int, float, program_t&, jack_nframes_t, fixed_t, int);
+typedef void init_func_t(int sr, int fupfr, fixed_t **w, fixed_t **clfo, output_note_func_t* out_n, IntToStr_func_t* its);
+
+#endif
diff --git a/synth/note_loader.cpp b/synth/note_loader.cpp
new file mode 100644
index 0000000..b7ccc99
--- /dev/null
+++ b/synth/note_loader.cpp
@@ -0,0 +1,44 @@
+
+#include <iostream>
+#include <dlfcn.h>
+
+#include "note_loader.h"
+#include "programs.h"
+#include "note_funcs.h"
+#include "globals.h"
+
+using namespace std;
+
+void load_note_from_so(string file, program_t &prog)
+{
+ void *handle;
+
+ handle = dlopen(file.c_str(), RTLD_LAZY);
+
+ if (handle==NULL)
+ throw string("could not open shared object (")+string(dlerror())+string(")");
+
+ try
+ {
+ prog.create_func=(create_func_t*) dlsym(handle,"create_note");
+ if (prog.create_func==NULL)
+ throw string("could not find symbol create_note in shared object (")+dlerror()+")";
+
+ init_func_t* initfunc=(init_func_t*) dlsym(handle,"init_vars");
+ if (initfunc==NULL)
+ throw string("could not find symbol init_vars in shared object (")+dlerror()+")";
+
+ initfunc(samp_rate, filter_update_frames, wave, curr_lfo, &output_note, &IntToStr);
+
+
+
+ prog.dl_handle=handle;
+ }
+ catch (string err)
+ {
+ prog.create_func=NULL;
+ prog.dl_handle=NULL;
+ dlclose(handle);
+ throw err;
+ }
+}
diff --git a/synth/note_loader.h b/synth/note_loader.h
new file mode 100644
index 0000000..a922f3c
--- /dev/null
+++ b/synth/note_loader.h
@@ -0,0 +1,13 @@
+#ifndef __NOTE_LOADER_H__
+#define __NOTE_LOADER_H__
+
+#include <string>
+#include <jack/jack.h>
+
+#include "programs.h"
+
+using namespace std;
+
+void load_note_from_so(string file, program_t &prog); //throws string
+
+#endif
diff --git a/synth/note_skel.h b/synth/note_skel.h
index d3b5a13..6aebb8b 100644
--- a/synth/note_skel.h
+++ b/synth/note_skel.h
@@ -30,6 +30,8 @@ class NoteSkel
virtual void set_param(const parameter_t &p, fixed_t v)=0;
+ virtual void destroy()=0;
+
protected:
virtual void do_ksl()=0;
virtual void do_ksr()=0;
diff --git a/synth/programs.cpp b/synth/programs.cpp
index be82fed..094f209 100644
--- a/synth/programs.cpp
+++ b/synth/programs.cpp
@@ -49,6 +49,9 @@ program_t::program_t()
pfactor.fm=NULL;
pfactor.out=NULL;
+
+ create_func=NULL;
+ dl_handle=NULL;
}
program_t::~program_t()
@@ -115,6 +118,10 @@ program_t& program_t::operator=(const program_t &that)
memcpy(this->pfactor.fm[i], that.pfactor.fm[i], sizeof(param_factor_t)*n_osc);
}
+
+ this->create_func=that.create_func;
+ this->dl_handle=that.dl_handle;
+
return *this;
}
else
diff --git a/synth/programs.h b/synth/programs.h
index e0b409c..9d8d8cc 100644
--- a/synth/programs.h
+++ b/synth/programs.h
@@ -7,6 +7,7 @@
#include <list>
#include "fixed.h"
+#include "note_funcs.h"
#include <jack/jack.h>
using namespace std;
@@ -173,7 +174,10 @@ struct program_t
pfactor_formula_t pfactor;
-
+
+ void *dl_handle;
+ create_func_t *create_func;
+
program_t();
~program_t();