Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: Waveform loop lock #293

Merged
merged 14 commits into from
Aug 14, 2023
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions Documentation/community_features.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ Synchronization modes accessible through the "LFO SYNC" shortcut.
### Audio Clip View
- ([#141]) Holding the vertical encoder down while turning the horizontal encoder will shift the clip along the underlying audio file, similar to the same interface for instrument clips.

### Sample Waveform View
- ([#293]) When a sample has loop start and loop end points set, holding down loop start and tapping loop end will lock the loop points together. Moving one will move the other, keeping them the same distance apart. Use the same process to unlock the loop points. Use SHIFT+TURN<> to double or half the loop length.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it should be shift+turn to edit loop length, shift+press to double. It feels weird having this little control over length if the loop is longer than a few samples

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See my response above about doubling/halving.


### Takeover Mode

- ([#170]) The Takeover menu consists of three modes that can be selected from:
Expand Down Expand Up @@ -134,3 +137,4 @@ This list includes all preprocessor switches that can alter firmware behaviour a
[#221]: https://github.com/SynthstromAudible/DelugeFirmware/pull/221
[#234]: https://github.com/SynthstromAudible/DelugeFirmware/pull/234
[#282]: https://github.com/SynthstromAudible/DelugeFirmware/pull/282
[#293]: https://github.com/SynthstromAudible/DelugeFirmware/pull/293
73 changes: 71 additions & 2 deletions src/deluge/gui/ui/sample_marker_editor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ extern "C" {

const uint8_t zeroes[] = {0, 0, 0, 0, 0, 0, 0, 0};

int loopLength = 0;
bool loopLocked = false;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these would probably benefit from being members of SampleMarkerEditor rather than globals


SampleMarkerEditor sampleMarkerEditor{};

SampleMarkerEditor::SampleMarkerEditor() {
Expand Down Expand Up @@ -142,10 +145,28 @@ void SampleMarkerEditor::writeValue(uint32_t value, MarkerType markerTypeNow) {
getCurrentSampleHolder()->startPos = value;
}
else if (markerTypeNow == MarkerType::LOOP_START) {
getCurrentMultisampleRange()->sampleHolder.loopStartPos = value;
if (loopLocked) {
int intendedLoopEndPos = value + loopLength;
if (intendedLoopEndPos <= getCurrentSampleHolder()->endPos) {
getCurrentMultisampleRange()->sampleHolder.loopStartPos = value;
getCurrentMultisampleRange()->sampleHolder.loopEndPos = intendedLoopEndPos;
}
}
else {
getCurrentMultisampleRange()->sampleHolder.loopStartPos = value;
}
}
else if (markerTypeNow == MarkerType::LOOP_END) {
getCurrentMultisampleRange()->sampleHolder.loopEndPos = value;
if (loopLocked) {
int intendedLoopStartPos = value - loopLength;
if (intendedLoopStartPos >= getCurrentSampleHolder()->startPos) {
getCurrentMultisampleRange()->sampleHolder.loopEndPos = value;
getCurrentMultisampleRange()->sampleHolder.loopStartPos = intendedLoopStartPos;
}
}
else {
getCurrentMultisampleRange()->sampleHolder.loopEndPos = value;
}
}
else if (markerTypeNow == MarkerType::END) {
getCurrentSampleHolder()->endPos = value;
Expand Down Expand Up @@ -426,6 +447,21 @@ ActionResult SampleMarkerEditor::padAction(int32_t x, int32_t y, int32_t on) {

goto ensureNotPastSampleLength;
}
else if (markerHeld == MarkerType::LOOP_START && markerPressed == MarkerType::LOOP_END) {
if (loopLocked == false) {
loopLocked = true;
int loopStart = getCurrentMultisampleRange()->sampleHolder.loopStartPos;
int loopEnd = getCurrentMultisampleRange()->sampleHolder.loopEndPos;
loopLength = loopEnd - loopStart;
numericDriver.displayPopup("LOCK");
}
else {
loopLocked = false;
loopLength = 0;
numericDriver.displayPopup("FREE");
}
return ActionResult::DEALT_WITH;
}

// Or if a loop point and they pressed the end marker, remove the loop point
else if (markerHeld == MarkerType::LOOP_START) {
Expand Down Expand Up @@ -623,6 +659,39 @@ static const uint32_t zoomUIModes[] = {UI_MODE_HOLDING_HORIZONTAL_ENCODER_BUTTON

ActionResult SampleMarkerEditor::horizontalEncoderAction(int32_t offset) {

if (loopLocked && Buttons::isShiftButtonPressed()) {
if (offset > 0) { // turn clockwise
int end = getCurrentSampleHolder()->endPos;
int loopEnd = getCurrentMultisampleRange()->sampleHolder.loopEndPos;

if (loopEnd + loopLength < end) {
loopLength = loopLength * 2;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this right? This reads like it's doubling/halfing the loop length when you turn the knob instead of incrementing it which is not how I read the conversation

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it's right. I did think we might be at different viewpoints here. The intention is that you'll set a loop length related to the tempo of the sample or track then doubling or halving the loop length will keep it rhythmically intact. Being able to arbitrarily adjust the loop length with SHIFT+TURN<> is fine but I'd still want a want to exactly double or half it. It's a magic way to find cool and unusual looping sections within samples.

Maybe SHIFT+PUSH+TURN<> for doubling/halving? Then use SHIFT+TURN<> for continuous change.

numericDriver.displayPopup(HAVE_OLED ? "Loop doubled" : "DOUB");
}
else {
numericDriver.displayPopup(HAVE_OLED ? "Loop too long" : "CANT");
return ActionResult::DEALT_WITH;
}
}
else { // turn anti-clockwise
if (loopLength > 2) {
loopLength = loopLength / 2;
numericDriver.displayPopup(HAVE_OLED ? "Loop halved" : "HALF");
}
else {
numericDriver.displayPopup(HAVE_OLED ? "Loop too short" : "CANT");
return ActionResult::DEALT_WITH;
}
}

int loopStart = getCurrentMultisampleRange()->sampleHolder.loopStartPos;
int newLoopEnd = loopStart + loopLength;
writeValue(newLoopEnd, MarkerType::LOOP_END);
uiNeedsRendering(this, 0xFFFFFFFF, 0);

return ActionResult::DEALT_WITH;
}

// We're quite likely going to need to read the SD card to do either scrolling or zooming
if (sdRoutineLock) {
return ActionResult::REMIND_ME_OUTSIDE_CARD_ROUTINE;
Expand Down