diff options
author | Florian Jung <flo@thinkpad.(none)> | 2011-01-09 19:09:05 +0100 |
---|---|---|
committer | Florian Jung <flo@thinkpad.(none)> | 2011-01-09 19:09:05 +0100 |
commit | df97e0ebb7f6591c50f3a588cb2a74901d38ac4a (patch) | |
tree | aa68ab5a73388d57636a4e5c9058b9dcc0f21e90 /note_compiler/plugin_factory | |
parent | aa1c06213e695be1dcb5980b638d8ce81efb4f51 (diff) |
Merged branch for compiled notes
The synthesizer is now able to load and use compiled, optimized shared
objects of programs. There's also a note-compiler which creates the code
for such objects.
TODO:
- let the note-compiler automatically compile OR rename it to
code-emitter
Diffstat (limited to 'note_compiler/plugin_factory')
35 files changed, 459 insertions, 0 deletions
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 |