diff options
-rw-r--r-- | synth/OPTIMIZATIONS | 3 | ||||
-rw-r--r-- | synth/note.cpp | 44 | ||||
-rw-r--r-- | synth/note.h | 8 | ||||
-rw-r--r-- | synth/note_skel.cpp | 2 | ||||
-rw-r--r-- | synth/note_skel.h | 2 | ||||
-rwxr-xr-x | synth/profile.sh | 2 |
6 files changed, 50 insertions, 11 deletions
diff --git a/synth/OPTIMIZATIONS b/synth/OPTIMIZATIONS index 4a22fd4..3ec667b 100644 --- a/synth/OPTIMIZATIONS +++ b/synth/OPTIMIZATIONS @@ -1,5 +1,8 @@ Sinnlose Optimierungen o if(foo.fm_strength!=0) ...: kein effekt, höchstens leichter anstieg! + o dauerndes nutzen von oscillator[i] durch einen curr_osc pointer + ersetzen (um etwa eine standardabweichung schneller -> kein + wirklicher effekt) Mögliche Optimierungen o ??? if (out>0) und was mit lfo: vlt das if weglassen? diff --git a/synth/note.cpp b/synth/note.cpp index f468a79..23267bf 100644 --- a/synth/note.cpp +++ b/synth/note.cpp @@ -50,6 +50,8 @@ Note::Note(int n, float v, program_t &prg, jack_nframes_t pf, fixed_t pb, int pr copy(&prg.osc_settings[0],&prg.osc_settings[n_oscillators],oscillator); copy(&prg.osc_settings[0],&prg.osc_settings[n_oscillators],orig.oscillator); + oscillator_phase_increment=new fixed_t[n_oscillators]; + fm_oscs=new list<int>[n_oscillators]; for (int i=0;i<n_oscillators;++i) for (int j=0;j<n_oscillators;++j) @@ -106,7 +108,7 @@ Note::Note(int n, float v, program_t &prg, jack_nframes_t pf, fixed_t pb, int pr program=prg_no; - + recalc_actual_freq(); } Note::~Note() @@ -123,6 +125,7 @@ Note::~Note() } delete [] oscillator; + delete [] oscillator_phase_increment; delete [] envelope; delete [] factor_env; @@ -135,6 +138,7 @@ Note::~Note() delete [] pfactor.freq_env_amount; delete [] pfactor.fm; + delete [] fm_oscs; } void Note::recalc_factors() @@ -188,7 +192,10 @@ 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: orig.oscillator[p.osc].factor=pow(2.0, (double)v/12.0/ONE)*ONE; oscillator[p.osc].factor=v*freqfactor_factor[p.osc]; break; + case FACTOR: orig.oscillator[p.osc].factor=pow(2.0, (double)v/12.0/ONE)*ONE; + oscillator[p.osc].factor=v*freqfactor_factor[p.osc]; + recalc_oscillator_phase_increment(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; @@ -241,7 +248,7 @@ void Note::set_param(const parameter_t &p, fixed_t v) //ACHTUNG: case FILTER_TREMOLO: filter_params.trem_strength=v; break; case FILTER_TREM_LFO: filter_params.trem_lfo=v; break; - case SYNC_FACTOR: sync_factor=v; break; + case SYNC_FACTOR: sync_factor=pow(2.0, (double)v/12.0/ONE)*ONE; sync_phase_increment=(actual_freq*sync_factor/samp_rate) >> SCALE; 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; @@ -323,11 +330,27 @@ void Note::do_ksl() void Note::do_ksr() { for (int i=0;i<n_oscillators;++i) - envelope[i]->set_ratefactor(1.0 / pow(freq>>SCALE, oscillator[i].ksr)); + envelope[i]->set_ratefactor(1.0 / pow(dest_freq>>SCALE, oscillator[i].ksr)); +} + +void Note::recalc_actual_freq() +{ + actual_freq=freq*pitchbend >>SCALE; + + sync_phase_increment=(actual_freq*sync_factor/samp_rate) >> SCALE; + + for (int i=0;i<n_oscillators;++i) + recalc_oscillator_phase_increment(i); +} + +void Note::recalc_oscillator_phase_increment(int osc) +{ + oscillator_phase_increment[osc]=(actual_freq*oscillator[osc].factor/samp_rate)>>SCALE; } fixed_t Note::get_sample() { + // maybe BOTTLENECK: possible optimisation: only execute every N frames if (freq!=dest_freq) { // the div.by.zero if p_frames=0 is avoided because then the @@ -337,13 +360,13 @@ fixed_t Note::get_sample() 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; + recalc_actual_freq(); + 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; @@ -356,7 +379,7 @@ fixed_t Note::get_sample() if (sync_factor) { - sync_phase+=(actual_freq*sync_factor/samp_rate) >> SCALE; // BOTTLENECK + sync_phase+=sync_phase_increment; // phase-increment depends on: // - actual_freq (which depends on freq and pitchbend) // steadily updated while portamento-ing and whenever a pitchbend comes in @@ -389,6 +412,7 @@ fixed_t Note::get_sample() 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]; + recalc_oscillator_phase_increment(i); } } @@ -404,10 +428,10 @@ fixed_t Note::get_sample() fm=fm>>SCALE; //phase increases in one second, i.e. in samp_rate frames, by the osc's freq - if (oscillator[i].vibrato_depth!=0) - oscillator[i].phase+=( (curr_lfo[oscillator[i].vibrato_lfo][oscillator[i].vibrato_depth]*actual_freq >>SCALE)*oscillator[i].factor/samp_rate)>>SCALE; + if (oscillator[i].vibrato_depth!=0) // BOTTLENECK: update only on lfo recalculation + oscillator[i].phase+=oscillator_phase_increment[i]*curr_lfo[oscillator[i].vibrato_lfo][oscillator[i].vibrato_depth] >>SCALE; else - oscillator[i].phase+=(actual_freq*oscillator[i].factor/samp_rate)>>SCALE; // BOTTLENECK + oscillator[i].phase+=oscillator_phase_increment[i]; // phase-increment depends on: // - actual_freq (which depends on freq and pitchbend) // steadily updated while portamento-ing and whenever a pitchbend comes in diff --git a/synth/note.h b/synth/note.h index 379f2b1..3b8311e 100644 --- a/synth/note.h +++ b/synth/note.h @@ -24,6 +24,8 @@ class Note : public NoteSkel bool still_active(); void set_param(const parameter_t &p, fixed_t v); + void recalc_actual_freq(); + void destroy(); private: @@ -32,6 +34,8 @@ class Note : public NoteSkel void recalc_factors(); void apply_pfactor(); + + void recalc_oscillator_phase_increment(int osc); Envelope **envelope; @@ -45,10 +49,14 @@ class Note : public NoteSkel fixed_t *old_oscval; int n_oscillators; oscillator_t *oscillator; + fixed_t* oscillator_phase_increment; std::list<int>* fm_oscs; fixed_t sync_factor; fixed_t sync_phase; + fixed_t sync_phase_increment; + + fixed_t actual_freq; pfactor_value_t pfactor; diff --git a/synth/note_skel.cpp b/synth/note_skel.cpp index 988f994..f3dd71f 100644 --- a/synth/note_skel.cpp +++ b/synth/note_skel.cpp @@ -18,6 +18,8 @@ NoteSkel::~NoteSkel() void NoteSkel::set_pitchbend(fixed_t pb) { pitchbend=pb; + + recalc_actual_freq(); } void NoteSkel::set_freq(float f) diff --git a/synth/note_skel.h b/synth/note_skel.h index 1afbe3a..4729aed 100644 --- a/synth/note_skel.h +++ b/synth/note_skel.h @@ -31,6 +31,8 @@ class NoteSkel virtual void set_param(const parameter_t &p, fixed_t v)=0; + virtual void recalc_actual_freq()=0; + virtual void destroy()=0; protected: diff --git a/synth/profile.sh b/synth/profile.sh index 921a5d4..a1b8096 100755 --- a/synth/profile.sh +++ b/synth/profile.sh @@ -7,6 +7,6 @@ else fi for ((i=1;i<=$cnt;i++)); do - /usr/bin/time -p ./synth -p 0:analog.prog -i 60 -x 1000:1 -a -m 2>&1 | grep 'user ' | sed 's/user //'; + /usr/bin/time -p ./synth -p 0:../../manyosc2.prog -i 60 -x 1000:1 -a -m 2>&1 | grep 'user ' | sed 's/user //'; #echo "$i / $cnt done" 1>&2 done | python avg_stddev.py |