summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--synth/channel.cpp71
-rw-r--r--synth/channel.h12
2 files changed, 79 insertions, 4 deletions
diff --git a/synth/channel.cpp b/synth/channel.cpp
index 35ee375..ef215c9 100644
--- a/synth/channel.cpp
+++ b/synth/channel.cpp
@@ -18,6 +18,11 @@ Channel::Channel()
max_pitchbend=1.0;
set_balance(64);
+
+ pressed_keys.clear();
+ held_keys.clear();
+ sostenuto_keys.clear();
+ hold_pedal_pressed=false;
}
Channel::~Channel()
@@ -65,7 +70,21 @@ void Channel::event(uint8_t a, uint8_t b, uint8_t c)
void Channel::note_off(int note)
{
- note_on(note,0);
+ pressed_keys.erase(note);
+
+ if (hold_pedal_pressed)
+ held_keys.insert(note);
+ else if (sostenuto_keys.find(note)!=sostenuto_keys.end())
+ /* do nothing */;
+ else
+ really_do_note_off(note);
+}
+
+void Channel::really_do_note_off(int note)
+{
+ for (list<Note*>::iterator it=notes.begin(); it!=notes.end(); it++)
+ if ((*it)->get_note()==note)
+ (*it)->release();
}
void Channel::note_on(int note, int vel)
@@ -73,6 +92,8 @@ void Channel::note_on(int note, int vel)
list<Note*>::iterator it;
if (vel>0) //note on
{
+ pressed_keys.insert(note);
+
if ( (n_voices==1) && (!notes.empty()) )
{
//no need to create a new note; reuse the existing
@@ -129,9 +150,7 @@ void Channel::note_on(int note, int vel)
}
else //note off
{
- for (it=notes.begin(); it!=notes.end(); it++)
- if ((*it)->get_note()==note)
- (*it)->release();
+ note_off(note);
}
}
@@ -181,6 +200,8 @@ void Channel::set_controller(int con,int val)
case 7: set_volume(val); break;
case 8: set_balance(val); break;
case 65: set_portamento(val); break;
+ case 64: set_hold_pedal(val>=64); break;
+ case 66: set_sostenuto_pedal(val>=64); break;
case 119: set_quick_release(val);
case 120: panic(); break;
case 121: reset_controllers(); break;
@@ -305,6 +326,48 @@ void Channel::set_real_portamento_frames()
(*it)->set_portamento_frames(portamento_frames);
}
+void Channel::set_hold_pedal(bool newstate)
+{
+ if (hold_pedal_pressed!=newstate)
+ {
+ hold_pedal_pressed=newstate;
+
+ if (newstate==false)
+ {
+ //check for all held keys: is the key not pressed any more?
+ // is the key not in sostenuto_keys?
+ //if both conditions are fulfilled, release that note
+ for (set<int>::iterator it=held_keys.begin(); it!=held_keys.end(); it++)
+ if ( (pressed_keys.find(*it)==pressed_keys.end()) &&
+ (sostenuto_keys.find(*it)==sostenuto_keys.end()) )
+ note_off(*it);
+
+ held_keys.clear();
+ }
+ }
+}
+
+void Channel::set_sostenuto_pedal(bool newstate)
+{
+ // !sostenuto_keys.empty() equals pedal_pressed
+ if ( newstate != !sostenuto_keys.empty() )
+ {
+ if (newstate)
+ {
+ sostenuto_keys=pressed_keys;
+ }
+ else
+ {
+ if (hold_pedal_pressed==false)
+ for (set<int>::iterator it=sostenuto_keys.begin(); it!=sostenuto_keys.end(); it++)
+ if (pressed_keys.find(*it)==pressed_keys.end())
+ really_do_note_off(*it);
+
+ sostenuto_keys.clear();
+ }
+ }
+}
+
void Channel::panic()
{
list<Note*>::iterator it;
diff --git a/synth/channel.h b/synth/channel.h
index ead3a67..4ddcbb3 100644
--- a/synth/channel.h
+++ b/synth/channel.h
@@ -24,6 +24,7 @@ class Channel
void set_pitch_bend(float val);
void note_on(int note, int vel);
void note_off(int note);
+ void really_do_note_off(int note);
void cleanup();
void release_all();
void panic();
@@ -36,6 +37,10 @@ class Channel
void set_quick_release(int val);
void reset_controllers();
+ void set_hold_pedal(bool newstate);
+ void set_sostenuto_pedal(bool newstate);
+
+
float balL, balR;
private:
void recalc_param(const parameter_t &par, program_t &prg);
@@ -58,6 +63,13 @@ class Channel
int n_voices;
jack_nframes_t quick_release;
+
+ set<int> pressed_keys;
+
+ bool hold_pedal_pressed;
+ set<int> held_keys;
+
+ set<int> sostenuto_keys;
};
#endif