diff options
-rw-r--r-- | TODO | 8 | ||||
-rw-r--r-- | TODO.done | 3 | ||||
-rw-r--r-- | synth/envelope.h | 2 | ||||
-rw-r--r-- | synth/note.cpp | 33 | ||||
-rw-r--r-- | synth/note.h | 3 | ||||
-rw-r--r-- | synth/parser.cpp | 37 | ||||
-rw-r--r-- | synth/programs.cpp | 17 | ||||
-rw-r--r-- | synth/programs.h | 30 | ||||
-rw-r--r-- | synth/util.cpp | 12 |
9 files changed, 130 insertions, 15 deletions
@@ -2,7 +2,13 @@ wenn man danach die noten spielen will. nicht reproduzierbar TODO für den synth -!! o freq-envelopes +!! o im in-synth-cli auch die snh-freq setzen!!! + + o freq-envelopes und pfactor dafür auch für compiled_notes implementieren! + o envelopes nur alle N frames updaten auch bei compiled notes implementieren! + + o optimierung: foo++ durch ++foo ersetzen + o optimierung: bei allen iterationen: foo.end() cachen! o zu testen: funktionieren no-release-envs auch in compilierten noten? @@ -68,7 +68,8 @@ TODO für den synth osc steht) x im cli dürfen warnungen nicht mehr fatal sein x on-the-fly die LFOs ändern - x funktioniert Channel::release_all bei gedrücktem HOLD oder SOSTENUTO? ja. + x funktioniert Channel::release_all bei gedrücktem HOLD oder SOSTENUTO? [ja] + x freq-envelopes: TODO fürs CLI diff --git a/synth/envelope.h b/synth/envelope.h index be50fa2..a9bb15b 100644 --- a/synth/envelope.h +++ b/synth/envelope.h @@ -35,7 +35,7 @@ class Envelope bool get_hold() { return hold; } jack_nframes_t get_attack() { return attack_orig; } jack_nframes_t get_decay() { return decay_orig; } - fixed_t get_sustain() { return sustain; } + fixed_t get_sustain() { return sustain_orig; } jack_nframes_t get_release() { return release_orig; } diff --git a/synth/note.cpp b/synth/note.cpp index 91291d7..35a7115 100644 --- a/synth/note.cpp +++ b/synth/note.cpp @@ -23,10 +23,12 @@ Note::Note(int n, float v, program_t &prg, jack_nframes_t pf, fixed_t pb, int pr pfactor.out=new fixed_t [n_oscillators]; + pfactor.freq_env_amount=new fixed_t [n_oscillators]; pfactor.fm=new fixed_t* [n_oscillators]; for (int i=0;i<n_oscillators;i++) pfactor.fm[i]=new fixed_t [n_oscillators]; + freqfactor_factor=new double[n_oscillators]; envval=new fixed_t[n_oscillators]; oscval=new fixed_t[n_oscillators]; old_oscval=new fixed_t[n_oscillators]; @@ -35,9 +37,13 @@ Note::Note(int n, float v, program_t &prg, jack_nframes_t pf, fixed_t pb, int pr envval[i]=oscval[i]=old_oscval[i]=0; envelope=new Envelope*[n_oscillators]; + factor_env=new Envelope*[n_oscillators]; for (int i=0;i<n_oscillators;i++) + { envelope[i]=new Envelope(prg.env_settings[i], envelope_update_frames); + factor_env[i]=new Envelope(prg.osc_settings[i].freq_env, envelope_update_frames); + } oscillator=new oscillator_t[n_oscillators]; orig.oscillator=new oscillator_t[n_oscillators]; @@ -106,18 +112,22 @@ Note::~Note() { delete [] oscillator[i].fm_strength; delete envelope[i]; + delete factor_env[i]; delete [] pfactor.fm[i]; } delete [] oscillator; delete [] envelope; + delete [] factor_env; + delete [] freqfactor_factor; delete [] envval; delete [] oscval; delete [] old_oscval; delete [] pfactor.out; + delete [] pfactor.freq_env_amount; delete [] pfactor.fm; } @@ -131,6 +141,7 @@ void Note::recalc_factors() for (int i=0;i<n_oscillators;i++) { pfactor.out[i]=calc_pfactor(curr_prg->pfactor.out[i], vel) * volume_factor; + pfactor.freq_env_amount[i]=calc_pfactor(curr_prg->pfactor.freq_env_amount[i], vel); for (int j=0;j<n_oscillators;j++) pfactor.fm[i][j]=calc_pfactor(curr_prg->pfactor.fm[i][j], vel); @@ -143,6 +154,7 @@ void Note::apply_pfactor() for (int i=0;i<n_oscillators;i++) { oscillator[i].output=orig.oscillator[i].output*pfactor.out[i] >>SCALE; + oscillator[i].freq_env_amount=orig.oscillator[i].freq_env_amount*pfactor.freq_env_amount[i] /ONE; //because it's a float for (int j=0;j<n_oscillators;j++) oscillator[i].fm_strength[j]=orig.oscillator[i].fm_strength[j]*pfactor.fm[i][j] >>SCALE; @@ -166,7 +178,7 @@ void Note::set_param(const parameter_t &p, fixed_t v) //ACHTUNG: case KSR: oscillator[p.osc].ksr=float(v)/ONE; break; case KSL: oscillator[p.osc].ksl=float(v)/ONE; break; - case FACTOR: oscillator[p.osc].factor=v; break; + case FACTOR: orig.oscillator[p.osc].factor=v; oscillator[p.osc].factor=v*freqfactor_factor[p.osc]; break; case MODULATION: orig.oscillator[p.osc].fm_strength[p.index]=v; apply_pfactor(); break; case OUTPUT: orig.oscillator[p.osc].output=v; apply_pfactor(); break; case TREMOLO: oscillator[p.osc].tremolo_depth=v; break; @@ -220,6 +232,14 @@ void Note::set_param(const parameter_t &p, fixed_t v) //ACHTUNG: case FILTER_TREM_LFO: filter_params.trem_lfo=v; break; case SYNC_FACTOR: sync_factor=v; break; + + case FREQ_ATTACK: factor_env[p.osc]->set_attack(v*samp_rate >>SCALE); break; + case FREQ_DECAY: factor_env[p.osc]->set_decay(v*samp_rate >>SCALE); break; + case FREQ_SUSTAIN: factor_env[p.osc]->set_sustain(v); break; + case FREQ_RELEASE: factor_env[p.osc]->set_release(v*samp_rate >>SCALE); break; + case FREQ_HOLD: factor_env[p.osc]->set_hold((v!=0)); break; + case FREQ_ENV_AMOUNT: orig.oscillator[p.osc].freq_env_amount=double(v)/ONE; apply_pfactor(); break; + default: throw string("trying to set an unknown parameter"); } @@ -255,7 +275,10 @@ void Note::release_quickly(jack_nframes_t maxt) void Note::release() { for (int i=0;i<n_oscillators;i++) + { envelope[i]->release_key(); + factor_env[i]->release_key(); + } if (filter_params.enabled) filter_envelope->release_key(); @@ -264,7 +287,10 @@ void Note::release() void Note::reattack() { for (int i=0;i<n_oscillators;i++) + { envelope[i]->reattack(); + factor_env[i]->reattack(); + } if (filter_params.enabled) filter_envelope->reattack(); @@ -343,7 +369,12 @@ fixed_t Note::get_sample() { env_frame_counter=0; for (i=0;i<n_oscillators;i++) + { envval[i]=envelope[i]->get_level(); + + freqfactor_factor[i]=pow(2.0, oscillator[i].freq_env_amount*(factor_env[i]->get_level() - factor_env[i]->get_sustain())/ONE); + oscillator[i].factor=orig.oscillator[i].factor*freqfactor_factor[i]; + } } diff --git a/synth/note.h b/synth/note.h index cc043e6..7181f6d 100644 --- a/synth/note.h +++ b/synth/note.h @@ -35,6 +35,9 @@ class Note : public NoteSkel int env_frame_counter; + double *freqfactor_factor; + Envelope **factor_env; + fixed_t *envval; fixed_t *oscval; fixed_t *old_oscval; diff --git a/synth/parser.cpp b/synth/parser.cpp index 10accac..cd4ed02 100644 --- a/synth/parser.cpp +++ b/synth/parser.cpp @@ -198,6 +198,13 @@ void init_oscs(int n_osc, oscillator_t *osc) osc[i].vibrato_depth=0; osc[i].vibrato_lfo=0; osc[i].custom_wave=NULL; + + osc[i].freq_env_amount=0; + osc[i].freq_env.attack=0; + osc[i].freq_env.decay=0; + osc[i].freq_env.sustain=ONE; + osc[i].freq_env.release=-1; + osc[i].freq_env.hold=true; } } @@ -231,6 +238,7 @@ void init_filter(filter_params_t &filter) void init_pfactors(int n_osc, pfactor_formula_t &pfactor) { pfactor.out=new param_factor_t [n_osc]; + pfactor.freq_env_amount=new param_factor_t [n_osc]; pfactor.fm=new param_factor_t* [n_osc]; pfactor.filter_env.offset=ONE; @@ -247,6 +255,9 @@ void init_pfactors(int n_osc, pfactor_formula_t &pfactor) pfactor.out[i].offset=0; pfactor.out[i].vel_amount=ONE; + pfactor.freq_env_amount[i].offset=0; + pfactor.freq_env_amount[i].vel_amount=ONE; + pfactor.fm[i]=new param_factor_t [n_osc]; for (int j=0;j<n_osc;j++) { @@ -380,7 +391,7 @@ program_t parse(string fn) osc[ind].output=val*ONE; break; case WAVEFORM: - if (isfloat(strval)) + if (isnum(strval)) { osc[ind].waveform=int(val); } @@ -497,6 +508,26 @@ program_t parse(string fn) case SYNC_FACTOR: sync_factor=val*ONE; break; + + case FREQ_ATTACK: + osc[ind].freq_env.attack=val*samp_rate; + break; + case FREQ_DECAY: + osc[ind].freq_env.decay=val*samp_rate; + break; + case FREQ_SUSTAIN: + osc[ind].freq_env.sustain=val*ONE; + break; + case FREQ_RELEASE: + osc[ind].freq_env.release=val*samp_rate; + break; + case FREQ_HOLD: + osc[ind].freq_env.hold=(val!=0); + break; + case FREQ_ENV_AMOUNT: + osc[ind].freq_env_amount=val; + break; + default: throw string("unknown variable ('"+array+"')"); } @@ -584,6 +615,10 @@ program_t parse(string fn) case FILTER_OFFSET: pfactor.filter_offset=parse_pfactor(strval); break; + + case FREQ_ENV_AMOUNT: + pfactor.freq_env_amount[ind]=parse_pfactor(strval); + break; default: throw string("velocity cannot influence parameter '"+array+"'"); diff --git a/synth/programs.cpp b/synth/programs.cpp index b896a06..0f675d6 100644 --- a/synth/programs.cpp +++ b/synth/programs.cpp @@ -51,6 +51,7 @@ program_t::program_t() pfactor.fm=NULL; pfactor.out=NULL; + pfactor.freq_env_amount=NULL; create_func=NULL; dl_handle=NULL; @@ -74,6 +75,8 @@ void program_t::cleanup() if (pfactor.out) delete [] pfactor.out; + if (pfactor.freq_env_amount) + delete [] pfactor.freq_env_amount; if (pfactor.fm) { for (unsigned int i=0;i<n_osc;i++) @@ -119,6 +122,9 @@ program_t& program_t::operator=(const program_t &that) this->pfactor.out=new param_factor_t [n_osc]; memcpy(this->pfactor.out, that.pfactor.out, sizeof(param_factor_t)*n_osc); + this->pfactor.freq_env_amount=new param_factor_t [n_osc]; + memcpy(this->pfactor.freq_env_amount, that.pfactor.freq_env_amount, sizeof(param_factor_t)*n_osc); + this->pfactor.fm=new param_factor_t* [n_osc]; for (i=0;i<n_osc;i++) { @@ -174,6 +180,13 @@ void program_t::set_param(const parameter_t &p, fixed_t v) //ACHTUNG: case FILTER_TREM_LFO: filter_settings.trem_lfo=v; break; case SYNC_FACTOR: sync_factor=v; break; + + case FREQ_ATTACK: osc_settings[p.osc].freq_env.attack=v*samp_rate >>SCALE; break; + case FREQ_DECAY: osc_settings[p.osc].freq_env.decay=v*samp_rate >>SCALE; break; + case FREQ_SUSTAIN: osc_settings[p.osc].freq_env.sustain=v; break; + case FREQ_RELEASE: osc_settings[p.osc].freq_env.release=v*samp_rate >>SCALE; break; + case FREQ_HOLD: osc_settings[p.osc].freq_env.hold=(v!=0); break; + case FREQ_ENV_AMOUNT: osc_settings[p.osc].freq_env_amount=double(v)/ONE; break; default: throw string("trying to set an unknown parameter"); } @@ -220,6 +233,7 @@ void init_default_program(program_t &p) p.pfactor.out=new param_factor_t [1]; + p.pfactor.freq_env_amount=new param_factor_t [1]; p.pfactor.fm=new param_factor_t* [1]; p.pfactor.filter_env.offset=ONE; @@ -232,6 +246,9 @@ void init_default_program(program_t &p) p.pfactor.out[0].offset=0; p.pfactor.out[0].vel_amount=ONE; + + p.pfactor.freq_env_amount[0].offset=ONE; + p.pfactor.freq_env_amount[0].vel_amount=0; p.pfactor.fm[0]=new param_factor_t [1]; p.pfactor.fm[0][0].offset=ONE; diff --git a/synth/programs.h b/synth/programs.h index 1ed9d6f..3ca4a65 100644 --- a/synth/programs.h +++ b/synth/programs.h @@ -48,7 +48,12 @@ enum parameter_enum FILTER_TREMOLO, FILTER_TREM_LFO, SYNC_FACTOR, - + FREQ_ATTACK, + FREQ_DECAY, + FREQ_SUSTAIN, + FREQ_RELEASE, + FREQ_HOLD, + FREQ_ENV_AMOUNT, PARAMETER_N_ENTRIES, UNKNOWN=-1 @@ -75,6 +80,7 @@ struct pfactor_formula_t { param_factor_t **fm; param_factor_t *out; + param_factor_t *freq_env_amount; param_factor_t filter_env; param_factor_t filter_res; param_factor_t filter_offset; @@ -84,6 +90,7 @@ struct pfactor_value_t { fixed_t **fm; fixed_t *out; + fixed_t *freq_env_amount; fixed_t filter_env; fixed_t filter_res; fixed_t filter_offset; @@ -113,12 +120,24 @@ struct custom_wave_t }; +struct env_settings_t +{ + jack_nframes_t attack; + jack_nframes_t decay; + fixed_t sustain; + signed int release; + bool hold; +}; + struct oscillator_t { fixed_t *fm_strength; //this osc gets modulated by osc #i by fm_strength[i]. fixed_t output; //NOT: osc #i gets modulated by this osc! int waveform; fixed_t factor; + float freq_env_amount; + env_settings_t freq_env; + fixed_t phase; fixed_t tremolo_depth; @@ -139,15 +158,6 @@ struct oscillator_t oscillator_t& operator=(const oscillator_t &that); }; -struct env_settings_t -{ - jack_nframes_t attack; - jack_nframes_t decay; - fixed_t sustain; - signed int release; - bool hold; -}; - struct filter_params_t { bool enabled; diff --git a/synth/util.cpp b/synth/util.cpp index 2862fdb..c54f2d5 100644 --- a/synth/util.cpp +++ b/synth/util.cpp @@ -171,6 +171,18 @@ parameter_enum param_to_enum(string param) return FILTER_TREM_LFO; else if (param=="sync_factor") return SYNC_FACTOR; + else if (param=="freq.env_amount") + return FREQ_ENV_AMOUNT; + else if (param=="freq.attack") + return FREQ_ATTACK; + else if (param=="freq.decay") + return FREQ_DECAY; + else if (param=="freq.sustain") + return FREQ_SUSTAIN; + else if (param=="freq.release") + return FREQ_RELEASE; + else if (param=="freq.hold") + return FREQ_HOLD; else return UNKNOWN; } |