[SCM] calf/master: + Organ: add polyphony limit support
js at users.alioth.debian.org
js at users.alioth.debian.org
Tue May 7 15:38:47 UTC 2013
The following commit has been merged in the master branch:
commit 98a9771c3d8ab2e14c636885f68de5ad15a82eaa
Author: Krzysztof Foltman <wdev at foltman.com>
Date: Thu Jan 1 15:21:57 2009 +0000
+ Organ: add polyphony limit support
diff --git a/gui/gui-organ.xml b/gui/gui-organ.xml
index 4042361..ee1d6b1 100644
--- a/gui/gui-organ.xml
+++ b/gui/gui-organ.xml
@@ -6,12 +6,19 @@
<line-graph param="master" refresh="1" width="120" height="40" expand="0" fill="0"/>
</align>
</if>
- <align scale-x="0.0" scale-y="0.0" align-x="1.0" align-y="0.5">
- <vbox>
- <label param="master"/>
- <knob param="master"/>
- <value param="master"/>
- </vbox>
+ <align scale-x="0.25" scale-y="0.0" align-x="1.0" align-y="0.5">
+ <hbox>
+ <vbox>
+ <label param="polyphony"/>
+ <knob param="polyphony"/>
+ <value param="polyphony"/>
+ </vbox>
+ <vbox>
+ <label param="master"/>
+ <knob param="master"/>
+ <value param="master"/>
+ </vbox>
+ </hbox>
</align>
</hbox>
<notebook>
diff --git a/src/calf/metadata.h b/src/calf/metadata.h
index 544594c..b340218 100644
--- a/src/calf/metadata.h
+++ b/src/calf/metadata.h
@@ -126,6 +126,7 @@ struct organ_enums
par_eg3attack, par_eg3decay, par_eg3sustain, par_eg3release, par_eg3velscl, par_eg3ampctl,
par_lforate, par_lfoamt, par_lfowet, par_lfophase, par_lfomode,
par_transpose, par_detune,
+ par_polyphony,
par_var_mapcurve,
param_count
};
diff --git a/src/calf/modules_synths.h b/src/calf/modules_synths.h
index 142c01a..c990ddf 100644
--- a/src/calf/modules_synths.h
+++ b/src/calf/modules_synths.h
@@ -216,6 +216,12 @@ public:
void params_changed() {
for (int i = 0; i < param_count - var_count; i++)
((float *)&par_values)[i] = *params[i];
+
+ unsigned int old_poly = polyphony_limit;
+ polyphony_limit = dsp::clip(dsp::fastf2i_drm(*params[par_polyphony]), 1, 32);
+ if (polyphony_limit < old_poly)
+ trim_voices();
+
update_params();
}
inline void pitch_bend(int amt)
diff --git a/src/calf/organ.h b/src/calf/organ.h
index eed6bdb..ca52697 100644
--- a/src/calf/organ.h
+++ b/src/calf/organ.h
@@ -219,6 +219,7 @@ public:
}
void note_on(int note, int vel) {
+ stolen = false;
finishing = false;
perc_released = false;
released = false;
@@ -248,6 +249,12 @@ public:
for (int i = 0; i < EnvCount; i++)
envs[i].note_off();
}
+
+ virtual void steal() {
+ perc_released = true;
+ finishing = true;
+ stolen = true;
+ }
void render_block();
diff --git a/src/calf/synth.h b/src/calf/synth.h
index 7179998..04adb51 100644
--- a/src/calf/synth.h
+++ b/src/calf/synth.h
@@ -103,9 +103,9 @@ inline unsigned int midi_note_to_phase(int note, double cents, int sr) {
class voice {
public:
int sample_rate;
- bool released, sostenuto;
+ bool released, sostenuto, stolen;
- voice() : sample_rate(-1), released(false), sostenuto(false) {}
+ voice() : sample_rate(-1), released(false), sostenuto(false), stolen(false) {}
/// reset voice to default state (used when a voice is to be reused)
virtual void setup(int sr) { sample_rate = sr; }
@@ -119,8 +119,11 @@ public:
virtual bool get_active()=0;
/// render voice data to buffer
virtual void render_to(float (*buf)[2], int nsamples)=0;
+ /// very fast note off
+ virtual void steal()=0;
/// return the note used by this voice
virtual int get_current_note()=0;
+ virtual float get_priority() { return stolen ? 20000 : (released ? 1 : 100); }
/// empty virtual destructor
virtual ~voice() {}
};
@@ -171,7 +174,6 @@ public:
read_ptr += ncopy;
}
}
-
};
/// Base class for all kinds of polyphonic instruments, provides
@@ -194,6 +196,8 @@ protected:
std::stack<dsp::voice *> unused_voices;
/// Gate values for all 128 MIDI notes
std::bitset<128> gate;
+ /// Maximum allocated number of channels
+ unsigned int polyphony_limit;
void kill_note(int note, int vel, bool just_one);
public:
@@ -201,9 +205,12 @@ public:
sample_rate = sr;
hold = false;
sostenuto = false;
+ polyphony_limit = (unsigned)-1;
}
+ virtual void trim_voices();
virtual dsp::voice *give_voice();
virtual dsp::voice *alloc_voice()=0;
+ virtual dsp::voice *steal_voice();
virtual void render_to(float (*output)[2], int nsamples);
virtual void note_on(int note, int vel);
virtual void percussion_note_on(int note, int vel) {}
diff --git a/src/modules.cpp b/src/modules.cpp
index b515de1..bd490b6 100644
--- a/src/modules.cpp
+++ b/src/modules.cpp
@@ -432,6 +432,8 @@ CALF_PORT_PROPS(organ) = {
{ -12, -24, 24, 49, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_SEMITONES, NULL, "transpose", "Transpose" },
{ 0, -100, 100, 201, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "detune", "Detune" },
+
+ { 16, 1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB, NULL, "polyphony", "Polyphony" },
{ 0, 0, 0, 0, PF_STRING | PF_PROP_MSGCONTEXT, &organ_init_map_curve, "map_curve", "Key mapping curve" },
};
diff --git a/src/synth.cpp b/src/synth.cpp
index 50b0246..0f34ec0 100644
--- a/src/synth.cpp
+++ b/src/synth.cpp
@@ -44,6 +44,12 @@ void basic_synth::kill_note(int note, int vel, bool just_one)
dsp::voice *basic_synth::give_voice()
{
+ if (active_voices.size() >= polyphony_limit)
+ {
+ dsp::voice *stolen = steal_voice();
+ if (stolen)
+ return stolen;
+ }
if (unused_voices.empty())
return alloc_voice();
else {
@@ -54,6 +60,42 @@ dsp::voice *basic_synth::give_voice()
}
}
+dsp::voice *basic_synth::steal_voice()
+{
+ std::list<dsp::voice *>::iterator found = active_voices.end();
+ float priority = 10000;
+ for(std::list<dsp::voice *>::iterator i = active_voices.begin(); i != active_voices.end(); i++)
+ {
+ if ((*i)->get_priority() < priority)
+ {
+ priority = (*i)->get_priority();
+ found = i;
+ }
+ }
+ if (found == active_voices.end())
+ return NULL;
+
+ (*found)->steal();
+ return NULL;
+}
+
+void basic_synth::trim_voices()
+{
+ // count stealable voices
+ unsigned int count = 0;
+ for(std::list<dsp::voice *>::iterator i = active_voices.begin(); i != active_voices.end(); i++)
+ {
+ if ((*i)->get_priority() < 10000)
+ count++;
+ }
+ // printf("Count=%d limit=%d\n", count, polyphony_limit);
+ // steal any voices above polyphony limit
+ if (count > polyphony_limit) {
+ for (unsigned int i = 0; i < count - polyphony_limit; i++)
+ steal_voice();
+ }
+}
+
void basic_synth::note_on(int note, int vel)
{
if (!vel) {
@@ -61,7 +103,7 @@ void basic_synth::note_on(int note, int vel)
return;
}
bool perc = check_percussion();
- dsp::voice *v = alloc_voice();
+ dsp::voice *v = give_voice();
v->setup(sample_rate);
v->released = false;
v->sostenuto = false;
--
calf audio plugins packaging
More information about the pkg-multimedia-commits
mailing list