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:50:49 +0100 |
commit | 43510e6fb436b7f4926c69e584861ec6f4936dc3 (patch) | |
tree | 724e2a0c1ef27a9070f2b0f6a5126af6d1766de7 /synth/channel.cpp | |
parent | ae8c1183ac4f9a3e3c54ac7fb57fe7d1631d1740 (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 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; |