summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Jung <flo@thinkpad.(none)>2011-01-15 18:13:48 +0100
committerFlorian Jung <flo@thinkpad.(none)>2011-01-15 18:13:48 +0100
commit67025394dcbc2d0917c89856c40be3b9198eca5e (patch)
tree48ac8600e1d4141ee587458db1076e967393fe35
parent9e3998bbaddf4eb6df8544497e42231137824998 (diff)
Implemented freq-envelopes for non-compiled notes
plus some tiny bugfixes: - in Envelope (get_sustain now returns orig_sustain) - parser now uses isnum instead of isfloat where appropriate
-rw-r--r--TODO8
-rw-r--r--TODO.done3
-rw-r--r--synth/envelope.h2
-rw-r--r--synth/note.cpp33
-rw-r--r--synth/note.h3
-rw-r--r--synth/parser.cpp37
-rw-r--r--synth/programs.cpp17
-rw-r--r--synth/programs.h30
-rw-r--r--synth/util.cpp12
9 files changed, 130 insertions, 15 deletions
diff --git a/TODO b/TODO
index fae6026..d6704c7 100644
--- a/TODO
+++ b/TODO
@@ -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?
diff --git a/TODO.done b/TODO.done
index fdfc955..a83b6ed 100644
--- a/TODO.done
+++ b/TODO.done
@@ -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;
}