[SCM] calf/master: + Organ, synth framework: potentially better pedal handling (both hold and sostenuto)

js at users.alioth.debian.org js at users.alioth.debian.org
Tue May 7 15:37:06 UTC 2013


The following commit has been merged in the master branch:
commit 988c7ac1d6678708ba7b94c8a7b3e509c2e5864c
Author: kfoltman <kfoltman at 78b06b96-2940-0410-b7fc-879d825d01d8>
Date:   Tue Apr 1 20:32:41 2008 +0000

    + Organ, synth framework: potentially better pedal handling (both hold and sostenuto)
    
    
    
    git-svn-id: https://calf.svn.sourceforge.net/svnroot/calf/trunk@141 78b06b96-2940-0410-b7fc-879d825d01d8

diff --git a/src/calf/synth.h b/src/calf/synth.h
index a9fba28..fd2dee0 100644
--- a/src/calf/synth.h
+++ b/src/calf/synth.h
@@ -103,6 +103,9 @@ inline unsigned int midi_note_to_phase(int note, double cents, int sr) {
 class voice {
 public:
     int sample_rate;
+    bool released, sostenuto;
+
+    voice() : sample_rate(-1), released(false), sostenuto(false) {}
 
     /// reset voice to default state (used when a voice is to be reused)
     virtual void setup(int sr) { sample_rate = sr; }
@@ -130,7 +133,6 @@ public:
 /// @todo it would make sense to support all notes off controller too
 struct basic_synth {
 protected:
-    synth::keystack keystack, keystack_hold;
     int sample_rate;
     bool hold, sostenuto;
     std::list<synth::voice *> active_voices;
@@ -151,6 +153,7 @@ public:
     virtual void first_note_on(int note, int vel) {}
     virtual void control_change(int ctl, int val);
     virtual void note_off(int note, int vel);
+    virtual void on_pedal_release();
     virtual ~basic_synth();
 };
 
diff --git a/src/synth.cpp b/src/synth.cpp
index f622ef6..eb137a1 100644
--- a/src/synth.cpp
+++ b/src/synth.cpp
@@ -33,7 +33,8 @@ using namespace synth;
 void basic_synth::kill_note(int note, int vel, bool just_one)
 {
     for (list<synth::voice *>::iterator it = active_voices.begin(); it != active_voices.end(); it++) {
-        if ((*it)->get_current_note() == note) {
+        // preserve sostenuto notes
+        if ((*it)->get_current_note() == note && !(sostenuto && (*it)->sostenuto)) {
             (*it)->note_off(vel);
             if (just_one)
                 return;
@@ -59,13 +60,11 @@ void basic_synth::note_on(int note, int vel)
         note_off(note, 0);
         return;
     }
-    bool perc = keystack_hold.empty() && keystack.empty();
+    bool perc = active_voices.empty();
     synth::voice *v = alloc_voice();
     v->setup(sample_rate);
-    if (hold)
-        keystack_hold.push(note);
-    else
-        keystack.push(note);
+    v->released = false;
+    v->sostenuto = false;
     gate.set(note);
     v->note_on(note, vel);
     active_voices.push_back(v);
@@ -74,31 +73,48 @@ void basic_synth::note_on(int note, int vel)
     }
 }
 
-void basic_synth::note_off(int note, int vel) {
+void basic_synth::note_off(int note, int vel)
+{
     gate.reset(note);
-    if (keystack.pop(note)) {
-        kill_note(note, vel, keystack_hold.has(note));
-    }        
+    if (!hold)
+        kill_note(note, vel, false);
 }
+
+#define for_all_voices(iter) for (std::list<synth::voice *>::iterator iter = active_voices.begin(); iter != active_voices.end(); iter++)
     
+void basic_synth::on_pedal_release()
+{
+    for_all_voices(i)
+    {
+        int note = (*i)->get_current_note();
+        if (note < 0 || note > 127)
+            continue;
+        bool still_held = gate[note];
+        // sostenuto pedal released
+        if ((*i)->sostenuto && !sostenuto)
+        {
+            // mark note as non-sostenuto
+            (*i)->sostenuto = false;
+            // if key still pressed or hold pedal used, hold the note (as non-sostenuto so it can be released later by releasing the key or pedal)
+            // if key has been released and hold pedal is not depressed, release the note
+            if (!still_held && !hold)
+                (*i)->note_off(127);
+        }
+        else if (!hold && !still_held && !(*i)->released)
+        {
+            (*i)->released = true;
+            (*i)->note_off(127);
+        }
+    }
+}
+
 void basic_synth::control_change(int ctl, int val)
 {
     if (ctl == 64) { // HOLD controller
         bool prev = hold;
         hold = (val >= 64);
         if (!hold && prev && !sostenuto) {
-            // HOLD was released - release all keys which were previously held
-            for (int i=0; i<keystack_hold.count(); i++) {
-                int note = keystack_hold.nth(i);
-                if (!gate.test(note)) {
-                    kill_note(note, 0, false);
-                    keystack_hold.pop(note);
-                    i--;
-                }
-            }
-            for (int i=0; i<keystack_hold.count(); i++)
-                keystack.push(keystack_hold.nth(i));
-            keystack_hold.clear();
+            on_pedal_release();
         }
     }
     if (ctl == 66) { // SOSTENUTO controller
@@ -106,28 +122,26 @@ void basic_synth::control_change(int ctl, int val)
         sostenuto = (val >= 64);
         if (sostenuto && !prev) {
             // SOSTENUTO was pressed - move all notes onto sustain stack
-            for (int i=0; i<keystack.count(); i++) {
-                keystack_hold.push(keystack.nth(i));
+            for_all_voices(i) {
+                (*i)->sostenuto = true;
             }
-            keystack.clear();
         }
         if (!sostenuto && prev) {
             // SOSTENUTO was released - release all keys which were previously held
-            for (int i=0; i<keystack_hold.count(); i++) {
-                kill_note(keystack_hold.nth(i), 0, false);
-            }
-            keystack_hold.clear();
+            on_pedal_release();
         }
     }
     if (ctl == 123 || ctl == 120) { // all notes off, all sounds off
         vector<int> notes;
         notes.reserve(128);
-        if (ctl == 120) // for "all sounds off", automatically release hold pedal
+        if (ctl == 120) { // for "all sounds off", automatically release hold and sostenuto pedal
+            control_change(66, 0);
             control_change(64, 0);
-        for (int i = 0; i < keystack.count(); i++)
-            notes.push_back(keystack.nth(i));
-        for (int i = 0; i < (int)notes.size(); i++)
-            note_off(notes[i], 0);
+        }
+        for_all_voices(i)
+        {
+            (*i)->note_off(127);
+        }
     }
     if (ctl == 121) { 
         control_change(1, 0);

-- 
calf audio plugins packaging



More information about the pkg-multimedia-commits mailing list