[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