-1 velocity means unset. */
| 594 | |
| 595 | /** -1 velocity means unset. */ |
| 596 | void releaseNote(uint8_t note, int8_t channel, int8_t velocity) { |
| 597 | // Remove the note |
| 598 | heldNotes.erase(std::remove(heldNotes.begin(), heldNotes.end(), note), heldNotes.end()); |
| 599 | // Hold note if pedal is pressed |
| 600 | if (pedal) |
| 601 | return; |
| 602 | // Find output channel of released note, if any |
| 603 | if (channels > 1 && polyMode == MPE_MODE) { |
| 604 | // Each MPE channel must be monophonic so the output channel must be the released note channel |
| 605 | } |
| 606 | else { |
| 607 | // Find channel of active note |
| 608 | channel = -1; |
| 609 | for (uint8_t c = 0; c < channels; c++) { |
| 610 | if (gates[c] && notes[c] == note) { |
| 611 | channel = c; |
| 612 | break; |
| 613 | } |
| 614 | } |
| 615 | } |
| 616 | if (channel < 0) { |
| 617 | // Released note is not active on any channel |
| 618 | return; |
| 619 | } |
| 620 | // Deactivate note |
| 621 | gates[channel] = false; |
| 622 | refreshHeld(); |
| 623 | // Set velocity |
| 624 | if (releaseVelocityEnabled && velocity >= 0) { |
| 625 | velocities[channel] = velocity; |
| 626 | } |
| 627 | } |
| 628 | |
| 629 | /** Deactivates all notes that are not held, and reactivates notes that are. */ |
| 630 | void refreshHeld() { |