diff options
author | Florian Jung <flo@thinkpad.(none)> | 2011-01-08 14:43:26 +0100 |
---|---|---|
committer | Florian Jung <flo@thinkpad.(none)> | 2011-01-08 14:43:26 +0100 |
commit | b3404c9b79176f81cf6703921c3d22a74cd4a8bf (patch) | |
tree | f15d60eb72a3c5d8f913775fa0c2cb8d3f9be48d /synth/channel.cpp | |
parent | f76e20a3486b31945fd35f6b1a0bd517d6dc176e (diff) |
Added support for hold- and sostenuto pedals
Diffstat (limited to 'synth/channel.cpp')
-rw-r--r-- | synth/channel.cpp | 71 |
1 files changed, 67 insertions, 4 deletions
diff --git a/synth/channel.cpp b/synth/channel.cpp index d70b199..e92afef 100644 --- a/synth/channel.cpp +++ b/synth/channel.cpp @@ -23,6 +23,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() @@ -70,7 +75,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<NoteSkel*>::iterator it=notes.begin(); it!=notes.end(); it++) + if ((*it)->get_note()==note) + (*it)->release(); } void Channel::note_on(int note, int vel) @@ -78,6 +97,8 @@ void Channel::note_on(int note, int vel) list<NoteSkel*>::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 @@ -152,9 +173,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); } } @@ -204,6 +223,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; @@ -328,6 +349,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<NoteSkel*>::iterator it; |