| 546 | |
| 547 | |
| 548 | void Arpeggiator::playNote() |
| 549 | { |
| 550 | calcTimeInterval(); |
| 551 | start(); |
| 552 | |
| 553 | additionalChordStartKeys.clearQuick(); |
| 554 | MidiSequenceArray.clearQuick(); |
| 555 | MidiSequenceArraySorted.clearQuick(); |
| 556 | |
| 557 | const int octaveRaw = (int)octaveSlider->getValue(); |
| 558 | const int octaveSign = octaveRaw >= 0 ? 1 : -1; |
| 559 | auto octaveAmount = abs(octaveRaw) + 1; |
| 560 | |
| 561 | for (int i = 0; i < octaveAmount; i++) |
| 562 | { |
| 563 | for (int j = 0; j < userHeldKeysArray.size(); j++) |
| 564 | { |
| 565 | MidiSequenceArray.addIfNotAlreadyThere(userHeldKeysArray[j] + (int8)(octaveSign * i * 12)); |
| 566 | MidiSequenceArraySorted.addIfNotAlreadyThere(userHeldKeysArraySorted[j] + (int8)(octaveSign * i * 12)); |
| 567 | } |
| 568 | } |
| 569 | |
| 570 | if (randomOrder) |
| 571 | { |
| 572 | int newIndex = MidiSequenceArraySorted.size() == 0 ? 0 : r.nextInt(MidiSequenceArraySorted.size()); |
| 573 | |
| 574 | while (curHeldNoteIdx == newIndex && MidiSequenceArraySorted.size() > 2) |
| 575 | newIndex = r.nextInt(MidiSequenceArraySorted.size()); |
| 576 | |
| 577 | curHeldNoteIdx = newIndex; |
| 578 | } |
| 579 | else |
| 580 | { |
| 581 | // this ensure that if a new note is added to the sorted list, we update where we are supposed to be along the sequence |
| 582 | // not a good implementation of the idea, but it works for now |
| 583 | if (sortKeysButton->getValue() && curHeldNoteIdx > 1) |
| 584 | curHeldNoteIdx = MidiSequenceArraySorted.indexOf(currentNote) + arpDirMod; |
| 585 | |
| 586 | // we must increment and wrap separately otherwise we will go from 0 to 1 and back to 0 instantly unless more than one note is held at exactly the same time |
| 587 | curHeldNoteIdx = WrapValueFromZeroToMax(curHeldNoteIdx, MidiSequenceArray.size()); |
| 588 | |
| 589 | curSeqPatternEnum = sequenceComboBox->getValue(); |
| 590 | |
| 591 | // check if we need to reverse sequence based on up/dn mode |
| 592 | if ((int)sequenceComboBox->getValue() >= 3 && MidiSequenceArray.size() > 1) |
| 593 | { |
| 594 | if (arpDirMod > 0 && curHeldNoteIdx == MidiSequenceArray.size() - 1) |
| 595 | arpDirMod = -abs(arpDirMod); |
| 596 | else if (arpDirMod < 0 && curHeldNoteIdx == 0) |
| 597 | arpDirMod = abs(arpDirMod); |
| 598 | } |
| 599 | } |
| 600 | |
| 601 | const int stepResetAmount = (int)stepReset->getValue(); |
| 602 | |
| 603 | // if master reset num steps is 0 ignore this block, otherwise do a full arp reset when num steps have passed |
| 604 | if (stepResetAmount > 0) |
| 605 | { |
nothing calls this directly
no test coverage detected