From e78131ccbbcb81da94e5992f788c6ea291a2050d Mon Sep 17 00:00:00 2001 From: Florian Jung Date: Thu, 6 Jan 2011 20:16:19 +0100 Subject: 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!) --- TODO | 7 + note_compiler/howtocompile.txt | 4 + note_compiler/main.cpp | 12 +- note_compiler/plugin_factory/Makefile | 34 +++ note_compiler/plugin_factory/channel.cpp | 1 + note_compiler/plugin_factory/channel.h | 1 + note_compiler/plugin_factory/cli.cpp | 1 + note_compiler/plugin_factory/cli.h | 1 + note_compiler/plugin_factory/defines.cpp | 1 + note_compiler/plugin_factory/defines.h | 1 + note_compiler/plugin_factory/envelope.cpp | 1 + note_compiler/plugin_factory/envelope.h | 1 + note_compiler/plugin_factory/filter.cpp | 1 + note_compiler/plugin_factory/filter.h | 1 + note_compiler/plugin_factory/fixed.h | 1 + note_compiler/plugin_factory/globals.cpp | 1 + note_compiler/plugin_factory/globals.h | 1 + note_compiler/plugin_factory/infile.cpp | 362 +++++++++++++++++++++++++++ note_compiler/plugin_factory/jack.cpp | 1 + note_compiler/plugin_factory/jack.h | 1 + note_compiler/plugin_factory/load.cpp | 1 + note_compiler/plugin_factory/load.h | 1 + note_compiler/plugin_factory/main.cpp | 1 + note_compiler/plugin_factory/note.cpp | 1 + note_compiler/plugin_factory/note.h | 1 + note_compiler/plugin_factory/note_funcs.h | 1 + note_compiler/plugin_factory/note_loader.cpp | 1 + note_compiler/plugin_factory/note_loader.h | 1 + note_compiler/plugin_factory/note_skel.cpp | 1 + note_compiler/plugin_factory/note_skel.h | 1 + note_compiler/plugin_factory/parser.cpp | 1 + note_compiler/plugin_factory/parser.h | 1 + note_compiler/plugin_factory/programs.cpp | 1 + note_compiler/plugin_factory/programs.h | 1 + note_compiler/plugin_factory/readwave.cpp | 1 + note_compiler/plugin_factory/readwave.h | 1 + note_compiler/plugin_factory/util.cpp | 1 + note_compiler/plugin_factory/util.h | 1 + note_compiler/templates/head.1 | 16 +- note_compiler/templates/interface.1 | 19 ++ synth/Makefile | 4 +- synth/channel.cpp | 50 ++-- synth/globals.cpp | 2 +- synth/globals.h | 2 +- synth/jack.cpp | 4 +- synth/main.cpp | 23 +- synth/note.cpp | 5 + synth/note.h | 2 + synth/note_funcs.h | 20 ++ synth/note_loader.cpp | 44 ++++ synth/note_loader.h | 13 + synth/note_skel.h | 2 + synth/programs.cpp | 7 + synth/programs.h | 6 +- 54 files changed, 641 insertions(+), 30 deletions(-) create mode 100644 note_compiler/howtocompile.txt create mode 100644 note_compiler/plugin_factory/Makefile create mode 120000 note_compiler/plugin_factory/channel.cpp create mode 120000 note_compiler/plugin_factory/channel.h create mode 120000 note_compiler/plugin_factory/cli.cpp create mode 120000 note_compiler/plugin_factory/cli.h create mode 120000 note_compiler/plugin_factory/defines.cpp create mode 120000 note_compiler/plugin_factory/defines.h create mode 120000 note_compiler/plugin_factory/envelope.cpp create mode 120000 note_compiler/plugin_factory/envelope.h create mode 120000 note_compiler/plugin_factory/filter.cpp create mode 120000 note_compiler/plugin_factory/filter.h create mode 120000 note_compiler/plugin_factory/fixed.h create mode 120000 note_compiler/plugin_factory/globals.cpp create mode 120000 note_compiler/plugin_factory/globals.h create mode 100644 note_compiler/plugin_factory/infile.cpp create mode 120000 note_compiler/plugin_factory/jack.cpp create mode 120000 note_compiler/plugin_factory/jack.h create mode 120000 note_compiler/plugin_factory/load.cpp create mode 120000 note_compiler/plugin_factory/load.h create mode 120000 note_compiler/plugin_factory/main.cpp create mode 120000 note_compiler/plugin_factory/note.cpp create mode 120000 note_compiler/plugin_factory/note.h create mode 120000 note_compiler/plugin_factory/note_funcs.h create mode 120000 note_compiler/plugin_factory/note_loader.cpp create mode 120000 note_compiler/plugin_factory/note_loader.h create mode 120000 note_compiler/plugin_factory/note_skel.cpp create mode 120000 note_compiler/plugin_factory/note_skel.h create mode 120000 note_compiler/plugin_factory/parser.cpp create mode 120000 note_compiler/plugin_factory/parser.h create mode 120000 note_compiler/plugin_factory/programs.cpp create mode 120000 note_compiler/plugin_factory/programs.h create mode 120000 note_compiler/plugin_factory/readwave.cpp create mode 120000 note_compiler/plugin_factory/readwave.h create mode 120000 note_compiler/plugin_factory/util.cpp create mode 120000 note_compiler/plugin_factory/util.h create mode 100644 note_compiler/templates/interface.1 create mode 100644 synth/note_funcs.h create mode 100644 synth/note_loader.cpp create mode 100644 synth/note_loader.h 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 + +#include +#include +#include + +#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 #include +#include -#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;idestroy(); it=notes.erase(it); } } @@ -313,7 +333,7 @@ void Channel::panic() list::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..."< + +#include "fixed.h" +#include + +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 +#include + +#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 +#include + +#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 #include "fixed.h" +#include "note_funcs.h" #include 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(); -- cgit v1.2.1