summaryrefslogtreecommitdiff
path: root/synth/note.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'synth/note.cpp')
-rw-r--r--synth/note.cpp44
1 files changed, 34 insertions, 10 deletions
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