summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Jung <florian.a.jung@web.de>2012-04-12 22:35:44 +0200
committerFlorian Jung <florian.a.jung@web.de>2012-04-12 22:35:44 +0200
commit2f796b659626569c02dd5016dc3df45000e2b7e2 (patch)
treee014eec75fdf0e0b19041a471c29b39303a18de3
parent7c875a14b73d844f4f3b8390e4463610262d9415 (diff)
use precalculated phase_increment instead of calculating it every
frame: brings up to 33% speed boost! bugfix: ksr now uses dest_freq instead of (current) freq
-rw-r--r--synth/OPTIMIZATIONS3
-rw-r--r--synth/note.cpp44
-rw-r--r--synth/note.h8
-rw-r--r--synth/note_skel.cpp2
-rw-r--r--synth/note_skel.h2
-rwxr-xr-xsynth/profile.sh2
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