Skip to content

feat: Loop de Cay additive overdub loop - #623

Closed
kosmar wants to merge 1 commit into
ATOVproject:mainfrom
kosmar:feat/loop-de-cay
Closed

kosmar wants to merge 1 commit into
ATOVproject:mainfrom
kosmar:feat/loop-de-cay

Conversation

@kosmar

@kosmar kosmar commented Aug 3, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • New 1ch app Loop de Cay: clocked additive overdub loop with per-wrap level decay (kill-floor to true 0)
  • Five I/O modes via Config: Pitch→MIDI, Gate→MIDI, MIDI→MIDI, MIDI→CV, Fader→Both
  • Gestures: Press = gate/play, Long = mute (no fader move), Shift+Short = arm, Shift+Long = erase
  • Alt = decay, Third = 1–8 bar window (crop/reveal + virgin tile); poly 4; RAM-only buffer
  • App ID 38 (avoids Hold Sam 36 / Harmonica 37 WIP IDs)

Test plan

  • Flash firmware and add Loop de Cay on a channel
  • Fader→Both: arm, play short notes with button+fader, confirm loop repeats on clock
  • Overdub adds notes; Alt decay fades velocity to silence; mute pauses decay
  • Shift+Long erases; Third shortens/extends bars (tile on virgin extend, reveal after crop)
  • Spot-check other modes (Pitch→MIDI, Gate→MIDI, MIDI→MIDI, MIDI→CV)

Prerequisites

The platform pieces this app needs are under review as their own PRs, so that
each app PR stays small enough to review on its own.

Required — these APIs do not exist on current main:

This branch is still based on an older main that still had the removed clock
helper, which is why it builds on its own but not after a rebase.

On top of the PRs above there is an app-side change: ClockEvent::Tick became
Tick(u64) in #579, so the match arm here has to be updated.

Building any of this on a current Rust nightly also needs the toolchain fix in
#632.

@kosmar

kosmar commented Aug 11, 2026

Copy link
Copy Markdown
Contributor Author

Update: Pitch→MIDI fader + Span

e9822be — In Pitch→MIDI, Mode 0 always opens a CV in jack and resolve_pitch preferred that path, so the fader (and Span) never drove pitch when unpatched. Open CV rests near 0 V and pinned notes to Base Note; Hold+Fader glissando was dead for the same reason.

CV pitch and the bipolar fader offset now stack: unpatched the fader keeps the documented span; with a cable it transposes; centre = 0 semitones (also the saved default).

Test on hardware

  • Loop de Cay · Pitch→MIDI · Base Note C3 · Span 120 · no cable on the jack
  • Hold button + move fader → full ±60 semitone range (scale-quantized), not stuck on C3
  • Patch V/Oct: centre = unchanged CV pitch; move fader to transpose

@kosmar

kosmar commented Aug 13, 2026

Copy link
Copy Markdown
Contributor Author

Pushed two fixes found while testing on the playground build:

  • fix(loop-de-cay): let a plain hold sustain again — the Hold+Fader glissando chased its target unconditionally, and since the target includes CV in, an unpatched jack jittering across a quantizer step retriggered the held note. A plain hold now sustains; the glide only engages once the fader has actually moved during the hold.
  • fix(loop-de-cay): end loop voices even when clock ticks are skipped — note starts and ends tested the loop position for exact equality. The clock gatekeeper publishes ticks immediately, so a subscriber that falls behind drops them rather than stalling the device clock, and a missed end position left the note sounding until its voice slot was stolen. Both now test whether the position was crossed since the last tick, wrap-around included.

Written and pushed by an AI coding agent on behalf of @kosmar. Verified to build; hardware test still pending.

@kosmar
kosmar marked this pull request as ready for review August 22, 2026 08:48
Wave-1 community subrepo scope: app, manuals, and mod registration only.

Clock uses drain/processor split (glob tick atomic + 1 ms processor) instead of clock_ticker in the main loop.

Co-authored-by: Cursor <cursoragent@cursor.com>
@kosmar

kosmar commented Aug 22, 2026

Copy link
Copy Markdown
Contributor Author

Written by an AI coding agent on @kosmar's behalf.

Force-pushed a Wave-1 scope cleanup onto this branch (single commit vs main):

Please re-run CI on this branch. Happy to adjust anything for review.

@ArthurGibert

Copy link
Copy Markdown
Member

Hey @kosmar — two things, one about where this belongs and one about the manual format you're using.

Where it belongs: this looks like a great fit for faderpunk-community-apps, which just went public. New on-device apps are meant to land there rather than here directly — see CONTRIBUTING.md's "Standalone companion tools" section, and the pointer it promised once that repo was live.

Ran loop_de_cay.rs against the actual submission gate (pr-scope-check.sh) — clean, no unsafe code, no panics, no MAX11300/storage bypass, no un-yielding loop — and did a real cargo build against current main with it dropped in, which passed too. It does have 15 .unwrap()/.expect() calls without a justification comment, which the gate soft-flags for human judgment rather than blocking (same treatment some existing official apps get) — worth a look before resubmitting, not a blocker.

About docs/apps/38-loop-de-cay/manual.{json,md}: this one's on us, not you — it was listed as a sanctioned option in CONTRIBUTING.md/the scope-check script without anyone actually verifying it was backed by real tooling, and it wasn't: nothing in the configurator reads it (confirmed against #606; its entry doesn't show up on the /#/manual page at all). You followed the policy as documented — the policy was wrong. Filed as #656, and #657 has already removed it as an option here. So faderpunk-community-apps isn't just a better fit organizationally — right now it's the only place this content would actually end up visible anywhere.

To resubmit there: just the app file itself (no mod.rs/registration changes — those are generated), a community app ID in the 100+ range, and a manual-tab.json entry built from your existing manual.{json,md}. Most of it maps over directly (manual.md is the entry's text field verbatim; name→title; description/color/icon/params/storage and most of channels are already the same shape) — but the schema also has fnPlusShiftTitle/ledTopPlusShift/ledBottomPlusShift-style fields for documenting combined Shift/Fn/Button behavior, which your format doesn't have dedicated slots for; where that's described inline in fnDescription/ledTop today, it'd need pulling out into those fields for parity with how official apps are documented. Happy to help with the conversion if useful. Whether/when to close this one is up to you or a maintainer — just flagging where it belongs.

@kosmar

kosmar commented Aug 23, 2026

Copy link
Copy Markdown
Contributor Author

Moving this to faderpunk-community-apps as requested: ATOVproject/faderpunk-community-apps#12

Closing here. App ID remapped 38 → 109 (community range).

@kosmar kosmar closed this Aug 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants