Skip to content

Commit

Permalink
display quantize/humanize mode for first encoder detent, then quantize (
Browse files Browse the repository at this point in the history
#2291)

- on first encoder detent the popup says either "humanize" or
  "quantize" depending on the encoder direction (plus "all" when
  necessary)

- For 7seg, when displaying the humanize/quantize all amount, prefix
  it with A as long as the result fits on the screen nicely.

- explicit UI_QUANTIZE_MODE, which silences auditions as soon as the
  tempo encoder is pressed while holding an audition pad

- the mode stays on as long as any audition pads remain pressed

- fix prevention of tempo-encoder popup on audition + tempo press,
  instead display "HUMANIZE/QUANTIZE ALL" as a hint. I believe this
  is a lefover from the original patch, which I believe used pad
  pressed instead of audition to quantize?
  • Loading branch information
nikodemus authored Jul 20, 2024
1 parent d2ed0b0 commit 4f36e03
Show file tree
Hide file tree
Showing 9 changed files with 125 additions and 52 deletions.
5 changes: 4 additions & 1 deletion src/deluge/gui/l10n/english.json
Original file line number Diff line number Diff line change
Expand Up @@ -299,8 +299,11 @@
"STRING_FOR_ARRANGEMENT_CLEARED": "Arrangement cleared",
"STRING_FOR_EMPTY_CLIP_INSTANCES_CANT_BE_MOVED_TO_THE_SESSION": "Empty clip instances can't be moved to the session",
"STRING_FOR_CANT_EDIT_LENGTH": "Can't edit length",
"STRING_FOR_QUANTIZE_ALL_ROW": "QUANTIZE ALL ROW",
"STRING_FOR_HUMANIZE_OR_QUANTIZE_ALL": "HUMANIZE/QUANTIZE ALL",
"STRING_FOR_QUANTIZE_ALL": "QUANTIZE ALL",
"STRING_FOR_QUANTIZE": "QUANTIZE",
"STRING_FOR_HUMANIZE_ALL": "HUMANIZE ALL",
"STRING_FOR_HUMANIZE": "HUMANIZE",
"STRING_FOR_VELOCITY_DECREASED": "Velocity decreased",
"STRING_FOR_VELOCITY_INCREASED": "Velocity increased",
"STRING_FOR_RANDOMIZED": "Randomized",
Expand Down
5 changes: 4 additions & 1 deletion src/deluge/gui/l10n/g_english.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -261,8 +261,11 @@ PLACE_SDRAM_DATA Language english{
{STRING_FOR_ARRANGEMENT_CLEARED, "Arrangement cleared"},
{STRING_FOR_EMPTY_CLIP_INSTANCES_CANT_BE_MOVED_TO_THE_SESSION, "Empty clip instances can't be moved to the session"},
{STRING_FOR_CANT_EDIT_LENGTH, "Can't edit length"},
{STRING_FOR_QUANTIZE_ALL_ROW, "QUANTIZE ALL ROW"},
{STRING_FOR_HUMANIZE_OR_QUANTIZE_ALL, "HUMANIZE/QUANTIZE ALL"},
{STRING_FOR_QUANTIZE_ALL, "QUANTIZE ALL"},
{STRING_FOR_QUANTIZE, "QUANTIZE"},
{STRING_FOR_HUMANIZE_ALL, "HUMANIZE ALL"},
{STRING_FOR_HUMANIZE, "HUMANIZE"},
{STRING_FOR_VELOCITY_DECREASED, "Velocity decreased"},
{STRING_FOR_VELOCITY_INCREASED, "Velocity increased"},
{STRING_FOR_RANDOMIZED, "Randomized"},
Expand Down
5 changes: 4 additions & 1 deletion src/deluge/gui/l10n/g_seven_segment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -178,8 +178,11 @@ PLACE_SDRAM_DATA Language seven_segment{
{STRING_FOR_ARRANGEMENT_CLEARED, "CLEAR"},
{STRING_FOR_EMPTY_CLIP_INSTANCES_CANT_BE_MOVED_TO_THE_SESSION, "EMPTY"},
{STRING_FOR_CANT_EDIT_LENGTH, "CANT"},
{STRING_FOR_QUANTIZE_ALL_ROW, "QTZA"},
{STRING_FOR_HUMANIZE_OR_QUANTIZE_ALL, "ALL"},
{STRING_FOR_QUANTIZE_ALL, "QTZA"},
{STRING_FOR_QUANTIZE, "QTZ"},
{STRING_FOR_HUMANIZE_ALL, "HUMA"},
{STRING_FOR_HUMANIZE, "HUM"},
{STRING_FOR_VELOCITY_DECREASED, "LESS"},
{STRING_FOR_VELOCITY_INCREASED, "MORE"},
{STRING_FOR_RANDOMIZED, "RND"},
Expand Down
5 changes: 4 additions & 1 deletion src/deluge/gui/l10n/seven_segment.json
Original file line number Diff line number Diff line change
Expand Up @@ -187,8 +187,11 @@
"STRING_FOR_ARRANGEMENT_CLEARED": "CLEAR",
"STRING_FOR_EMPTY_CLIP_INSTANCES_CANT_BE_MOVED_TO_THE_SESSION": "EMPTY",
"STRING_FOR_CANT_EDIT_LENGTH": "CANT",
"STRING_FOR_QUANTIZE_ALL_ROW": "QTZA",
"STRING_FOR_HUMANIZE_OR_QUANTIZE_ALL": "ALL",
"STRING_FOR_QUANTIZE_ALL": "QTZA",
"STRING_FOR_QUANTIZE": "QTZ",
"STRING_FOR_HUMANIZE_ALL": "HUMA",
"STRING_FOR_HUMANIZE": "HUM",
"STRING_FOR_VELOCITY_DECREASED": "LESS",
"STRING_FOR_VELOCITY_INCREASED": "MORE",
"STRING_FOR_RANDOMIZED": "RND",
Expand Down
5 changes: 4 additions & 1 deletion src/deluge/gui/l10n/strings.h
Original file line number Diff line number Diff line change
Expand Up @@ -278,8 +278,11 @@ enum class String : size_t {
STRING_FOR_ARRANGEMENT_CLEARED,
STRING_FOR_EMPTY_CLIP_INSTANCES_CANT_BE_MOVED_TO_THE_SESSION,
STRING_FOR_CANT_EDIT_LENGTH,
STRING_FOR_QUANTIZE_ALL_ROW,
STRING_FOR_HUMANIZE_OR_QUANTIZE_ALL,
STRING_FOR_QUANTIZE_ALL,
STRING_FOR_QUANTIZE,
STRING_FOR_HUMANIZE_ALL,
STRING_FOR_HUMANIZE,
STRING_FOR_VELOCITY_DECREASED,
STRING_FOR_VELOCITY_INCREASED,
STRING_FOR_RANDOMIZED,
Expand Down
1 change: 1 addition & 0 deletions src/deluge/gui/ui/ui.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ extern bool pendingUIRenderingLock;

// Non-exclusive UI modes, which can (if the code allows) occur at the same time as other ones, including the
// "exclusive" ones above.
#define UI_MODE_QUANTIZE (1 << 27)
#define UI_MODE_STUTTERING (1 << 28)
#define UI_MODE_HORIZONTAL_SCROLL (1 << 29)
#define UI_MODE_AUDITIONING (1 << 30)
Expand Down
138 changes: 95 additions & 43 deletions src/deluge/gui/views/instrument_clip_view.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -665,9 +665,11 @@ ActionResult InstrumentClipView::buttonAction(deluge::hid::Button b, bool on, bo
copyNotes();
}
}
else if (b == TEMPO_ENC && isUIModeActiveExclusively(UI_MODE_NOTES_PRESSED)
else if (b == TEMPO_ENC && isUIModeActive(UI_MODE_AUDITIONING)
&& runtimeFeatureSettings.get(RuntimeFeatureSettingType::Quantize) == RuntimeFeatureStateToggle::On) {
// prevent Tempo pop-up , when note is pressed
// Prevent Tempo pop-up when auditioning: audition + tempo press is how quantize/humanize all starts.
// Intentionally not using PopupType::QUANITZE, so we display the info for the direction on first detent.
display->popupTextTemporary(deluge::l10n::get(deluge::l10n::String::STRING_FOR_HUMANIZE_OR_QUANTIZE_ALL));
}
// Horizontal encoder button
else if (b == X_ENC) {
Expand Down Expand Up @@ -1613,13 +1615,20 @@ ActionResult InstrumentClipView::padAction(int32_t x, int32_t y, int32_t velocit
}
}

// We're quantizing: either adding a new note to the set being quantized, or removing.
// In the first case we simply defer to auditionPadAction.
else if (isUIModeActive(UI_MODE_QUANTIZE)) {
if (velocity) {
return auditionPadAction(velocity, y, true);
}
else {
return commandStopQuantize(y);
}
}

// Actual basic audition pad press:
else if (!velocity || isUIModeWithinRange(auditionPadActionUIModes)) {
exitUIMode(UI_MODE_DRAGGING_KIT_NOTEROW);
if (sdRoutineLock && !allowSomeUserActionsEvenWhenInCardRoutine) {
return ActionResult::REMIND_ME_OUTSIDE_CARD_ROUTINE; // Allowable sometimes if in card routine.
}
auditionPadAction(velocity, y, Buttons::isShiftButtonPressed());
return auditionPadAction(velocity, y, Buttons::isShiftButtonPressed());
}
}
}
Expand Down Expand Up @@ -3462,9 +3471,13 @@ void InstrumentClipView::setSelectedDrum(Drum* drum, bool shouldRedrawStuff, Kit
}
}

void InstrumentClipView::auditionPadAction(int32_t velocity, int32_t yDisplay, bool shiftButtonDown) {
ActionResult InstrumentClipView::auditionPadAction(int32_t velocity, int32_t yDisplay, bool shiftButtonDown) {
exitUIMode(UI_MODE_DRAGGING_KIT_NOTEROW);
if (sdRoutineLock && !allowSomeUserActionsEvenWhenInCardRoutine) {
return ActionResult::REMIND_ME_OUTSIDE_CARD_ROUTINE; // Allowable sometimes if in card routine.
}

if (editedAnyPerNoteRowStuffSinceAuditioningBegan && !velocity) {
// in case we were editing quantize/humanize
actionLogger.closeAction(ActionType::NOTE_NUDGE);
}

Expand All @@ -3488,7 +3501,8 @@ void InstrumentClipView::auditionPadAction(int32_t velocity, int32_t yDisplay, b
drum = getAuditionedDrum(velocity, yDisplay, shiftButtonDown, instrument, modelStackWithTimelineCounter,
modelStackWithNoteRowOnCurrentClip);
if (drum == nullptr) {
return; // don't continue auditioning if drum is null
return ActionResult::DEALT_WITH;
; // don't continue auditioning if drum is null
}
}

Expand Down Expand Up @@ -3545,6 +3559,8 @@ void InstrumentClipView::auditionPadAction(int32_t velocity, int32_t yDisplay, b
if (!clipIsActiveOnInstrument && velocity) {
indicator_leds::indicateAlertOnLed(IndicatorLED::SESSION_VIEW);
}

return ActionResult::DEALT_WITH;
}

// sub-function of AuditionPadAction
Expand Down Expand Up @@ -4766,37 +4782,69 @@ void InstrumentClipView::rotateNoteRowHorizontally(int32_t offset) {
}

void InstrumentClipView::tempoEncoderAction(int8_t offset, bool encoderButtonPressed, bool shiftButtonPressed) {

if (isUIModeActive(UI_MODE_AUDITIONING)
&& runtimeFeatureSettings.get(RuntimeFeatureSettingType::Quantize)
== RuntimeFeatureStateToggle::On) { // quantize
if (encoderButtonPressed) {
quantizeNotes(offset, NUDGEMODE_QUANTIZE_ALL);
}
else {
quantizeNotes(offset, NUDGEMODE_QUANTIZE);
}
auto quantizeType = encoderButtonPressed ? NudgeMode::QUANTIZE_ALL : NudgeMode::QUANTIZE;
if (isUIModeActive(UI_MODE_QUANTIZE)) {
commandQuantizeNotes(offset, quantizeType);
}
else if (isUIModeActive(UI_MODE_AUDITIONING)
&& runtimeFeatureSettings.get(RuntimeFeatureSettingType::Quantize)
== RuntimeFeatureStateToggle::On) { // quantize
commandStartQuantize(offset, quantizeType);
}
else {
playbackHandler.tempoEncoderAction(offset, encoderButtonPressed, shiftButtonPressed);
}
}

void InstrumentClipView::quantizeNotes(int32_t offset, int32_t nudgeMode) {
void appendQuantizeMode(StringBuf& text, int8_t direction, NudgeMode mode) {
switch (mode) {
case NudgeMode::QUANTIZE:
if (direction >= 0) {
text.append(deluge::l10n::get(deluge::l10n::String::STRING_FOR_QUANTIZE));
}
else {
text.append(deluge::l10n::get(deluge::l10n::String::STRING_FOR_HUMANIZE));
}
break;
case NudgeMode::QUANTIZE_ALL:
if (direction >= 0) {
text.append(deluge::l10n::get(deluge::l10n::String::STRING_FOR_QUANTIZE_ALL));
}
else {
text.append(deluge::l10n::get(deluge::l10n::String::STRING_FOR_HUMANIZE_ALL));
}
break;
}
}

shouldIgnoreHorizontalScrollKnobActionIfNotAlsoPressedForThisNotePress = true;
void InstrumentClipView::commandStartQuantize(int8_t offset, NudgeMode mode) {
auditioningSilently = true;
reassessAllAuditionStatus();
enterUIMode(UI_MODE_QUANTIZE);
quantizeAmount = 0;
DEF_STACK_STRING_BUF(text, 30);
appendQuantizeMode(text, offset, mode);
display->popupText(text.c_str(), PopupType::QUANTIZE);
}

// just popping up
if (!offset) {
quantizeAmount = 0;
if (nudgeMode == NUDGEMODE_QUANTIZE) {
display->displayPopup(deluge::l10n::get(deluge::l10n::String::STRING_FOR_QUANTIZE));
}
else if (nudgeMode == NUDGEMODE_QUANTIZE_ALL) {
display->displayPopup(deluge::l10n::get(deluge::l10n::String::STRING_FOR_QUANTIZE_ALL_ROW));
ActionResult InstrumentClipView::commandStopQuantize(int32_t y) {
auto res = auditionPadAction(0, y, true);
if (res != ActionResult::DEALT_WITH) {
return res;
}
if (!getNumNoteRowsAuditioning()) {
// No pads pressed, can actually stop quantizing
if (display->hasPopupOfType(PopupType::QUANTIZE)) {
display->cancelPopup();
}
return;
exitUIMode(UI_MODE_QUANTIZE);
}
return ActionResult::DEALT_WITH;
;
}

void InstrumentClipView::commandQuantizeNotes(int8_t offset, NudgeMode nudgeMode) {
shouldIgnoreHorizontalScrollKnobActionIfNotAlsoPressedForThisNotePress = true;

int32_t squareSize = getPosFromSquare(1) - getPosFromSquare(0);

Expand All @@ -4815,17 +4863,21 @@ void InstrumentClipView::quantizeNotes(int32_t offset, int32_t nudgeMode) {
}

if (display->haveOLED()) {
char buffer[24];
snprintf(buffer, sizeof(buffer), "%s %s%d%%", //<
(quantizeAmount >= 0) ? "Quantize" : "Humanize", //<
(nudgeMode == NUDGEMODE_QUANTIZE) ? "" : "All ", //<
abs(quantizeAmount * 10));
display->popupTextTemporary(buffer);
DEF_STACK_STRING_BUF(text, 24);
appendQuantizeMode(text, quantizeAmount, nudgeMode);
text.append(" ");
text.appendInt(abs(quantizeAmount * 10));
text.append("%");
display->popupText(text.c_str(), PopupType::QUANTIZE);
}
else {
char buffer[5];
snprintf(buffer, sizeof(buffer), "%d", quantizeAmount * 10); // Negative means humanize
display->displayPopup(buffer, 0, true);
DEF_STACK_STRING_BUF(text, 6);
// Put A in front for QUANTIZE ALL if there's space for it.
if (nudgeMode == NudgeMode::QUANTIZE_ALL && quantizeAmount > -10) {
text.append("A");
}
text.appendInt(quantizeAmount * 10); // Negative means humanize
display->popupText(text.c_str(), PopupType::QUANTIZE);
}

char modelStackMemory[MODEL_STACK_MAX_SIZE];
Expand All @@ -4851,11 +4903,11 @@ void InstrumentClipView::quantizeNotes(int32_t offset, int32_t nudgeMode) {
uint32_t nRows{0};

switch (nudgeMode) {
case NUDGEMODE_QUANTIZE:
case NudgeMode::QUANTIZE:
nRows = kDisplayHeight;
quantizeAll = false;
break;
case NUDGEMODE_QUANTIZE_ALL:
case NudgeMode::QUANTIZE_ALL:
nRows = currentClip->noteRows.getNumElements();
quantizeAll = true;
break;
Expand All @@ -4865,7 +4917,7 @@ void InstrumentClipView::quantizeNotes(int32_t offset, int32_t nudgeMode) {

uint32_t rowUpdateMask = 0;

for (auto i = 0; i < nRows; ++i) {
for (int32_t i = 0; i < nRows; ++i) {
ModelStackWithNoteRow* modelStackWithNoteRow;
NoteRow* thisNoteRow{nullptr};
if (quantizeAll) {
Expand Down
11 changes: 7 additions & 4 deletions src/deluge/gui/views/instrument_clip_view.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,7 @@ struct EditPadPress {
#define MPE_RECORD_LENGTH_FOR_NOTE_EDITING 3
#define MPE_RECORD_INTERVAL_TIME (kSampleRate >> 2) // 250ms

#define NUDGEMODE_QUANTIZE 1
#define NUDGEMODE_QUANTIZE_ALL 2
enum class NudgeMode { QUANTIZE, QUANTIZE_ALL };

class InstrumentClipView final : public ClipView, public InstrumentClipMinder {
public:
Expand Down Expand Up @@ -92,7 +91,7 @@ class InstrumentClipView final : public ClipView, public InstrumentClipMinder {
void offsetNoteCodeAction(int32_t newOffset);
int32_t getYVisualFromYDisplay(int32_t yDisplay);
int32_t getYVisualWithinOctaveFromYDisplay(int32_t yDisplay);
void auditionPadAction(int32_t velocity, int32_t yDisplay, bool shiftButtonDown);
ActionResult auditionPadAction(int32_t velocity, int32_t yDisplay, bool shiftButtonDown);
void potentiallyRefreshNoteRowMenu();
void enterScaleMode(uint8_t yDisplay = 255);
void exitScaleMode();
Expand Down Expand Up @@ -247,7 +246,11 @@ class InstrumentClipView final : public ClipView, public InstrumentClipMinder {
void rotateNoteRowHorizontally(ModelStackWithNoteRow* modelStack, int32_t offset, int32_t yDisplay,
bool shouldDisplayDirectionEvenIfNoNoteRow = false);

void quantizeNotes(int32_t offset, int32_t nudgeMode);
// TEMPO encoder commands
void commandQuantizeNotes(int8_t offset, NudgeMode nudgeMode);
void commandStartQuantize(int8_t offset, NudgeMode nudgeMode);
ActionResult commandStopQuantize(int32_t y);
void silenceAllAuditions();

// auditionPadAction functions
Drum* getAuditionedDrum(int32_t velocity, int32_t yDisplay, bool shiftButtonDown, Instrument* instrument,
Expand Down
2 changes: 2 additions & 0 deletions src/deluge/hid/display/display.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ enum class PopupType {
SWING,
/// Tempo
TEMPO,
/// Quantize and humanize
QUANTIZE,
// Note: Add here more popup types
};

Expand Down

0 comments on commit 4f36e03

Please sign in to comment.