Merge Ω-W2-T5: bound the waveform zero-crossing snap to a pixel radius
Single-cycle loop marks stop teleporting to the one interior crossing. Ctrl on a marker drag defeats the snap, and no longer loses the grab to a coincident node.
This commit is contained in:
@@ -311,3 +311,11 @@ against a performance budget — they are there because `VoiceEngine::applyLiveT
|
||||
"channel identity derives from `app_version` accessors, no scattered `#ifdef`s" —
|
||||
`INLINE_UID` needs literal brace-init tokens, so it can't route through a runtime
|
||||
string accessor.
|
||||
- **Ctrl held during a waveform marker drag defeats the zero-crossing snap outright**
|
||||
(`editor_input_waveform.cpp`'s `dragWaveform`, reading `dragModifiers().ctrl` — the same
|
||||
"get out of the way, I want exactness" role Ctrl plays as the knobs' fine drag). It is
|
||||
undiscoverable by design — no cursor cue, no label — so this note is its only home; the
|
||||
radius itself (`core/instrument/ui/waveform_view`'s `snapToZeroCrossing`) is documented there,
|
||||
not here. `resolveWaveformClaim` (`core/instrument/ui/spline_edit`) is the reason Ctrl held
|
||||
BEFORE mouse-down still reaches the mark rather than stealing a coincident envelope-node grab
|
||||
or hard/smooth toggle.
|
||||
|
||||
@@ -282,13 +282,16 @@ void ReaSamplerEditor::dragWaveform(const FaceLayout& fl, int x, int y) {
|
||||
dragStartMarkers_.crossfade};
|
||||
std::int64_t newFrame = resolveDragFrame(overlay, frames, startVals[idx], dx);
|
||||
|
||||
// Snap to the nearest zero crossing in the decoded PCM. Pure over the cached mono
|
||||
// frames — no host types, no file I/O. The crossfade handle is exempt: it sets a fade
|
||||
// LENGTH, and the whole point of the fade is that its edges need no zero crossing.
|
||||
// Snap to a zero crossing in the decoded PCM, but only one within kZeroCrossingSnapPx of
|
||||
// where the mark was dropped. Pure over the cached mono frames — no host types, no file I/O.
|
||||
// The crossfade handle is exempt: it sets a fade LENGTH, and the whole point of the fade is
|
||||
// that its edges need no zero crossing. Ctrl defeats the snap outright, the same "get out of
|
||||
// the way, I want exactness" role it plays as the knobs' fine drag. `[verify — DAW]` this
|
||||
// `GetKeyState` read has no test target — nothing in CI observes the defeat actually landing.
|
||||
const std::vector<AudioSample>& pcm = monoPcmFor(selectedId_);
|
||||
if (!pcm.empty() && waveMarker_ != WaveMarker::kCrossfade) {
|
||||
newFrame = nearestZeroCrossing(pcm.data(), static_cast<std::int64_t>(pcm.size()),
|
||||
newFrame);
|
||||
if (!pcm.empty() && waveMarker_ != WaveMarker::kCrossfade && !dragModifiers().ctrl) {
|
||||
newFrame = snapToZeroCrossing(pcm.data(), frames, newFrame,
|
||||
zeroCrossingSnapFrames(overlay, frames));
|
||||
}
|
||||
|
||||
// Build the edited marker set from the snapshot, moving only the grabbed marker, then
|
||||
|
||||
Reference in New Issue
Block a user