[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