Lightningbeam/lightningbeam-ui/lightningbeam-editor/src
Skyler Lehmkuhl 16e3d676d6 Cycle recording: multi-take capture, take folders, comping
Recording into a cycle region now produces one take per pass. Pick a take
from a badge on the clip; split the clip and pick different takes on the
halves, and you've comped.

Data model (phase 2):
- AudioClipType::TakeFolder { takes, recorded_loop_beats } holds the take
  list on the CLIP; ClipInstance::active_take holds the selection on the
  INSTANCE. That split is what makes comping fall out of the existing
  split action for free — split clones the instance, so the two halves
  share one take list but choose independently. recorded_loop_beats lets
  a future time-stretch/conform pass reconcile audio takes if the tempo
  moves under them.
- AudioClip::resolve(active_take) -> ResolvedContent{Audio|Midi|Recording}
  collapses a take folder to what an instance actually plays. A folder is
  not a distinct *case* at call sites — it's an audio or MIDI clip whose
  identity depends on which take is live — so every backend-sync site now
  resolves through this instead of matching clip_type raw. Reverse lookups
  go through owns_audio_pool_index/owns_midi_clip_id, since a folder owns
  one pool file per take, not just the active one.
- BackendContext::add_clip_instance/remove_clip_instance: switching takes
  is a remove + re-add (there's no in-place pool-swap command), and that's
  the same work AddClipInstanceAction does. One implementation, on the
  context that already owns the controller and both ID maps, so the
  seconds-vs-beats conversions can't drift between copies.

Capture (phase 3):
- Takes are cut GEOMETRICALLY at stop, in exact loop-length multiples. The
  playhead advances before the capture block in process(), so the wrap
  instant isn't sample-exact against the buffer just captured — but the
  geometry is. wrap_count only decides *whether* the recording is
  multi-take, never where the cuts land.
- Partial passes are padded with silence: punch in mid-region and take 1
  gets silence prepended back to the region start; stop mid-pass and the
  last take gets silence appended. Every take is the same length, which is
  the invariant comping depends on. A final take under 50ms of real audio
  is dropped as a stop artifact (but a take that FILLED the region never
  is, however short the region).
- MIDI merges, and it falls out for free: anchoring the recording at
  loop_start rather than the punch-in point means the transport always
  wraps back INTO the region, so every note's offset already lands inside
  [0, loop_len) and passes overdub with no folding logic at all.
- The whole session commits as ONE undoable action via push_applied.

Fixes found on the way:
- Split was seconds/beats confused on MIDI. trim_start/trim_end are
  domain-polymorphic exactly like AudioClip::duration was — SECONDS for
  audio/video/vector, BEATS for MIDI — and split mapped the split point
  into clip content in seconds unconditionally. Now it works in the clip's
  own domain via Document::clip_trim_duration(). Regression test included.
- TrimClip took raw f64s whose meaning flipped by track type, and the
  engine set an AUDIO clip's external_duration = Beats(end - start) where
  those bounds were SECONDS — so a 1-second split played back as half a
  second at 120 BPM. Replaced with a domain-tagged TrimRange, built from
  the clip (clip.trim_range()) so the wrong unit isn't expressible, and
  the span is now converted at the clip's position on the timeline.
- The live preview grew past the loop end while the playhead wrapped. It
  now grows through the first pass then pins at the region length, and the
  waveform inside restarts at the region start on each pass. The pass
  offset is derived from the captured buffer, not the playhead — those
  advance on different clocks, and differencing them made the waveform
  jitter horizontally.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 14:40:10 -04:00
..
export Timeline types stage 2: fix editor seconds↔beats at every clip boundary 2026-07-11 14:10:38 -04:00
mobile Cycle recording phase 1: transport loop region 2026-07-13 02:13:06 -04:00
panes Cycle recording: multi-take capture, take folders, comping 2026-07-13 14:40:10 -04:00
preferences Clean up build warnings 2026-07-09 13:24:32 -04:00
tools Add drawing tablet input support 2026-03-11 10:58:30 -04:00
widgets make sample load menus consistent 2026-02-16 19:12:21 -05:00
config.rs Fix FLAC export end-to-end (real backend path) + smart tag defaults 2026-07-09 13:09:54 -04:00
cqt_gpu.rs Add clip split and duplicate commands 2026-02-15 02:11:57 -05:00
curve_editor.rs Clean up build warnings 2026-06-21 16:48:59 -04:00
custom_cursor.rs Add tool skeletons 2026-03-06 07:22:50 -05:00
debug_overlay.rs Composite grouped/nested video on the GPU path 2026-06-22 17:38:30 -04:00
default_instrument.rs clean up some compiler warnings 2025-12-03 06:39:26 -05:00
effect_thumbnails.rs Fix gamma handling and improve brush canvas performance 2026-06-16 08:32:39 -04:00
gpu_brush.rs Address code-review findings across export, decode, and data model 2026-06-26 17:47:32 -04:00
gpu_timer.rs Composite grouped/nested video on the GPU path 2026-06-22 17:38:30 -04:00
hw_video.rs hw: surface import_raw failures (diagnose washed-out 10-bit HDR) 2026-06-26 03:59:39 -04:00
keymap.rs Onion skinning (raster): toggle + tinted ghosts of the active layer 2026-06-20 23:05:57 -04:00
main.rs Cycle recording: multi-take capture, take folders, comping 2026-07-13 14:40:10 -04:00
menu.rs Onion skinning (raster): toggle + tinted ghosts of the active layer 2026-06-20 23:05:57 -04:00
notifications.rs Address code-review findings across export, decode, and data model 2026-06-26 17:47:32 -04:00
nv12_blit.rs nv12: HDR-correct input — PQ/HLG EOTF + BT.2020→709 gamut (Stage A pt 1) 2026-06-26 02:47:09 -04:00
raster_tool.rs Clean up build warnings 2026-06-21 16:48:59 -04:00
sample_import.rs Repair test suite + fix sample key-range overlap bug 2026-06-23 19:07:06 -04:00
sample_import_dialog.rs Fit modal dialogs to the phone screen on mobile 2026-07-01 06:28:04 -04:00
svg_import.rs Address code-review findings across export, decode, and data model 2026-06-26 17:47:32 -04:00
tablet.rs fix build issues 2026-06-02 13:41:10 -04:00
test_mode.rs Clean up build warnings 2026-06-21 16:48:59 -04:00
theme.rs Unify colors via theme CSS variables; theme egui visuals 2026-07-01 07:08:00 -04:00
theme_render.rs Clean up build warnings 2026-06-21 16:48:59 -04:00
waveform_gpu.rs Stream audio & video from .beam container; waveform LOD pyramid + persistence 2026-06-17 13:52:38 -04:00