From d84da6cdfb9027a67b8ab50fe2c23374acc3b245 Mon Sep 17 00:00:00 2001 From: Florian Jung Date: Sat, 8 Jan 2011 18:27:40 +0100 Subject: Added some of the bugfixes to the note_compiler and removed use_pfactor --- TODO | 6 +- note_compiler/main.cpp | 133 +++++++------------- note_compiler/parser.cpp | 4 - note_compiler/plugin_factory/infile.cpp | 189 +++++++++++++++------------- note_compiler/programs.h | 2 - note_compiler/templates/set_param.1 | 2 + note_compiler/templates/set_param.2 | 34 ----- note_compiler/templates/set_param.filter | 7 ++ note_compiler/templates/set_param.filterenv | 34 +++++ 9 files changed, 195 insertions(+), 216 deletions(-) delete mode 100644 note_compiler/templates/set_param.2 create mode 100644 note_compiler/templates/set_param.filter create mode 100644 note_compiler/templates/set_param.filterenv diff --git a/TODO b/TODO index f8155f6..0dda219 100644 --- a/TODO +++ b/TODO @@ -5,16 +5,16 @@ TODO für den synth o note-compiler: vel_influence ist IMMER gegeben für output, außer wenn anders angegeben o note-compiler: *1 bzw /2 optimierungen klappen nicht? - o note-compiler: pfactor nicht wegoptimieren, immer verwenden + x note-compiler: pfactor nicht wegoptimieren, immer verwenden o beide parser: envelopes von oscs mit out=0 standardmäßig deaktivieren 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.) x wave auf int*[] mit wave[i]=new int[] umbauen -!!!x BUG: bei Note::set_param sollte statt dem eigentlichen param + x BUG: bei Note::set_param sollte statt dem eigentlichen param der orig gesetzt werden und dann neu berechnet werden! -!!!x BUG: bei release und reattack: BEIDE male die filter-envelope beachten! + x BUG: bei release und reattack: BEIDE male die filter-envelope beachten! o KSL mit powf und floats statt mit double umschreiben o statt lfo-nummer direkten zugriff auf curr_lfo angeben? x oscval-nullen kann in get_sample() weggelassen werden diff --git a/note_compiler/main.cpp b/note_compiler/main.cpp index 38302ef..47ed685 100644 --- a/note_compiler/main.cpp +++ b/note_compiler/main.cpp @@ -92,20 +92,15 @@ void write_filter_decs() void write_pfactor_decs() { - if (prog.use_pfactor) - { - 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"; - } + 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//pfactors/velocity influence are disabled\n"; + comment << "\t\t\t//filter is disabled\n"; + out << "\t\t} orig;\n"; } @@ -139,9 +134,8 @@ void write_ctor() for (i=0;ipfactor.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<"<pfactor.out[i], vel);\n" - "\t\t\n" - "\t\tfor (int j=0;j<"<pfactor.fm[i][j], vel);\n" - "\t}\n"; + 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<"<pfactor.out[i], vel);\n" + "\t\t\n" + "\t\tfor (int j=0;j<"<pfactor.fm[i][j], vel);\n" + "\t}\n"; + out << "}\n"; } @@ -263,20 +248,17 @@ void write_apply_pfactor() out << "void Note::apply_pfactor()\n" "{\n"; - if (prog.use_pfactor) + 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>SCALE;\n" - "\tfor (int i=0;i<"<>SCALE;\n"; - } + out << "\tosc"<>SCALE;\n" + "\tfor (int i=0;i<"<>SCALE;\n"; } out << "}\n"; @@ -661,15 +643,16 @@ void write_set_param() { out << "void Note::set_param(const parameter_t &p, fixed_t v)\n" "{\n" - "\toscillator_t *sel_osc=NULL;\n" - "\tEnvelope *sel_env=NULL;\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;ifm_strength[p.index]=v*pfactor.fm[p.osc][p.index] >>SCALE; break;\n" - "\t\tcase OUTPUT: sel_osc->output=v*pfactor.out[p.osc] >>SCALE; break;\n"; - else - out << "\t\tcase MODULATION: sel_osc->fm_strength[p.index]=v; break;\n" - "\t\tcase OUTPUT: sel_osc->output=v; break;\n"; - if ((prog.filter.enabled==true) || (prog.filter.enabled_const==false)) { - out << "\t\t\n" - "\t\tcase FILTER_ENABLED: output_note(\"NOTE: cannot enable filter in playing notes\"); break;\n" - "\t\t\n"; - + include_file("set_param.filter"); if (prog.filter.env_settings.enabled) - include_file("set_param.2"); + include_file("set_param.filterenv"); else include_file("set_param.nofilterenv"); - - if (prog.use_pfactor) - out << "\t\tcase FILTER_ENV_AMOUNT: filter_params.env_amount=float(v*pfactor.filter_env)/ONE/ONE; break;\n" - "\t\tcase FILTER_OFFSET: filter_params.freqfactor_offset=float(v*pfactor.filter_offset)/ONE/ONE; break;\n" - "\t\tcase FILTER_RESONANCE: filter_params.resonance=float(v*pfactor.filter_res)/ONE/ONE; break;\n"; - else - out << "\t\tcase FILTER_ENV_AMOUNT: filter_params.env_amount=float(v)/ONE; break;\n" - "\t\tcase FILTER_OFFSET: filter_params.freqfactor_offset=float(v)/ONE; break;\n" - "\t\tcase FILTER_RESONANCE: filter_params.resonance=float(v)/ONE; break;\n"; - - out << "\t\tcase FILTER_TREMOLO: filter_params.trem_strength=v; break;\n" - "\t\tcase FILTER_TREM_LFO: filter_params.trem_lfo=v; break;\n"; } else include_file("set_param.nofilter"); diff --git a/note_compiler/parser.cpp b/note_compiler/parser.cpp index 17c197f..b15b981 100644 --- a/note_compiler/parser.cpp +++ b/note_compiler/parser.cpp @@ -126,8 +126,6 @@ program_t parse(string fn) fixed_t sync_factor=0; bool sync_factor_const=true; - bool use_pfactor=true; //TODO FINDMICH war false - char buf[2000]; string line; string var; @@ -358,7 +356,6 @@ program_t parse(string fn) default: // other params than the above may not be influenced! throw string("velocity cannot influence parameter '"+array+"'"); } - use_pfactor=true; } @@ -475,7 +472,6 @@ program_t parse(string fn) result.filter=filter; result.sync_factor=sync_factor; result.sync_factor_const=sync_factor_const; - result.use_pfactor=use_pfactor; } else throw string ("could not open '"+fn+"'"); diff --git a/note_compiler/plugin_factory/infile.cpp b/note_compiler/plugin_factory/infile.cpp index 147aec0..3523fd8 100644 --- a/note_compiler/plugin_factory/infile.cpp +++ b/note_compiler/plugin_factory/infile.cpp @@ -48,30 +48,27 @@ class Note : public NoteSkel // member variables begin here Envelope *env0; - //envelope1 is unused - //envelope2 is unused - //envelope3 is unused + Envelope *env1; fixed_t *oscval; fixed_t *old_oscval; oscillator_t osc0; oscillator_t osc1; - oscillator_t osc2; - oscillator_t osc3; //sync is disabled - //filter 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; - oscillator_t osc2; - oscillator_t osc3; - //filter is disabled + filter_params_t filter_params; } orig; // member variables end here }; @@ -89,39 +86,37 @@ Note::Note(int n, float v, program_t &prg, jack_nframes_t pf, fixed_t pb, int pr { curr_prg=&prg; - oscval=new fixed_t[4]; - old_oscval=new fixed_t[4]; - for (int i=0;i<4;i++) + 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 [4]; - pfactor.fm=new fixed_t* [4]; - for (int i=0;i<4;i++) - pfactor.fm[i]=new fixed_t [4]; + 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]); - //envelope1 is disabled - //envelope2 is disabled - //envelope3 is disabled + 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]; - osc2=prg.osc_settings[2]; - orig.osc2=prg.osc_settings[2]; - osc3=prg.osc_settings[3]; - orig.osc3=prg.osc_settings[3]; //initalize oscillator.phase to multiples of their wave resolution osc0.phase=ONE * PHASE_INIT; - osc1.phase=ONE * PHASE_INIT; - osc2.phase=ONE * PHASE_INIT; - osc3.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); @@ -141,17 +136,9 @@ Note::~Note() delete pfactor.fm[0]; delete [] osc1.fm_strength; - //envelope1 is disabled + delete env1; delete pfactor.fm[1]; - delete [] osc2.fm_strength; - //envelope2 is disabled - delete pfactor.fm[2]; - - delete [] osc3.fm_strength; - //envelope3 is disabled - delete pfactor.fm[3]; - delete [] oscval; delete [] old_oscval; @@ -166,36 +153,36 @@ void Note::destroy() void Note::recalc_factors() { - for (int i=0;i<4;i++) + 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<4;j++) + 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<4;i++) + 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<4;i++) + for (int i=0;i<2;i++) osc1.fm_strength[i]=orig.osc1.fm_strength[i]*pfactor.fm[1][i] >>SCALE; - osc2.output=orig.osc2.output*pfactor.out[2] >>SCALE; - for (int i=0;i<4;i++) - osc2.fm_strength[i]=orig.osc2.fm_strength[i]*pfactor.fm[2][i] >>SCALE; - osc3.output=orig.osc3.output*pfactor.out[3] >>SCALE; - for (int i=0;i<4;i++) - osc3.fm_strength[i]=orig.osc3.fm_strength[i]*pfactor.fm[3][i] >>SCALE; } bool Note::still_active() { if ( ((osc0.output>0) && (env0->still_active())) - /* envelope1 is disabled */ - /* envelope2 is disabled */ - /* envelope3 is disabled */ ) + || ((osc1.output>0) && (env1->still_active())) ) return true; else return false; @@ -203,9 +190,9 @@ bool Note::still_active() void Note::release() { env0->release_key(); - //envelope1 is disabled - //envelope2 is disabled - //envelope3 is disabled + env1->release_key(); + + filter_envelope->release_key(); } void Note::release_quickly(jack_nframes_t maxt) { @@ -213,27 +200,23 @@ void Note::release_quickly(jack_nframes_t maxt) env0->set_release(maxt); env0->release_key(); - //envelope1 is disabled - - //envelope2 is disabled - - //envelope3 is disabled + if (env1->get_release() > maxt) + env1->set_release(maxt); + env1->release_key(); } void Note::reattack() { env0->reattack(); - //envelope1 is disabled - //envelope2 is disabled - //envelope3 is disabled + env1->reattack(); + + filter_envelope->reattack(); } void Note::do_ksr() { env0->set_ratefactor(1.0 / pow(freq>>SCALE, osc0.ksr)); - //envelope1 is disabled - //envelope2 is disabled - //envelope3 is disabled + env1->set_ratefactor(1.0 / pow(freq>>SCALE, osc1.ksr)); } void Note::do_ksl() { @@ -267,39 +250,42 @@ fixed_t Note::get_sample() osc0.phase+= (actual_freq*osc0.factor/samp_rate)>>SCALE; - oscval[0] = wave[0][ ( ( osc0.phase + ( + (old_oscval[1]) ) ) * WAVE_RES >>SCALE ) % WAVE_RES ] * env0->get_level() >>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] = wave[0][ ( ( osc1.phase + ( + (old_oscval[2] /2) ) ) * WAVE_RES >>SCALE ) % WAVE_RES ]; + 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 - osc2.phase+= (actual_freq*osc2.factor/samp_rate)>>SCALE; - oscval[2] = wave[0][ ( ( osc2.phase + ( + (old_oscval[3] * 209715) >>SCALE ) ) * WAVE_RES >>SCALE ) % WAVE_RES ]; - //oscillator2 has no tremolo - - osc3.phase+= (actual_freq*osc3.factor/samp_rate)>>SCALE; - oscval[3] = wave[0][ ( osc3.phase * WAVE_RES >>SCALE ) % WAVE_RES ]; - //oscillator3 has no tremolo + fixed_t out = ( + osc0.output*oscval[0] + osc1.output*oscval[1] >>SCALE ); - fixed_t out = ( + osc0.output*oscval[0] + osc1.output*oscval[1] + osc2.output*oscval[2] + osc3.output*oscval[3] >>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; + oscillator_t* sel_osc=NULL; + oscillator_t* sel_orig_osc=NULL; + Envelope* sel_env=NULL; switch (p.osc) { - case 0: sel_osc=&osc0; sel_env=env0; break; - case 1: sel_osc=&osc1; /* envelope1 is disabled */ break; - case 2: sel_osc=&osc2; /* envelope2 is disabled */ break; - case 3: sel_osc=&osc3; /* envelope3 is disabled */ break; + 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)); } @@ -329,21 +315,50 @@ void Note::set_param(const parameter_t &p, fixed_t v) 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 MODULATION: sel_osc->fm_strength[p.index]=v*pfactor.fm[p.osc][p.index] >>SCALE; break; - case OUTPUT: sel_osc->output=v*pfactor.out[p.osc] >>SCALE; break; - case FILTER_ENABLED: - case FILTER_ENV_AMOUNT: 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: - 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"); + 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/programs.h b/note_compiler/programs.h index f290e35..d7acd61 100644 --- a/note_compiler/programs.h +++ b/note_compiler/programs.h @@ -115,8 +115,6 @@ struct program_t fixed_t sync_factor; bool sync_factor_const; - - bool use_pfactor; }; #endif diff --git a/note_compiler/templates/set_param.1 b/note_compiler/templates/set_param.1 index 3d20dfe..21fc983 100644 --- a/note_compiler/templates/set_param.1 +++ b/note_compiler/templates/set_param.1 @@ -23,3 +23,5 @@ 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.2 b/note_compiler/templates/set_param.2 deleted file mode 100644 index aaa21b4..0000000 --- a/note_compiler/templates/set_param.2 +++ /dev/null @@ -1,34 +0,0 @@ - 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.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; -- cgit v1.2.1