From eb81cf5820770c54d33facaf09f7f79a17e272ed Mon Sep 17 00:00:00 2001 From: Florian Jung Date: Mon, 10 Jan 2011 17:04:54 +0100 Subject: Implemented handler for soft-pedal Controller 67 aka soft-pedal now can reduce the note's volume by half TODO: - let the user set the percentage for the volume, either per controller (per channel) or per CLI (global) --- TODO | 1 - TODO.done | 2 +- note_compiler/main.cpp | 4 +- note_compiler/parser.cpp | 13 ++-- note_compiler/plugin_factory/infile.cpp | 106 +++++++------------------------- note_compiler/programs.h | 1 - note_compiler/templates/ctor.foot | 1 + note_compiler/templates/head.1 | 2 +- note_compiler/templates/interface.1 | 4 +- synth/Makefile | 2 +- synth/channel.cpp | 21 +++++-- synth/channel.h | 3 + synth/jack.cpp | 2 +- synth/note.cpp | 8 +-- synth/note.h | 2 +- synth/note_funcs.h | 2 +- synth/note_skel.cpp | 9 +++ synth/note_skel.h | 2 + 18 files changed, 72 insertions(+), 113 deletions(-) diff --git a/TODO b/TODO index a77ac04..845f723 100644 --- a/TODO +++ b/TODO @@ -1,6 +1,5 @@ TODO für den synth o bei envelopes: releasephase abschalten (bei sustain bleiben) - o soft-pedal o programme on-the-fly (um)laden o RAM aufräumen? diff --git a/TODO.done b/TODO.done index c03e853..654ff17 100644 --- a/TODO.done +++ b/TODO.done @@ -59,7 +59,7 @@ TODO für den synth x filter_envelope könnte mit anderem ctor geinitet werden (weniger schreibarbeit) x notes compilieren und als .so-datei laden x parser-klasse durch parse-funktion ersetzen - x sostenuto-, halte-, legato-pedal + x sostenuto-, halte-, legato-, soft-pedal TODO fürs CLI diff --git a/note_compiler/main.cpp b/note_compiler/main.cpp index 47ed685..4d3fcae 100644 --- a/note_compiler/main.cpp +++ b/note_compiler/main.cpp @@ -109,7 +109,7 @@ void write_ctor() int i; string tabtmp=""; - out << "Note::Note(int n, float v, program_t &prg, jack_nframes_t pf, fixed_t pb, int prg_no)\n" + out << "Note::Note(int n, float v, program_t &prg, jack_nframes_t pf, fixed_t pb, int prg_no, float vol_fac)\n" "{\n" "\tcurr_prg=&prg;\n" "\t\n" @@ -234,7 +234,7 @@ void write_recalc_factors() out << "\tfor (int i=0;i<"<pfactor.out[i], vel);\n" + "\t\tpfactor.out[i]=calc_pfactor(curr_prg->pfactor.out[i], vel) * volume_factor;\n" "\t\t\n" "\t\tfor (int j=0;j<"<pfactor.fm[i][j], vel);\n" diff --git a/note_compiler/parser.cpp b/note_compiler/parser.cpp index c89ddd9..7fb3fa0 100644 --- a/note_compiler/parser.cpp +++ b/note_compiler/parser.cpp @@ -24,7 +24,6 @@ void init_oscs(int n_osc, oscillator_t *osc) osc[i].output=0; osc[i].output_const=true; - osc[i].output_no_pfactor=false; osc[i].waveform=0; osc[i].waveform_const=true; osc[i].factor=ONE; @@ -370,13 +369,9 @@ program_t parse(string fn) osc[ind].fm_strength_const[ind2]=false; break; case OUTPUT: - if (state==4) // vel.-influence - { - if (isfloat(strval)) //is it a plain number, not a formula? - osc[ind].output_no_pfactor=true; - } - else - osc[ind].output_const=false; break; + if (state!=4) // not vel.-influence + osc[ind].output_const=false; + break; case WAVEFORM: osc[ind].waveform_const=false; break; case FACTOR: @@ -481,7 +476,7 @@ program_t parse(string fn) for (int i=0;iwave_len, osc1.custom_wave->samp_rate); + osc1.phase=ONE * PHASE_INIT; 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); + set_vol_factor(vol_fac); pitchbend=pb; @@ -153,13 +145,9 @@ void Note::destroy() 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); + pfactor.out[i]=calc_pfactor(curr_prg->pfactor.out[i], vel) * volume_factor; for (int j=0;j<2;j++) pfactor.fm[i][j]=calc_pfactor(curr_prg->pfactor.fm[i][j], vel); @@ -167,10 +155,6 @@ void Note::recalc_factors() } 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; @@ -191,8 +175,6 @@ void Note::release() { env0->release_key(); env1->release_key(); - - filter_envelope->release_key(); } void Note::release_quickly(jack_nframes_t maxt) { @@ -209,8 +191,6 @@ void Note::reattack() { env0->reattack(); env1->reattack(); - - filter_envelope->reattack(); } void Note::do_ksr() @@ -249,29 +229,18 @@ fixed_t Note::get_sample() //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 + osc0.phase+= ( (osc0.vibrato_depth==0) ? ((actual_freq*osc0.factor/samp_rate)>>SCALE) : (( (curr_lfo[osc0.vibrato_lfo][osc0.vibrato_depth]*actual_freq >>SCALE)*osc0.factor/samp_rate)>>SCALE) ); + oscval[0] = wave[1][ ( ( osc0.phase + ( + (old_oscval[0] * 104857) + (old_oscval[1] * osc0.fm_strength[1]) >>SCALE ) ) * WAVE_RES >>SCALE ) % WAVE_RES ] * env0->get_level() >>SCALE; + if (osc0.tremolo_depth) + oscval[0] = oscval[0] * curr_lfo[0][osc0.tremolo_depth] >>SCALE; - 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; + osc1.phase+= ( (curr_lfo[osc1.vibrato_lfo][osc1.vibrato_depth]*actual_freq >>SCALE)*osc1.factor/samp_rate)>>SCALE; + oscval[1] = wave[0][ ( osc1.phase * WAVE_RES >>SCALE ) % WAVE_RES ] * env1->get_level() >>SCALE; //oscillator1 has no tremolo - fixed_t out = ( + osc0.output*oscval[0] + osc1.output*oscval[1] >>SCALE ); - + 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; } @@ -318,47 +287,18 @@ void Note::set_param(const parameter_t &p, fixed_t v) 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_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: - if (filter_params.enabled) - filter_envelope->set_hold(v!=0); - else - output_note("NOTE: cannot set filter-hold when filter is disabled"); + case FILTER_OFFSET: + case FILTER_RESONANCE: + case FILTER_TREMOLO: + case FILTER_TREM_LFO: + output_note("NOTE: trying to set some filter-param, but filter is disabled"); break; @@ -370,13 +310,13 @@ void Note::set_param(const parameter_t &p, fixed_t v) -extern "C" NoteSkel* create_note(int n, float v,program_t &prg, jack_nframes_t pf, fixed_t pb, int prg_no) +extern "C" NoteSkel* create_note(int n, float v,program_t &prg, jack_nframes_t pf, fixed_t pb, int prg_no, float vol_fac) { 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); + return new Note(n,v,prg,pf,pb,prg_no,vol_fac); } 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) diff --git a/note_compiler/programs.h b/note_compiler/programs.h index 9025ba1..d7acd61 100644 --- a/note_compiler/programs.h +++ b/note_compiler/programs.h @@ -47,7 +47,6 @@ struct oscillator_t bool *fm_strength_const; fixed_t output; bool output_const; - bool output_no_pfactor; int waveform; bool waveform_const; fixed_t factor; diff --git a/note_compiler/templates/ctor.foot b/note_compiler/templates/ctor.foot index 05d4421..5cc0631 100644 --- a/note_compiler/templates/ctor.foot +++ b/note_compiler/templates/ctor.foot @@ -4,6 +4,7 @@ set_note(n); freq=dest_freq; set_vel(v); + set_vol_factor(vol_fac); pitchbend=pb; diff --git a/note_compiler/templates/head.1 b/note_compiler/templates/head.1 index 6759f56..b50d694 100644 --- a/note_compiler/templates/head.1 +++ b/note_compiler/templates/head.1 @@ -26,7 +26,7 @@ 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(int n, float v,program_t &prg, jack_nframes_t pf, fixed_t pb, int prg_no, float vol_fac); ~Note(); fixed_t get_sample(); diff --git a/note_compiler/templates/interface.1 b/note_compiler/templates/interface.1 index cacc175..2ccee41 100644 --- a/note_compiler/templates/interface.1 +++ b/note_compiler/templates/interface.1 @@ -1,10 +1,10 @@ -extern "C" NoteSkel* create_note(int n, float v,program_t &prg, jack_nframes_t pf, fixed_t pb, int prg_no) +extern "C" NoteSkel* create_note(int n, float v,program_t &prg, jack_nframes_t pf, fixed_t pb, int prg_no, float vol_fac) { 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); + return new Note(n,v,prg,pf,pb,prg_no,vol_fac); } 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) diff --git a/synth/Makefile b/synth/Makefile index c1d6dab..864c0a7 100644 --- a/synth/Makefile +++ b/synth/Makefile @@ -1,5 +1,5 @@ CXX=g++ -CFLAGS=-Wall -O2 +CFLAGS=-Wall -g CXXFLAGS=$(CFLAGS) LDFLAGS=-lm `pkg-config --cflags --libs jack` diff --git a/synth/channel.cpp b/synth/channel.cpp index 0042162..fe28e7d 100644 --- a/synth/channel.cpp +++ b/synth/channel.cpp @@ -28,6 +28,7 @@ Channel::Channel() sostenuto_keys.clear(); hold_pedal_pressed=false; legato_pedal_pressed=false; + curr_vol_factor=1.0; } Channel::~Channel() @@ -117,12 +118,14 @@ void Channel::note_on(int note, int vel) newnote = new Note(note,(float)vel/128.0, curr_prg, portamento_frames, pitchbend, - program); + program, + curr_vol_factor); else newnote = curr_prg.create_func(note,(float)vel/128.0, curr_prg, portamento_frames, pitchbend, - program); + program, + curr_vol_factor); notes.push_back(newnote); } @@ -132,6 +135,7 @@ void Channel::note_on(int note, int vel) n->set_note(note,n->still_active()); n->set_vel((float)vel/128.0); if ((legato_pedal_pressed==false) || !n->still_active()) n->reattack(); + n->set_vol_factor(curr_vol_factor); //no need to push back. would become #1 instead of #1 } } @@ -145,6 +149,7 @@ void Channel::note_on(int note, int vel) neednewnote=false; (*it)->reattack(); (*it)->set_vel((float)vel/128.0); + (*it)->set_vol_factor(curr_vol_factor); notes.push_back(*it); //reorder notes notes.erase(it); break; @@ -157,12 +162,14 @@ void Channel::note_on(int note, int vel) newnote = new Note(note,(float)vel/128.0, curr_prg, portamento_frames, pitchbend, - program); + program, + curr_vol_factor); else newnote = curr_prg.create_func(note,(float)vel/128.0, curr_prg, portamento_frames, pitchbend, - program); + program, + curr_vol_factor); notes.push_back(newnote); } @@ -223,6 +230,7 @@ void Channel::set_controller(int con,int val) case 65: set_portamento(val); break; case 64: set_hold_pedal(val>=64); break; case 66: set_sostenuto_pedal(val>=64); break; + case 67: set_soft_pedal(val>=64); break; case 68: set_legato_pedal(val>=64); break; case 119: set_quick_release(val); case 120: panic(); break; @@ -394,6 +402,11 @@ void Channel::set_legato_pedal(bool newstate) { legato_pedal_pressed=newstate; } + +void Channel::set_soft_pedal(bool newstate) +{ + curr_vol_factor = (newstate==false) ? 1.0 : 0.5; //TODO richtigen wert! +} void Channel::panic() { diff --git a/synth/channel.h b/synth/channel.h index b0a855a..9727ab8 100644 --- a/synth/channel.h +++ b/synth/channel.h @@ -40,6 +40,7 @@ class Channel void set_hold_pedal(bool newstate); void set_sostenuto_pedal(bool newstate); void set_legato_pedal(bool newstate); + void set_soft_pedal(bool newstate); float balL, balR; private: @@ -71,6 +72,8 @@ class Channel set sostenuto_keys; bool legato_pedal_pressed; + + float curr_vol_factor; }; #endif diff --git a/synth/jack.cpp b/synth/jack.cpp index 3949722..0c98855 100644 --- a/synth/jack.cpp +++ b/synth/jack.cpp @@ -12,7 +12,7 @@ using namespace std; -#define DO_DEBUGGING_EVENTS +//#define DO_DEBUGGING_EVENTS jack_port_t *midi_in; jack_port_t *out_port[N_CHANNELS]; diff --git a/synth/note.cpp b/synth/note.cpp index b6bfa22..91291d7 100644 --- a/synth/note.cpp +++ b/synth/note.cpp @@ -14,12 +14,9 @@ inline fixed_t init_custom_osc_phase(int len, fixed_t sr) } -Note::Note(int n, float v, program_t &prg, jack_nframes_t pf, fixed_t pb, int prg_no) +Note::Note(int n, float v, program_t &prg, jack_nframes_t pf, fixed_t pb, int prg_no, float vol_fac) { - curr_prg=&prg; - - n_oscillators=prg.n_osc; @@ -92,6 +89,7 @@ Note::Note(int n, float v, program_t &prg, jack_nframes_t pf, fixed_t pb, int pr set_note(n); freq=dest_freq; set_vel(v); + set_vol_factor(vol_fac); pitchbend=pb; @@ -132,7 +130,7 @@ void Note::recalc_factors() for (int i=0;ipfactor.out[i], vel); + pfactor.out[i]=calc_pfactor(curr_prg->pfactor.out[i], vel) * volume_factor; for (int j=0;jpfactor.fm[i][j], vel); diff --git a/synth/note.h b/synth/note.h index 03a7180..cc043e6 100644 --- a/synth/note.h +++ b/synth/note.h @@ -12,7 +12,7 @@ class Note : public NoteSkel { public: - Note(int n, float v,program_t &prg, jack_nframes_t pf, fixed_t pb, int prg_no); + Note(int n, float v,program_t &prg, jack_nframes_t pf, fixed_t pb, int prg_no, float vol_fac); ~Note(); fixed_t get_sample(); diff --git a/synth/note_funcs.h b/synth/note_funcs.h index 2a9d3c0..08ea7f9 100644 --- a/synth/note_funcs.h +++ b/synth/note_funcs.h @@ -14,7 +14,7 @@ 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 NoteSkel* create_func_t (int, float, program_t&, jack_nframes_t, fixed_t, int, float); 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_skel.cpp b/synth/note_skel.cpp index b028ca4..988f994 100644 --- a/synth/note_skel.cpp +++ b/synth/note_skel.cpp @@ -62,6 +62,14 @@ void NoteSkel::set_vel(float v) apply_pfactor(); } +void NoteSkel::set_vol_factor(float vol_fac) +{ + volume_factor=vol_fac; + + recalc_factors(); + apply_pfactor(); +} + void NoteSkel::set_portamento_frames(jack_nframes_t t) { portamento_frames=t; @@ -72,3 +80,4 @@ int NoteSkel::get_program() { return program; } + diff --git a/synth/note_skel.h b/synth/note_skel.h index 6aebb8b..1afbe3a 100644 --- a/synth/note_skel.h +++ b/synth/note_skel.h @@ -21,6 +21,7 @@ class NoteSkel void set_freq(float f, bool do_port); void set_pitchbend(fixed_t pb); void set_vel(float v); + void set_vol_factor(float vol_fac); void set_portamento_frames(jack_nframes_t f); virtual void release_quickly(jack_nframes_t maxt)=0; @@ -44,6 +45,7 @@ class NoteSkel jack_nframes_t portamento_t, portamento_frames; pfactor_value_t pfactor; + float volume_factor; int note; int program; -- cgit v1.2.1