Files
reasampler/src/core/instrument/ui/loop_marks.cpp
T
daniel 1b4d0e67b7 Loop-crossfade-ux review fixes: parked-drag no longer fakes LOOP OFF, waveform label contrast fixed, hover memoizes its bank read
Also corrects the cap-area, em-dash, glyph-overhang and heuristic-comment findings noted in review.
2026-08-02 13:52:32 -04:00

64 lines
2.2 KiB
C++

// loop_marks.cpp — see loop_marks.h. Pure value folds; no host types.
#include "core/instrument/ui/loop_marks.h"
#include "core/instrument/engine/loop/loop_span.h" // defaultLoopBounds
namespace reasampler::instrument::ui {
namespace {
// The engine's own acceptance test, restated over the editor's two integers: resolveLoop
// refuses an inverted, empty or out-of-range span rather than repairing it, so a span it would
// refuse is one the handles must be re-parked out of.
bool spanUsable(std::int64_t loopStart, std::int64_t loopEnd, std::int64_t frameCount) {
return loopStart >= 0 && loopEnd > loopStart && loopEnd <= frameCount;
}
} // namespace
LoopMarks resolveLoopMarks(const StoredLoop& stored, std::int64_t frameCount) {
LoopMarks m;
if (stored.override_) {
m.hasLoop = stored.override_->hasLoop;
m.loopStart = stored.override_->start;
m.loopEnd = stored.override_->end;
} else if (stored.intrinsic && stored.intrinsic->hasLoop) {
m.hasLoop = true;
m.loopStart = stored.intrinsic->start;
m.loopEnd = stored.intrinsic->end;
}
if (stored.startPoint) m.start = *stored.startPoint;
m.crossfade = stored.crossfade > 0 ? stored.crossfade : 0;
if (!spanUsable(m.loopStart, m.loopEnd, frameCount)) {
m.hasLoop = false;
m.parked = true;
const engine::loop::LoopBounds d = engine::loop::defaultLoopBounds(frameCount);
m.loopStart = d.start;
m.loopEnd = d.end;
}
return m;
}
LoopWrite applyLoopMarks(const LoopMarks& m) {
LoopWrite w;
const bool spanAlive = m.loopEnd > m.loopStart;
w.loop.hasLoop = m.hasLoop && spanAlive;
if (m.parked && !m.hasLoop) {
// A parked pair (never set) must round-trip back to parked, not to a real "LOOP OFF"
// span — resolveLoopMarks only re-parks a span spanUsable would refuse, so collapse it
// deliberately rather than writing back the default bounds' own alive span.
w.loop.start = m.loopStart;
w.loop.end = m.loopStart;
} else {
w.loop.start = m.loopStart;
w.loop.end = m.loopEnd;
}
w.crossfade = (spanAlive && m.crossfade > 0) ? m.crossfade : 0;
w.start = m.start;
return w;
}
} // namespace reasampler::instrument::ui