loop: crossfade the Gate sustain seam, and unshadow the loop handles that made loop points look gone
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
#include "core/ui/bank_grid.h" // ThumbnailKey / thumbnailKeyString (the pure key)
|
||||
#include "core/util/file_bytes.h" // shared whole-file loader
|
||||
#include "ext_keys.h"
|
||||
#include "core/instrument/engine/loop/loop_span.h" // defaultLoopBounds (the shared ghost span)
|
||||
#include "core/instrument/ui/browser_scroll.h" // nameMatchesQuery (type-to-filter)
|
||||
#include "shell/instrument/reaper_bridge.h"
|
||||
#include "shell/instrument/reasampler_processor.h"
|
||||
@@ -31,6 +32,8 @@ using capture::WavLayout;
|
||||
using capture::extractFloatFrames;
|
||||
using capture::parseWavLayout;
|
||||
using capture::resolveBankFile;
|
||||
using instrument::engine::loop::LoopBounds;
|
||||
using instrument::engine::loop::defaultLoopBounds;
|
||||
using instrument::ui::nameMatchesQuery;
|
||||
using ui::ThumbnailKey;
|
||||
using ui::thumbnailKeyString;
|
||||
@@ -160,10 +163,12 @@ void ReaSamplerEditor::loadSelection(const std::string& id) {
|
||||
// loaded, so a load swaps the sound and keeps the settings. The three CAPTURE-ANCHORED
|
||||
// overrides are: a root, a loop span and a start frame all name positions in the
|
||||
// OUTGOING capture and mean nothing in the new one, so they clear and the new capture
|
||||
// plays from its own bank intrinsics.
|
||||
// plays from its own bank intrinsics. The loop crossfade goes with the span it belongs
|
||||
// to — it is a length in the outgoing capture's frames.
|
||||
selectedId_ = id;
|
||||
params_.rootOverride.reset();
|
||||
params_.loopOverride.reset();
|
||||
params_.loopCrossfadeFrames = 0;
|
||||
params_.startPoint.reset();
|
||||
commitAndReload();
|
||||
}
|
||||
@@ -196,10 +201,17 @@ ReaSamplerEditor::SetupMarkers ReaSamplerEditor::pickedMarkers(std::int64_t fram
|
||||
m.loopEnd = params_.loopOverride->end;
|
||||
}
|
||||
if (params_.startPoint) m.start = *params_.startPoint;
|
||||
// Default an unset loop's end to the sample length so the loop markers have somewhere sane
|
||||
// to sit before the user drags (loopStart stays 0). The "no loop" state is m.hasLoop==false;
|
||||
// the markers are still drawn (drag one to CREATE a loop).
|
||||
if (!m.hasLoop && m.loopEnd == 0) m.loopEnd = frames > 0 ? frames : 0;
|
||||
m.crossfade = params_.loopCrossfadeFrames;
|
||||
// A collapsed or inverted span is the OFF state (the engine refuses it either way), so
|
||||
// park the handles on the shared default rather than leaving them stacked on each other
|
||||
// where neither could be grabbed apart again. The markers are still drawn at 'no loop'
|
||||
// weight — drag one to CREATE a loop.
|
||||
if (!m.hasLoop || m.loopEnd <= m.loopStart) {
|
||||
m.hasLoop = false;
|
||||
const LoopBounds d = defaultLoopBounds(frames);
|
||||
m.loopStart = d.start;
|
||||
m.loopEnd = d.end;
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
@@ -207,10 +219,13 @@ void ReaSamplerEditor::applyMarkers(const SetupMarkers& m) {
|
||||
// Write the edited markers into the parameter set as the loop/start override. The bank
|
||||
// intrinsic is never written (read-only bank consumer).
|
||||
SampleLoop loop;
|
||||
loop.hasLoop = m.hasLoop;
|
||||
// Collapsing the span onto itself is the OFF gesture — record it as such so the next
|
||||
// pickedMarkers re-offers the default handles instead of two coincident ones.
|
||||
loop.hasLoop = m.hasLoop && m.loopEnd > m.loopStart;
|
||||
loop.start = m.loopStart;
|
||||
loop.end = m.loopEnd;
|
||||
params_.loopOverride = loop;
|
||||
params_.loopCrossfadeFrames = m.crossfade;
|
||||
params_.startPoint = m.start;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user