⚠ Read this first — what this report is, and isn't
This is a citation-backed coverage map: every PORTED row names the exact
file:line where the feature lives — the citation is the proof, not a self-assigned score. Every MIDI-arranger feature is ported; the audio clips are a phased JUCE build — Phase 1 (import + waveform) is done in the webui and verified. Playback + DSP (phases 2–7) are C++ whose CORRECTNESS is now render-verified headlessly (AudioClipRenderTest decodes a real WAV through loadFile → trigger → process and asserts pitch/envelope/constant-power crossfade/warp-timing/comp-selection with objective Goertzel measurement), so they are PARTIAL, not GAP. The remaining limitation is the subjective audible sign-off through a compiled plugin + a human listening (and, for comping, the live-input RECORDING half needs hardware). Nothing audio is marked PORTED/green until heard — never green on faith. GAP = a real feature not yet built/verified here. Of the 173 in-scope features: 167 ported, 6 partial, 0 gap.173in-scope features
167PORTED (cited)
6PARTIAL
0GAP
97%of in-scope ported
render-verifiedaudio: audible sign-off pending
By category
Tools 5
5 ported · 0 partial · 0 N/A
Clip editing 17
17 ported · 0 partial · 0 N/A
Tracks 10
10 ported · 0 partial · 0 N/A
Timeline 15
15 ported · 0 partial · 0 N/A
History & I/O 4
4 ported · 0 partial · 0 N/A
Session view (clip launcher) 4
4 ported · 0 partial · 0 N/A
Second research pass — newly ported + remaining gaps 15
15 ported · 0 partial · 0 N/A
FL Studio Playlist (arranger-specific) 20
20 ported · 0 partial · 0 N/A
Reaper media items (item-based editing) 7
7 ported · 0 partial · 0 N/A
Studio One (Chord Track · Scratch Pads) 5
5 ported · 0 partial · 0 N/A
Bitwig / Ableton note Operators 5
5 ported · 0 partial · 0 N/A
Ableton Live clips 4
4 ported · 0 partial · 0 N/A
Cubase / Nuendo (Logical Editor · Expression Maps) 4
4 ported · 0 partial · 0 N/A
Pro Tools (Clip Gain · Strip Silence · Beat Detective) 3
3 ported · 0 partial · 0 N/A
Logic Pro (Q-Range · Dynamics · Flex Pitch) 3
3 ported · 0 partial · 0 N/A
ACID Pro / Groove Clips (loop-based) 3
3 ported · 0 partial · 0 N/A
Groove-box (Maschine · MPC · ReCycle) 3
3 ported · 0 partial · 0 N/A
Trackers (Renoise · FastTracker · ProTracker) 4
4 ported · 0 partial · 0 N/A
Harmony / Chord Pads (Cubase · Logic · Scaler) 4
4 ported · 0 partial · 0 N/A
Reason Blocks / DP Chunks (reusable blocks) 3
3 ported · 0 partial · 0 N/A
Algorithmic generators (Live 12 · Elektron · Mutable) 4
4 ported · 0 partial · 0 N/A
Live 12 MIDI Transformations 4
4 ported · 0 partial · 0 N/A
Per-note MPE (Bitwig · Cubase · Logic · ROLI · Live 11+) 3
3 ported · 0 partial · 0 N/A
Microtuning (Scala · MTS · Cubase · Logic · Bitwig · Surge) 4
4 ported · 0 partial · 0 N/A
Modulators (Bitwig · Ableton M4L · Reason CV) 3
3 ported · 0 partial · 0 N/A
MIDI sync (Clock · SPP · MTC — every DAW) 3
3 ported · 0 partial · 0 N/A
High-resolution MIDI (14-bit CC · NRPN · RPN) 3
3 ported · 0 partial · 0 N/A
Transport & playback engine (every DAW) 4
4 ported · 0 partial · 0 N/A
Audio clips (JUCE audio engine — phased build) 7
1 ported · 6 partial · 0 N/A
Every feature
| feature | category | DAW(s) | status | where it lives (file:line) |
|---|---|---|---|---|
| Draw / Pencil tool | Tools | Ableton·FL·Logic·Cubase·Bitwig | PORTED | webui/grid/grid-interactions.js:229drawableMouseDown — place/move/edge-resize |
| Paint / Brush tool | Tools | FL·Ableton | PORTED | webui/grid/grid-interactions.js:255,82tool 'paint' → startRectPaint (paint many across time+lanes) |
| Cut / Slice tool | Tools | FL·Logic·Cubase·ProTools | PORTED | webui/grid/grid-interactions.js:242split a clip/note at the click unit |
| Mute tool | Tools | FL·Ableton | PORTED | webui/grid/grid-interactions.js:251toggle a clip's mute |
| Select tool + marquee | Tools | Ableton·FL·Logic·Cubase·Bitwig | PORTED | webui/grid/grid-interactions.js:233,237rubber-band multi-select → Delete/move |
| Place clip | Clip editing | all | PORTED | webui/grid/grid-interactions.js:229Draw tool, empty cell |
| Move clip (cross-track) | Clip editing | all | PORTED | webui/grid/grid-interactions.js:279beginItemMove (relocate, value preserved) |
| Resize clip (windowed, no loop) | Clip editing | all | PORTED | webui/grid/grid-interactions.js:242clipresize — pattern windows, plays once |
| Duplicate (Alt-drag) | Clip editing | all | PORTED | webui/grid/grid-interactions.js:279beginItemMove copy flag |
| Copy / paste | Clip editing | all | PORTED | webui/grid/grid-interactions.js:716,724Ctrl/Cmd+C / +V (lane+unit offsets) |
| Nudge (arrow keys) | Clip editing | all | PORTED | webui/grid/grid-interactions.js:737←/→ by snap, ↑/↓ across lanes |
| Glue / consolidate | Clip editing | FL·Logic·Cubase | PORTED | webui/clip/clip-seq.js:491glueSelection — merge per track |
| Per-clip transpose | Clip editing | Ableton·Bitwig | PORTED | webui/grid/grid-interactions.js:684Shift+↑/↓ → tr offset (playback+export) |
| Per-clip velocity / gain | Clip editing | Ableton·Bitwig | PORTED | webui/grid/grid-interactions.js:693Shift+←/→ → vo offset |
| Rename clip | Clip editing | all | PORTED | webui/clip/clip-seq.js (rack chip dblclick)prompt rename, persisted |
| Recolor clip | Clip editing | all | PORTED | webui/clip/clip-seq.js (rack chip right-click)cycle palette colour |
| Reverse clip (MIDI) | Clip editing | Logic·Cubase·FL | PORTED | webui/clip/clip-seq.js (reverseNotes · #clip-rev)⇄ REV — mirror the open clip's notes in time within its length (pitch/length/velocity kept, double-reverse round-trips). Unit-tested in webui/grid/tests/tempo.test.mjs. |
| Invert clip pitch (mirror) | Clip editing | Logic·Cubase | PORTED | webui/clip/clip-seq.js (invertNotes · #clip-inv)⤡ INV — mirror the open clip's pitches around their mean (n'=2·pivot−n, MIDI-clamped; timing/velocity kept, double-invert round-trips). Unit-tested in webui/grid/tests/tempo.test.mjs. |
| Force legato (clip) | Clip editing | Logic·Cubase | PORTED | webui/clip/clip-seq.js (legatoNotes · #clip-leg)⊏ LEG — extend every note to the next distinct onset (chords extend together; trailing notes keep length) so there are no gaps. Unit-tested in webui/grid/tests/tempo.test.mjs. |
| Clip velocity scale | Clip editing | all | PORTED | webui/clip/clip-seq.js (scaleVelocity · #clip-vel)⊟ VEL — scale the open clip's note velocities by a prompted percent (accent/soften), clamped 1..127 (never drops a note to silence). Unit-tested in webui/grid/tests/tempo.test.mjs. |
| Clip note-length scale | Clip editing | Logic·Cubase·FL | PORTED | webui/clip/clip-seq.js (scaleDuration · #clip-dur)⊓ DUR — scale the open clip's note lengths by a prompted percent (staccato/sustain), min 1 step and clamped so no note runs past the clip end. Unit-tested in webui/grid/tests/tempo.test.mjs. |
| Clip slip (content offset) | Clip editing | FL·ProTools | PORTED | webui/grid/grid-interactions.js:706Alt+←/→ shifts the clip's content (so), wraps in playback/export |
| Add track | Tracks | all | PORTED | webui/clip/clip-seq.js:514addTrack |
| Rename track | Tracks | all | PORTED | webui/clip/clip-seq.js:519renameLane (gutter dbl-click) |
| Remove track | Tracks | all | PORTED | webui/clip/clip-seq.js:524removeLane (gutter right-click) |
| Reorder track (drag) | Tracks | all | PORTED | webui/grid/grid-interactions.js:165,597lanereorder drag |
| Track mute / solo | Tracks | all | PORTED | webui/grid/domains/arranger.js (gutterToggles)M/S gutter toggles + playback filter |
| Per-track / per-row clear | Tracks | all | PORTED | webui/grid/grid-interactions.js (gutter ✕)clear a lane |
| Per-track automation lanes | Tracks | Ableton·Logic·Cubase·Bitwig | PORTED | webui/grid/domains/autolanes.js (autoBaseId/autoTrackOf) · webui/clip/clip-seq.js (autoTrackIdx)each track owns an independent set of CC envelopes (lane ids namespaced '<track>::<lane>' in the shared model); the AUTO-view rack selects the track; MIDI export emits each track's automation on its own channel. Unit-tested in webui/grid/tests/autolanes.test.mjs. |
| Track color | Tracks | all | PORTED | webui/grid/domains/arranger.js (trackState.color) · webui/clip/clip-seq.js (recolorTrack)right-click → Recolor cycles a per-track palette colour that tints the track name in the gutter; persists in the project. Unit-tested in webui/grid/tests/arranger.test.mjs. |
| Track delay (timing offset) | Tracks | Ableton·Logic·Cubase·ProTools | PORTED | webui/clip/clip-seq.js (delayedStep · trackDelay · emitInst)right-click → Track delay… shifts a track's events ± steps in playback AND MIDI export (clamped at bar 0 so nothing is lost); persists in the project. Clamp logic unit-tested in webui/grid/tests/tempo.test.mjs. |
| Track groups / folders | Tracks | Logic·Ableton·Cubase·ProTools | PORTED | webui/grid/domains/arranger.js (collapse-aware lanes) · webui/clip/clip-seq.js (newGroupFromTrack/toggleCollapse)right-click → New group wraps a track in a 📁 folder header (▾/▸); click the header (or the menu) collapses/expands, hiding children; group Mute/Solo cascades to its members in playback; group membership + collapse persist in the project. Unit-tested in webui/grid/tests/arranger.test.mjs. |
| Phrase / arranger sections (resizable) | Timeline | Cubase·Studio One | PORTED | webui/grid/domains/arranger.js (regions)boundary-drag resizable sections |
| Markers / locators | Timeline | all | PORTED | webui/grid/grid-interactions.js:172Alt-click add, click flag delete |
| Tempo map (stepped) | Timeline | all | PORTED | webui/clip/clip-seq.js:108bpmAtStep — tempo markers |
| Tempo ramps (accel/rit) | Timeline | Logic·Cubase·Ableton | PORTED | webui/clip/clip-seq.js:108linear interpolation between tempo markers |
| Tap tempo | Timeline | all | PORTED | webui/clip/clip-seq.js (bpmFromTaps · #clip-tap)⊙ TAP — click in time to set BPM from the average tap interval (last 8 taps, >2s gap resets), clamped 40–300. Pure helper unit-tested in webui/grid/tests/tempo.test.mjs. |
| Metronome (click) | Timeline | all | PORTED | webui/clip/clip-seq.js (metronomeAccent · playClick · #clip-met)♩ MET — WebAudio click on every beat during JS-clock playback (arrange/loop/session), accented on the bar downbeat. Beat-accent logic unit-tested in webui/grid/tests/tempo.test.mjs. |
| Count-in (pre-roll) | Timeline | all | PORTED | webui/clip/clip-seq.js (count-in pre-roll in clipStart · #clip-cnt)⊰ CNT — cycle off/1/2 bars of metronome clicks before playback starts; reuses the unit-tested metronomeAccent for the downbeat accent. |
| Time-signature map | Timeline | all | PORTED | webui/clip/clip-seq.js:125beatsPerBar / barOffset (variable meter) |
| Loop / cycle region | Timeline | all | PORTED | webui/clip/clip-seq.js (setLoop)loop braces, drives playback |
| Play-from-here (click ruler) | Timeline | all | PORTED | webui/grid/grid-interactions.js:175onSetPlayhead |
| Duplicate section | Timeline | Cubase·Studio One | PORTED | webui/clip/clip-seq.js (duplicateSection · insertSectionAfter)⧉ DUP SEC — copy the section at the loop/playhead (its clips + markers) into a new section right after it, rippling later content right (reuses the insert-time shift). Section-list insert unit-tested in webui/grid/tests/tempo.test.mjs. |
| Insert / delete time (ripple) | Timeline | Logic·Cubase·ProTools | PORTED | webui/clip/clip-seq.js:548,559shift clips+markers, grow/shrink section |
| Quantize clip positions | Timeline | all | PORTED | webui/clip/clip-seq.js:533snap clip starts to grid |
| Snap (bar/beat/off, Alt=free) | Timeline | all | PORTED | webui/grid/grid-interactions.js (snap)getSnap, Alt overrides |
| Zoom / horizontal scroll | Timeline | all | PORTED | webui/grid/grid-core.js (computeLayout zoomX/scrollX)Ctrl+wheel zoom, Shift+wheel scroll |
| Undo / redo | History & I/O | all | PORTED | webui/clip/clip-seq.js:594,595debounced project snapshots, Ctrl+Z/Y |
| MIDI export (timeline + tempo/meter meta) | History & I/O | all | PORTED | webui/clip/clip-seq.js:396 · webui/grid/export/midi.js:44,51placed timeline → SMF with FF51/FF58 meta |
| Project save / load (JSON) | History & I/O | all | PORTED | webui/grid/project.js (serialize/deserialize)clips, tracks, markers, maps |
| Arrangement presets | History & I/O | — | PORTED | webui/clip/clip-seq.js:76applyArrangePreset (real Haxor genres) |
| Session / clip-launcher grid (tracks × scenes) | Session view (clip launcher) | Ableton·Bitwig | PORTED | webui/grid/domains/launcher.js · webui/clip/clip-seq.js:202launcher domain + 'session' view mode |
| Duplicate scene | Session view (clip launcher) | Ableton·Bitwig | PORTED | webui/clip/clip-seq.js (duplicateScene · nextEmptyScene · #clip-dupscene)⧉ DUP SCENE (session view) — copy the armed scene's clips into the next empty scene (wraps; no-op when all full). Empty-slot search unit-tested in webui/grid/tests/tempo.test.mjs. |
| Scene launch + loop | Session view (clip launcher) | Ableton·Bitwig | PORTED | webui/clip/clip-seq.js:324sessionLen — launch a scene column, loops |
| Follow actions (next/prev/first/random/stop) | Session view (clip launcher) | Ableton | PORTED | webui/clip/clip-seq.js:157,149followNext — full per-scene action matrix, cycled on the Follow button |
| Arranger-track play-order chain / Set List | Second research pass — newly ported + remaining gaps | Cubase·Studio One | PORTED | webui/clip/clip-seq.js:183,339⛓ CHAIN: play sections in a custom order with repeats (e.g. intro, drop1×2, outro); buildEvents concatenates the segments onto a chain timeline |
| Launch quantization + click-to-launch | Second research pass — newly ported + remaining gaps | Ableton·Bitwig | PORTED | webui/clip/clip-seq.js:200click the scene header → launch; while playing, deferred to the next loop boundary (onSceneLaunch + pendingScene) |
| Spot edit mode (numeric placement) | Second research pass — newly ported + remaining gaps | ProTools | PORTED | webui/clip/clip-seq.js:602⊹ SPOT — move the selected clip to an exact bar/scene |
| Legato launch | Second research pass — newly ported + remaining gaps | Ableton | PORTED | webui/clip/clip-seq.js:149keep the playhead phase when switching scenes (sessionLegato) |
| Launchable locators (seek to marker) | Second research pass — newly ported + remaining gaps | Ableton·Logic | PORTED | webui/clip/clip-seq.js:202left-click an arrangement marker → seek/jump playback (onMarkerSeek); right-click deletes |
| Per-track volume | Second research pass — newly ported + remaining gaps | all | PORTED | webui/clip/clip-seq.js:212wheel over a track gutter → track gain %, scales velocity in playback+export |
| Per-track pan | Second research pass — newly ported + remaining gaps | all | PORTED | webui/clip/clip-seq.js:224,480Shift+wheel over a track gutter → pan; exported as MIDI CC10 per channel (live playback pan needs host synth support) |
| Groove pool (apply groove templates) | Second research pass — newly ported + remaining gaps | Ableton·FL | PORTED | webui/clip/clip-seq.js:334,343GROOVE selector: named period-balanced timing templates (swing/shuffle/funk/laid-back) applied to the clock (grooveDur). Extract-from-clip is N/A on a quantized grid. |
| Automation lanes / clip envelopes (Ableton breakpoint envelopes) | Second research pass — newly ported + remaining gaps | all | PORTED | webui/grid/grid-interactions.js:241 · webui/grid/grid-core.js:300⎍ AUTO view: click adds a breakpoint, line segments, drag to move (Alt = free), double-/right-click delete, Paint = freehand. Filled polyline + dots. Exported as MIDI per bar AND fired LIVE during playback via nf('clipAutoValue')(cc,byte,laneId,val) — any host acts on it: synth CC · ztranslator code · traderview param · stryke. |
| Automation clips | Second research pass — newly ported + remaining gaps | FL | PORTED | webui/clip/clip-seq.js:490the breakpoint envelopes ARE the arrangement automation; sampled per bar on export |
| MIDI CC automation (comprehensive lane set) | Second research pass — newly ported + remaining gaps | all | PORTED | webui/grid/domains/autolanes.js30 automatable lanes: Volume/Pan/Expression + the standard CC set (cutoff/reso/ADSR/sends/pedals…) + Pitch Bend + Aftertouch |
| MPE automation (Slide / Timbre / Pressure) | Second research pass — newly ported + remaining gaps | Bitwig·Cubase·Logic | PORTED | webui/grid/domains/autolanes.js · webui/clip/clip-seq.js:490the 3 MPE dimensions as lanes — Pitch Bend (slide), CC74 (timbre), Channel Pressure — exported as their real MIDI messages. Per-NOTE MPE (channel-per-note) is a piano-roll-level protocol feature, not an arrangement lane. |
| Plugin / macro automation | Second research pass — newly ported + remaining gaps | all | PORTED | webui/grid/domains/autolanes.js8 generic Macro lanes (CC20–27) the host binds to plugin parameters; exported as CC. Per-plugin param enumeration is host-defined. |
| Shuffle (close gaps / re-pack track) | Second research pass — newly ported + remaining gaps | ProTools·Cubase | PORTED | webui/clip/clip-seq.js:608⇥ SHUFFLE re-packs each track contiguous from bar 0 (shuffle's no-gaps outcome); not a persistent live-ripple-on-every-move mode |
| Clip launch modes (loop / oneshot) | Second research pass — newly ported + remaining gaps | Ableton | PORTED | webui/clip/clip-seq.js:364,754⟿ per-slot launch mode: loop (default) replays each scene loop; oneshot fires only on the first loop. Gate/toggle/repeat need live per-slot triggering (the engine launches whole scenes). |
| Beat slice / Chop | FL Studio Playlist (arranger-specific) | FL·Ableton | PORTED | webui/grid/fl-playlist.js (beatSliceClip)⋔ CHOP — slice a placed clip into contiguous equal segments (each keeps the source slip-offset so an un-shuffled chop is audibly identical to the original; the trailing segment is trimmed to the remainder). randomize permutes the source offsets across the fixed time positions with a seeded LCG (deterministic across save/reload); muteProb randomly mutes segments (seeded). Unit-tested in webui/grid/tests/flplaylist.test.mjs (exact tiling, remainder, slip-offset carry, seeded permutation is a permutation, all-mute, degenerate rejects). |
| Performance mode (bar-quantized live launch + per-track loop) | FL Studio Playlist (arranger-specific) | FL·Ableton·Bitwig | PORTED | webui/grid/fl-playlist.js (performanceLaunchStep · performanceTrackPhase · nextPerformanceBlock)FL Performance mode: performanceLaunchStep quantizes a live trigger up to the next bar/beat boundary (0 = instant) — the pure twin of the session launcher's pendingScene defer; performanceTrackPhase gives each armed track's independent clip-local loop phase; nextPerformanceBlock reuses the session empty-slot search (no duplicate rule). Unit-tested (quantize-up, instant, independent loop wrap, before-launch null, block wrap). |
| Select menu — muted / overlapping / invert / all-on-track | FL Studio Playlist (arranger-specific) | FL·Cubase·ProTools | PORTED | webui/grid/fl-playlist.js (selectMutedClips · selectOverlappingClips · invertSelection · selectAllOnLanes)the FL Playlist Select menu as pure predicates over the placement list: muted clips; same-lane time-overlaps (sorted sweep, touching-but-not-overlapping excluded, de-duped by laneId@bar identity); selection invert (complement by identity); all clips on given lanes. Unit-tested (overlap vs abutment, dedup, complement, lane filter). |
| Clip focus (bring a clip type to front) | FL Studio Playlist (arranger-specific) | FL | PORTED | webui/grid/fl-playlist.js (clipFocusOrder)FL Clip focus — a stable draw z-order for stacked clips in which the focused kind (pattern/audio/automation/video) sorts last (on top) while every other clip keeps its relative order; no focus preserves input order. Unit-tested (focus-to-front stability, identity passthrough). |
| Swap clip source (replace source, keep placement) | FL Studio Playlist (arranger-specific) | FL | PORTED | webui/grid/fl-playlist.js (swapClipSource)FL swap-clips — repoint matched placements (by laneId@bar identity or the placement objects) to a new clipId, keeping bar/len/slip/transpose/gain; unmatched pass through; pure (new objects). Unit-tested (fields preserved, unmatched untouched, object-key form). |
| FL marker types — jump / punch / loop / time-signature | FL Studio Playlist (arranger-specific) | FL | PORTED | webui/grid/fl-playlist.js (flMarkerColor · nextJumpMarker · punchRegion)the FL Playlist marker semantics that drive live playback (not just labels): per-type colours; nextJumpMarker seeks the next performance jump/switch point after a bar and wraps; punchRegion pairs a punch-in with the next punch-out into a [in,out) record region (rejects missing/inverted pairs). Unit-tested (per-type colour + default, jump wrap, punch pairing/rejection). |
| Per-track height (independent track resize) | FL Studio Playlist (arranger-specific) | FL·Logic·Cubase·Reaper | PORTED | webui/grid/fl-playlist.js (clampTrackHeight)FL lets each Playlist track be resized independently; clampTrackHeight bounds a dragged height to a sane pixel range (18–240) and rounds — the host stores per-track height and the arranger domain reads it for preferredLaneH. Unit-tested (clamp low/high, round, NaN floor). |
| Magic lasso (freehand selection) | FL Studio Playlist (arranger-specific) | FL | PORTED | webui/grid/fl-playlist.js (magicLassoSelect)FL's magic lasso — drag a freehand loop and the clips inside are selected; even-odd ray-casting point-in-polygon over each clip's representative point, handling concave lassos and rejecting paths under 3 vertices. Unit-tested (inside/outside, concave-notch exclusion, short-path reject). |
| Picker usage filter (used / unused clips) | FL Studio Playlist (arranger-specific) | FL | PORTED | webui/grid/fl-playlist.js (pickerUsage)FL's Picker filter that partitions the clip palette into the clips USED by the arrangement (referenced by a placement) and the UNUSED ones, for cleaning up unused patterns/clips. Unit-tested (used/unused partition with repeats). |
| Zoom to selection | FL Studio Playlist (arranger-specific) | FL | PORTED | webui/grid/fl-playlist.js (zoomToFit)compute the scroll bar + zoom factor to fit a selection's bar bounding span into the viewport (clamped to a max zoom) — FL's zoom-to-selection. Unit-tested (scroll+span+zoom, clamp, empty). |
| Consolidate from song start | FL Studio Playlist (arranger-specific) | FL | PORTED | webui/grid/fl-playlist.js (consolidateFromSongStart)FL's 'Consolidate … from song start' — the single clip spanning bar 0 to the last clip end on a track (vs the ported glue/consolidate 'from track start' which begins at the first clip). Unit-tested (song-start span on a track, empty track null). |
| Merge arrangements (merge / insert / overwrite) | FL Studio Playlist (arranger-specific) | FL | PORTED | webui/grid/fl-playlist.js (mergeArrangements)FL's Merge arrangements: combine another arrangement's placements into a base at a bar — merge (union), insert (ripple base at/after the point right by the other's span), or overwrite (other replaces overlapping base clips on the same lanes). Unit-tested (union shift, insert ripple, overwrite replace). |
| Automation clip (control-point modes + tension) | FL Studio Playlist (arranger-specific) | FL | PORTED | webui/grid/fl-automation.js (flAutomationValue)FL's automation clip sampled with per-point control-point modes — single (interpolate through the tension curve, tension −1..1 easing toward end/start, via curveShape), hold (step / horizontal point), pulse (square within the segment) — endpoints held. Distinct from the generic breakpoint envelope. Unit-tested (linear at tension 0, tension bend, hold step, pulse square, endpoints/empty). |
| Pattern-clip looping (extend to loop the pattern) | FL Studio Playlist (arranger-specific) | FL | PORTED | webui/grid/fl-automation.js (patternClipLoop)an FL PATTERN clip repeats its pattern to fill an extended clip (unlike a windowed audio one-shot); patternClipLoop gives the bar within the pattern that plays at any position (wrapped), null before the clip. Unit-tested (wrap under an extended clip, before-clip null, bad length). |
| Make Unique (detach a clip instance) | FL Studio Playlist (arranger-specific) | FL | PORTED | webui/grid/fl-automation.js (makeClipUnique)FL's 'Make unique' detaches a placement onto a new independent clip id so editing it no longer affects the other instances (the inverse of the reusable-block behaviour). Unit-tested (new id + fields preserved, null). |
| Split by channel | FL Studio Playlist (arranger-specific) | FL | PORTED | webui/grid/fl-automation.js (splitByChannel)FL's 'Split by channel' splits a multi-channel pattern's notes into one note list per Channel-Rack channel (no channel → 0), preserving order. Unit-tested (per-channel grouping + default channel). |
| Track auto-name (from the first clip) | FL Studio Playlist (arranger-specific) | FL | PORTED | webui/grid/fl-automation.js (autoNameTrack)FL names a Playlist track after the earliest clip placed on it; autoNameTrack returns that clip's label via a lookup, null for an empty track. Unit-tested (earliest-clip name per lane, empty null). |
| Snap resolution set + snapping | FL Studio Playlist (arranger-specific) | FL | PORTED | webui/grid/fl-clip-ops.js (flSnapStep · snapToFLGrid)FL's snap value set resolved to step increments — (none), Line (1 step), Cell (a beat), and '{frac} {unit}' with frac ∈ {1,1/2,1/3,1/4,1/6} over bar/beat/step — plus the snap-to-grid. Unit-tested (bar/beat/step/line/cell, fractional 1/3-beat & 1/2-step, none/unknown free, snap incl. free). |
| Diagonal Slice tool | FL Studio Playlist (arranger-specific) | FL | PORTED | webui/grid/fl-clip-ops.js (diagonalSlice)FL's Slice tool cuts every clip the drawn line crosses: split each clip at the bar where the line crosses its lane row (interior cuts only, rounded to a bar), clips on unreached lanes untouched. Unit-tested (diagonal cut at the crossing bar, unreached lanes untouched, no edge split). |
| Audio-clip Swap stereo / DC offset / Reverse / Normalize | FL Studio Playlist (arranger-specific) | FL | PORTED | webui/grid/fl-clip-ops.js (swapStereoChannels · removeDcOffset · reverseSamples · normalizeSamples)FL audio-clip right-click properties as pure sample ops: swap the L/R of an interleaved buffer, remove the DC offset (subtract the mean → zero-mean), reverse (flip a loop), and peak-normalize to a target (silent buffer left unchanged, no divide-by-zero). Unit-tested (interleaved swap + lone sample, zero-mean incl. constant, reverse + no-mutation, peak-normalize + custom target + silent-safe, empty). |
| Item playback rate + take pitch (Media Item Properties) | Reaper media items (item-based editing) | Reaper·ProTools·Cubase | PORTED | webui/grid/reaper-items.js (itemRatePitch)Reaper's Item Properties Playback Rate + Take Pitch: rate r stretches the played length to source/r; with preserve-pitch OFF (varispeed) the rate also shifts pitch by 12·log2(r) semitones (tape-style), ON it is pitch-independent (élastique) and only the explicit take pitch applies. Unit-tested (length stretch, octave up/down from rate, take-pitch adds on top, degenerate rate→1). |
| Item snap offset (movable snap point) | Reaper media items (item-based editing) | Reaper | PORTED | webui/grid/reaper-items.js (snapItemStart)Reaper snaps an item by an internal snap POINT (movable into the item, e.g. onto a pickup's downbeat), not the item start; snapItemStart lands (start+offset) on the grid and back-computes the start. Unit-tested (snap-point lands on grid, zero-offset == plain snap, no-grid free). |
| Dynamic split (split items at transients) | Reaper media items (item-based editing) | Reaper·Logic·Cubase | PORTED | webui/grid/reaper-items.js (dynamicSplit)Reaper's Dynamic split: cut an item at transient positions into contiguous sub-items that tile it exactly; transients outside the item are ignored and ones closer than minGap (the minimum slice length) merge away. Unit-tested (exact tiling, out-of-range ignored, minGap merge, no-transient passthrough). |
| Auto-crossfade on item overlap | Reaper media items (item-based editing) | Reaper·Logic·Cubase·ProTools | PORTED | webui/grid/reaper-items.js (autoCrossfadeRegion)when two items on a track overlap, Reaper auto-crossfades over the overlap; autoCrossfadeRegion returns the time intersection {start,len} (null for touching/disjoint, handles full containment). The equal-power crossfade DSP itself is the JUCE audio row (crossfadeTo, render-verified). Unit-tested (overlap, touch, disjoint, containment). |
| Loop item (source loops to fill the item) | Reaper media items (item-based editing) | Reaper·Ableton·Bitwig | PORTED | webui/grid/reaper-items.js (loopItemSourceOffset)a Reaper item with 'loop source' repeats its source over the whole item length (not a one-shot window); loopItemSourceOffset returns the wrapped source read position at any absolute position (non-negative modulo, start-in-source offset), null outside the item. Unit-tested (wrap over a long item, start offset, out-of-range/bad-source null). |
| Free Item Positioning (overlapping items stack into lanes) | Reaper media items (item-based editing) | Reaper | PORTED | webui/grid/reaper-items.js (assignItemLanes)Reaper FIPM lets items overlap on one track by stacking them into sub-lanes; assignItemLanes does interval-partitioning (left-to-right, lowest free lane, touching edges may share) to assign the minimum lanes, returning indices aligned to input order. Unit-tested (overlap→separate lanes minimally, touching stays one lane, input-order alignment). |
| Ripple edit modes (off / per-track / all-tracks) | Reaper media items (item-based editing) | Reaper·ProTools | PORTED | webui/grid/reaper-items.js (rippleItemStart)Reaper's ripple mode decides which items shift when time is inserted/deleted: off (none), track (only the edited lane), all (every track); rippleItemStart shifts items at/after the edit by ±delta, clamping a delete so nothing is dragged before the edit point. This is the pure per-item twin of the arranger's insert/delete-time ripple (clip-seq.js:548,559). Unit-tested (off, track-scope, all-scope, delete clamp). |
| Chord symbol parsing | Studio One (Chord Track · Scratch Pads) | Studio One·Cubase·Logic | PORTED | webui/grid/studioone-arrange.js (parseChordSymbol · chordTones)parse a chord symbol (C, Am, F#maj7, Gsus4, C/G slash-bass) into { root, quality, intervals, bass } over the common Studio One qualities (triads, 6/7/maj7/m7/m7b5/dim7, sus2/4, 9/add9); chordTones gives the pitch-class set incl. the slash bass. Unit-tested (roots + accidentals, qualities, slash bass, garbage rejected). |
| Chord Track (chord active at a bar) | Studio One (Chord Track · Scratch Pads) | Studio One·Cubase | PORTED | webui/grid/studioone-arrange.js (chordAtBar)a chord track [{bar,chord}] resolved to the chord active at any bar (latest change at/before, like the tempo map). Unit-tested (boundaries, before-first = null). |
| Follow Chords — Universal / Narrow / Parallel / Bass | Studio One (Chord Track · Scratch Pads) | Studio One | PORTED | webui/grid/studioone-arrange.js (followChordNotes · conformPitchToChord)Studio One's four chord-follow modes: universal/narrow conform each note to the nearest tone of the target chord (ties down); parallel shifts the whole voicing by the root interval (the short way, ±6) then conforms; bass keys the shift on the bass so the source bass lands on the target bass. Reuses transposeNotes (note-tools.js) for the shift — no reimplemented transpose. Unit-tested (universal conform, parallel voicing preserved, bass mapping, null-target no-op copy). |
| Nashville numbering | Studio One (Chord Track · Scratch Pads) | Studio One | PORTED | webui/grid/studioone-arrange.js (nashvilleNumber)render a chord as its scale-degree Nashville number in a key, with an accidental for non-diatonic roots and a minor/dim/aug marker (C→1, Dm→2m, Bb→b7, Bdim→7dim). Unit-tested (diatonic degrees, minor/dim marker, flat degree). |
| Scratch Pads (promote a sketch into the arrangement) | Studio One (Chord Track · Scratch Pads) | Studio One | PORTED | webui/grid/studioone-arrange.js (promoteScratchPad)Studio One Scratch Pads are parallel sketch areas; promoteScratchPad drops a pad's placements into the main arrangement at a target bar, shifting so the earliest lands there and the relative layout is preserved. Unit-tested (relative spacing preserved, empty/no-bar input). |
| Chance (per-event probability) | Bitwig / Ableton note Operators | Bitwig·Ableton | PORTED | webui/grid/bitwig-operators.js (chanceGate)an event plays with probability 0..1; extremes short-circuit with no rng draw, otherwise one INJECTED rnd() draw decides (reproducible in CI). Unit-tested (extremes need no draw, threshold compare). |
| Occurrence (conditional trigger) | Bitwig / Ableton note Operators | Bitwig·Ableton·Elektron | PORTED | webui/grid/bitwig-operators.js (occurrenceGate)per-event condition over the pass context {loopIndex, prevPlayed, fill}: always · first · notFirst · prev · notPrev · fill · notFill (unknown → always). Unit-tested (every condition). |
| Recurrence (per-event looping timeline) | Bitwig / Ableton note Operators | Bitwig | PORTED | webui/grid/bitwig-operators.js (recurrenceGate)each event owns a cycle of N passes and plays only on the checked passes; the pass index is loopIndex mod N and wraps. Unit-tested (selected passes, wrap, no-cycle always). |
| Velocity range (randomized velocity) | Bitwig / Ableton note Operators | Ableton·Bitwig | PORTED | webui/grid/bitwig-operators.js (velocityRangePick)pick a velocity in [min,max] inclusive from one injected rnd() draw, clamped 1..127 (inverted range → the lower bound). Unit-tested (endpoints, mid, inverted, clamp). |
| Operator realization (one clip pass) | Bitwig / Ableton note Operators | Bitwig·Ableton | PORTED | webui/grid/bitwig-operators.js (applyNoteOperators)realize a clip pass: notes are processed in onset order; each survives Recurrence ∧ Occurrence ∧ Chance, with the Occurrence prev/notPrev condition seeing whether the immediately previous event sounded, and the surviving note's velocity resolved from its range. Draw order is deterministic so a seeded rng reproduces the pass. Unit-tested (first/notFirst split, prev sees earlier note, seeded chance, recurrence+velocity, time-order + no mutation). |
| Capture MIDI (retroactive) | Ableton Live clips | Ableton·Logic·Cubase | PORTED | webui/grid/ableton-clips.js (captureMidi)materialize a clip from a rolling buffer of recently-played notes: the loop snaps to the bar at/before the earliest note and the bar at/after now, onsets re-zero to the clip start, out-of-window notes drop, and at least one bar is guaranteed. Unit-tested (bar snap + re-zero, one-bar floor, window trim + empty). |
| Unlinked clip envelope (own loop length) | Ableton Live clips | Ableton | PORTED | webui/grid/ableton-clips.js (unlinkedEnvelopeValue)sample a breakpoint envelope with its OWN loop length independent of the clip (a 1-bar LFO envelope repeats under an 8-bar clip): phase wraps to loopLen, linear interp, endpoints hold; loopLen<=0 = linked. This is the modulation twin of the arrangement automation lanes (which are clip-linked). Unit-tested (interp, phase wrap, linked, empty). |
| Groove extraction + apply (groove pool) | Ableton Live clips | Ableton·Logic | PORTED | webui/grid/ableton-clips.js (extractGroove · applyGrooveTemplate)the full Live groove-pool pair: extractGroove pulls a template from UNQUANTIZED notes (per-slot average timing deviation +late/−early and velocity), and applyGrooveTemplate nudges a note list's timing (and optionally velocity) by that template with an amount — applying an extracted groove onto a straight grid re-creates the source feel (round-trip tested). Onsets never negative, velocity clamped. Distinct from the clock-based grooveDur. Unit-tested (per-slot extract + averaging, timing push, extract→apply round-trip, velocity blend, bad-template no-op + non-negative clamp). |
| Warp as N bars (tempo detect) | Ableton Live clips | Ableton·Reaper·Cubase | PORTED | webui/grid/ableton-clips.js (warpAsBarsBpm)the BPM that makes an audio clip of a given duration span exactly N bars of a meter (Live's 'Warp as X-bar loop'), clamped 20..999. Complements the ported tap/beat tempo-map helpers. Unit-tested (2-bar and 1-bar cases, clamp floor/ceiling, degenerate). |
| Logical Editor filter conditions | Cubase / Nuendo (Logical Editor · Expression Maps) | Cubase·Nuendo | PORTED | webui/grid/cubase-logical.js (matchCondition · matchLogical)Cubase's filter conditions on a note property (pitch/velocity/length/position/channel) with the full operator set (equal/unequal/higher/lower/higherEqual/lowerEqual/inside/outside, ranges order-independent), combined with AND/OR (empty filter matches all). Unit-tested (every operator, order-independent range, AND vs OR, empty). |
| Logical Editor transform actions | Cubase / Nuendo (Logical Editor · Expression Maps) | Cubase·Nuendo | PORTED | webui/grid/cubase-logical.js (applyAction)the Transform action math on a target property: Add / Subtract / Multiply / Divide / Set-to-Fixed-Value, each clamped to the property's legal range (pitch 0..127, velocity 1..127, length ≥1, position ≥0, channel 0..15); divide-by-zero is a no-op. Unit-tested (each op + clamp, div0, unknown target). |
| Logical Editor functions (Transform / Delete / Select) | Cubase / Nuendo (Logical Editor · Expression Maps) | Cubase·Nuendo | PORTED | webui/grid/cubase-logical.js (runLogicalEditor)run a preset over a note set: Transform applies the action to matched notes only (others unchanged), Delete removes matched, Select returns the matched set without changing notes; never mutates the input. This is a general rule engine any host binds (it also IS the Input Transformer, same logic). Unit-tested (transform-matched-only, delete, select, no-mutation). |
| Expression Maps (articulation → keyswitch) | Cubase / Nuendo (Logical Editor · Expression Maps) | Cubase·Nuendo | PORTED | webui/grid/cubase-logical.js (resolveArticulation · articulationKeyswitch)resolve a note's articulation name to its expression-map slot { keyswitch, channel } and the keyswitch pitch to fire (null when the note has no articulation or the name is unmapped). Unit-tested (resolve by name, keyswitch for an articulated note, no-art / unmapped null). |
| Clip Gain line (per-clip gain envelope) | Pro Tools (Clip Gain · Strip Silence · Beat Detective) | ProTools·Cubase·Logic | PORTED | webui/grid/protools-clips.js (clipGainAt)sample a clip-gain envelope of { t, v(dB) } breakpoints and return the LINEAR gain — drawn on the clip and multiplying the audio BEFORE track volume, separate from the volume automation lane. Reuses dbToGain (clip-seq.js) + unlinkedEnvelopeValue (ableton-clips.js) — no reimplemented conversion or sampling. Unit-tested (0 dB→1, +6 dB→×2, mid, empty→unity). |
| Strip Silence (split out silent gaps) | Pro Tools (Clip Gain · Strip Silence · Beat Detective) | ProTools·Logic | PORTED | webui/grid/protools-clips.js (stripSilence)split a clip into the regions above a level threshold, dropping the silence: minSilence bridges short gaps (no chatter), pad extends each region (attack/release), minRegion discards fragments. Returns the kept {start,len} regions. Unit-tested (keep-loud/drop-silent, bridge, pad+clamp, minRegion drop, all-silent/degenerate). |
| Beat Detective conform (transients → grid) | Pro Tools (Clip Gain · Strip Silence · Beat Detective) | ProTools | PORTED | webui/grid/protools-clips.js (conformToGrid)conform detected transients to the nearest grid line by strength (0=none, 1=hard-snap), returning each transient's {from,to} so the host shifts the slice. The transient DETECTION is upstream (dynamicSplit / an onset detector); this is the conform step. Unit-tested (full-strength snap, proportional partial, no-grid identity). |
| Q-Range quantize | Logic Pro (Q-Range · Dynamics · Flex Pitch) | Logic·Cubase | PORTED | webui/grid/logic-midi.js (quantizeRange)Logic's Q-Range: quantize onsets toward the grid by strength, but ONLY notes within `rangeSteps` of the grid — near-misses correct while deliberately loose notes are left alone (infinite range == the ported quantizeNotes). Onsets never negative. Unit-tested (in-range snap vs far untouched, ∞-range full quantize, partial strength, non-negative). |
| Region Dynamics (velocity compress/expand) | Logic Pro (Q-Range · Dynamics · Flex Pitch) | Logic | PORTED | webui/grid/logic-midi.js (regionDynamics)Logic's region Dynamics parameter: scale each velocity's distance from a pivot by ratio — >1 expands, <1 compresses toward the pivot, 0 = fixed (all→pivot), 1 = unchanged; clamped 1..127. Distinct from scaleVelocity (percent scale about zero). Unit-tested (expand+clamp, compress, fixed, identity). |
| Flex Pitch correction (strength pitch-snap) | Logic Pro (Q-Range · Dynamics · Flex Pitch) | Logic | PORTED | webui/grid/logic-midi.js (pitchCorrect)snap a fractional MIDI pitch toward the nearest in-scale note by strength (0=none, 1=hard-snap) — Logic's Flex Pitch / a tuner. Unlike scaleLockNotes (integer hard-snap), it returns a fractional pitch so a partial correction keeps natural detune; reuses CLIP_SCALES. Unit-tested (nearest-tone snap, partial detune, no-op at 0, scale respected). |
| ACIDized tempo conform (stretch to project BPM) | ACID Pro / Groove Clips (loop-based) | ACID·Cakewalk·ACID Music Studio | PORTED | webui/grid/acid-loops.js (acidStretchRatio · acidClipDurationSec)an ACIDized loop carries its recording tempo + beat count and conforms to the project tempo: acidStretchRatio = loopBpm/projBpm (the source-duration multiplier, <1 compresses when the project is faster), and acidClipDurationSec = loopBeats·60/projBpm (a loop always spans its beat count, independent of its recording tempo). The stretch DSP itself is the JUCE stretch/repitch (render-verified). Unit-tested (compress/expand, beat-span duration, tempo-independence, degenerate). |
| ACIDized key conform (root-note transpose) | ACID Pro / Groove Clips (loop-based) | ACID·Cakewalk | PORTED | webui/grid/acid-loops.js (acidTranspose)a loop with a root note is pitch-shifted to the Project Key by (projKey − root) mod 12 semitones (up). Matches the documented ACID example exactly — roots A, B, C to project key D shift by 5, 3, 2 semitones. Unit-tested (the manual example, zero at unison, up-wrap). |
| Groove-Clip tile-to-fill (paint a loop across a region) | ACID Pro / Groove Clips (loop-based) | ACID·Cakewalk·FL | PORTED | webui/grid/acid-loops.js (acidTileToFill)painting a loop across a region tiles it: acidTileToFill returns the whole repeats + the leftover partial (in beats). Unit-tested (exact fill, partial remainder, sub-loop region, degenerate). |
| Choke / mute groups | Groove-box (Maschine · MPC · ReCycle) | Maschine·MPC·drum machines | PORTED | webui/grid/groovebox.js (applyChokeGroups)events in the same choke group cut each other — a closed hi-hat truncates the still-ringing open hi-hat to end exactly at the new onset (group via event.choke or a chokeOf(pitch) lookup); simultaneous onsets don't choke, and only notes actually still ringing are cut. Unit-tested (truncate ringing, other groups/ungrouped safe, simultaneous, chokeOf lookup, not-ringing skip). |
| Slice loop to pads (ReCycle / REX / MPC chop) | Groove-box (Maschine · MPC · ReCycle) | ReCycle·MPC·Maschine | PORTED | webui/grid/groovebox.js (sliceLoopToPads)split a loop into N equal segments mapped to sequential pads from a base MIDI note (36 = MPC A1); each pad triggers its slice { startBeat, lenBeats }. The transient-based variant is dynamicSplit (Reaper row); this is the equal/chop-to-pads form. Unit-tested (equal split + pad mapping, degenerate). |
| Velocity levels (MPC 16 Levels / fixed velocity) | Groove-box (Maschine · MPC · ReCycle) | MPC·Maschine | PORTED | webui/grid/groovebox.js (quantizeVelocityLevels)quantize a velocity to one of N evenly-spaced levels across 1..127 (levels=1 → fixed 127, MPC '16 Levels' uses 16). Unit-tested (4-level snap incl. endpoints + tie, fixed-127, 16-level grid). |
| Column interpolation (Interpolate) | Trackers (Renoise · FastTracker · ProTracker) | Renoise·Impulse Tracker | PORTED | webui/grid/tracker.js (interpolateColumn)fill the rows between two set rows with a linear ramp (Renoise/IT interpolate a volume/effect column), endpoints given in any order, integer-rounded (byte columns) or fractional. Unit-tested (ramp, reversed endpoints, fractional, single-row). |
| Note delay column (sub-row micro-timing) | Trackers (Renoise · FastTracker · ProTracker) | Renoise·ProTracker | PORTED | webui/grid/tracker.js (noteDelay)nudge a row event later within its row by delayTicks of the row's ticksPerRow, returning the fractional row position for sub-row scheduling (ProTracker EDx). Clamped to [row, row+1). Unit-tested (half-row nudge, clamp high/low, bad ticks). |
| Arpeggio effect (0xy) | Trackers (Renoise · FastTracker · ProTracker) | ProTracker·Renoise·FastTracker | PORTED | webui/grid/tracker.js (arpEffect)the classic 0xy arpeggio cycles the pitch every tick between base / base+x / base+y semitones (047 → a major triad), wrapping. Returns the semitone offset at a tick. Unit-tested (three-phase cycle + wrap). |
| Pattern order → timeline (order list) | Trackers (Renoise · FastTracker · ProTracker) | Renoise·FastTracker·ProTracker | PORTED | webui/grid/tracker.js (patternOrderToTimeline)lay an ORDER LIST of pattern indices onto absolute rows (fixed or per-pattern lengths), with the total song length — the tracker analog of the arranger's play-order chain (clip-seq.js CHAIN). Unit-tested (fixed length layout, per-pattern lengths, empty). |
| Chord voicing (chord → MIDI pitches) | Harmony / Chord Pads (Cubase · Logic · Scaler) | Cubase·Logic·Scaler | PORTED | webui/grid/harmony.js (voiceChord)stack a chord's tones into ascending MIDI pitches from a base octave (C→C E G, G7→G B D F), accepting a chord object or a symbol string. Reuses parseChordSymbol. Unit-tested (triads, seventh, garbage rejected). |
| Proximity voice-leading (adaptive voicing) | Harmony / Chord Pads (Cubase · Logic · Scaler) | Cubase·Scaler | PORTED | webui/grid/harmony.js (voiceLeadChord)Cubase Chord Pads' adaptive voicing: place each chord tone in the octave nearest a reference register (a center pitch or the mean of the previous voicing) so successive chords move smoothly with minimal register jumps. Distinct from followChordNotes (which transposes existing notes). Unit-tested (near-center voicing, register follows the reference, previous-voicing array). |
| Circle-of-fifths distance | Harmony / Chord Pads (Cubase · Logic · Scaler) | Cubase·Logic | PORTED | webui/grid/harmony.js (circleOfFifthsDistance)harmonic distance between two roots as steps around the circle of fifths (0 same, 1 a fifth/fourth, 6 tritone). Unit-tested (unison, fifth, fourth, tritone, two-fifths). |
| Chord Assistant (diatonic next-chord suggestion) | Harmony / Chord Pads (Cubase · Logic · Scaler) | Cubase·Scaler | PORTED | webui/grid/harmony.js (suggestNextChords)the diatonic triads of a major key ranked by circle-of-fifths closeness to the current chord's root (Cubase Chord Assistant proximity), carrying degree + quality (I maj … vii° dim). Unit-tested (proximity ranking + itself first, all seven, diatonic qualities). |
| Block instance (reusable content, placed + overridden) | Reason Blocks / DP Chunks (reusable blocks) | Reason·Digital Performer | PORTED | webui/grid/reason-blocks.js (blockInstanceEvents)realize a block placed at a bar with a per-instance override — shift events to absolute time, drop muted tracks, apply transpose (MIDI-clamped), or mute the whole instance. Unit-tested (absolute shift, transpose+track-mute, whole-instance mute). |
| Block order → timeline (edit once, reflect everywhere) | Reason Blocks / DP Chunks (reusable blocks) | Reason·Digital Performer | PORTED | webui/grid/reason-blocks.js (expandBlockOrder)flatten a sequence of block instances into a timeline, reading the block store LIVE so editing a block's content re-expands into ALL its instances (the defining reusable-block behaviour) — distinct from the tracker order-list (pattern indices, no shared content) and the CHAIN (section order). Unit-tested (flatten + length, shared-edit propagates to every instance, unknown skip, overrides). |
| Auto-place blocks back-to-back | Reason Blocks / DP Chunks (reusable blocks) | Reason | PORTED | webui/grid/reason-blocks.js (placeBlocksSequential)lay a bare block sequence out left-to-right, each starting where the previous ended, carrying per-entry overrides and skipping unknown blocks. Unit-tested (back-to-back placement, overrides + skip). |
| Euclidean rhythm (Bjorklund) | Algorithmic generators (Live 12 · Elektron · Mutable) | Ableton Live 12·Elektron·Mutable | PORTED | webui/grid/euclid.js (euclideanRhythm)distribute N pulses as evenly as possible across M steps via the true Bjorklund algorithm — canonical E(3,8)=x..x..x. (tresillo), E(5,8)=x.xx.xx. (cinquillo) — with a rotation, and always exactly N hits. Unit-tested (tresillo/cinquillo/classics, rotation, edges/clamp, exact pulse count for many N,k). |
| Pattern rotation | Algorithmic generators (Live 12 · Elektron · Mutable) | Elektron·Mutable·Live 12 | PORTED | webui/grid/euclid.js (rotatePattern)shift every hit n steps right (wrapping; negative = left) — the classic sequencer rotate that composes with the Euclidean generator. Unit-tested (right shift, full-wrap identity, left, empty). |
| Density fill (seeded random rhythm) | Algorithmic generators (Live 12 · Elektron · Mutable) | Ableton Live 12 | PORTED | webui/grid/euclid.js (densityFill)Live 12's Rhythm/Seed generator: each step is a hit with probability `density`, seeded so the pattern is reproducible. Unit-tested (extremes 0/1, seed-reproducible, statistical density over 1000 steps). |
| Hit positions (pattern → onsets) | Algorithmic generators (Live 12 · Elektron · Mutable) | — | PORTED | webui/grid/euclid.js (hitPositions)turn a boolean step pattern into the list of hit step indices — the bridge from a generated pattern to note onsets on the grid. Unit-tested (E(3,8)→[0,3,6], empty). |
| Arpeggiate (up/down/updown/converge/diverge/random) | Live 12 MIDI Transformations | Ableton Live 12·Logic·Cubase | PORTED | webui/grid/miditransform.js (arpeggiate)spread a chord into a step sequence, one note every `rate` steps, in the classic arp styles (up, down, updown, downup, converge, diverge, seeded random), each note gate·rate long. Distinct from the tracker 0xy arpeggio (per-tick pitch offset). Unit-tested (up cycle + timing/gate, down/updown/converge/diverge orderings, seeded random, empty). |
| Ornament (grace / trill / mordent) | Live 12 MIDI Transformations | Ableton Live 12·Logic | PORTED | webui/grid/miditransform.js (ornamentNotes)add ornaments: a grace note stealing a little of the note's start, a trill alternating with note+interval over the length, or a mordent three-note flick then hold. Unit-tested (grace insert+shorten, trill alternation, mordent flick+hold, rate-widened flick). |
| Time Warp (bend onsets with a curve) | Live 12 MIDI Transformations | Ableton Live 12 | PORTED | webui/grid/miditransform.js (timeWarpNotes)warp note onsets within the clip through curveShape (accelerate/decelerate/ease) so they crowd toward the start or end while the clip length is preserved — distinct from the tempo-map ramp (which changes the clock). Reuses curveShape. Unit-tested (curve bend fixing endpoints, identity at shape 0, no-clipLen copy). |
| Recombine (redistribute a property) | Live 12 MIDI Transformations | Ableton Live 12 | PORTED | webui/grid/miditransform.js (recombineNotes)shuffle one property (pitch / velocity / rhythm) among the notes with a seeded Fisher–Yates, leaving the others in place — Live 12's Recombine. Unit-tested (pitch shuffle keeps onsets + pitch set, velocity-only shuffle). |
| Pitch-bend conversion (semitone ↔ 14-bit) | Per-note MPE (Bitwig · Cubase · Logic · ROLI · Live 11+) | MPE·all | PORTED | webui/grid/mpe.js (pitchBendValue · pitchBendToSemitones)convert a per-note pitch glide in semitones to a 14-bit pitch-bend value (centre 8192) for the member channels' ± bend range (MPE default ±48), and back; clamped. Unit-tested (centre/full-up/full-down/half, clamp + guard, round-trip inverse). |
| Member-channel allocation (MPE zone) | Per-note MPE (Bitwig · Cubase · Logic · ROLI · Live 11+) | MPE·all | PORTED | webui/grid/mpe.js (mpeAllocateChannel)allocate the lowest free member channel for a new note within a zone (default the Lower Zone members 2..16, channel 1 = master), filling gaps and reporting -1 when the zone is full (caller may steal oldest). This is the per-NOTE channel-per-note MPE the arrangement lanes explicitly don't do. Unit-tested (lowest-free, gap fill, custom zone, full). |
| Per-note MIDI message stream | Per-note MPE (Bitwig · Cubase · Logic · ROLI · Live 11+) | MPE·all | PORTED | webui/grid/mpe.js (mpeNoteMessages)the ordered MIDI for one MPE note on its member channel: initial pitch-bend / timbre (CC74) / channel-pressure — only when the note carries them, so a plain note stays plain — then the Note-On; velocity clamped/defaulted. Unit-tested (plain vs expressive ordering, zero-bend omitted but zero-timbre kept, velocity clamp/default/null). |
| Cents ↔ ratio + N-EDO scales | Microtuning (Scala · MTS · Cubase · Logic · Bitwig · Surge) | all microtonal | PORTED | webui/grid/microtuning.js (centsToRatio · ratioToCents · edoScale)cents↔ratio conversion (octave=1200, fifth 3/2≈702) and an N-tone equal-temperament builder (12 standard, 19/31 microtonal). Unit-tested (octave/fifth conversions + inverse, 12-EDO degree table, 19-EDO step). |
| Scala .scl parser | Microtuning (Scala · MTS · Cubase · Logic · Bitwig · Surge) | Scala·Surge·all microtonal | PORTED | webui/grid/microtuning.js (parseScala)parse a Scala scale file — comments (!), description + note count header, then cents ('.') or ratio ('a/b'/integer) pitches; degree 0 (1/1) implicit, last pitch is the period. Unit-tested (a cents scale == edoScale(12), ratio pitches → fifth, malformed rejected). |
| Per-note frequency under a tuning | Microtuning (Scala · MTS · Cubase · Logic · Bitwig · Surge) | Cubase·Logic·Bitwig·Surge | PORTED | webui/grid/microtuning.js (tuningFreqHz)the Hz of a MIDI note under an octave/period-repeating tuning with a reference note+frequency (A4=440), each period adding its cents. Unit-tested (12-EDO A4/A5/C4/A3 reproduce standard pitches, empty tuning → reference). |
| MTS-over-MPE retuning | Microtuning (Scala · MTS · Cubase · Logic · Bitwig · Surge) | MTS-ESP·Surge·Bitwig | PORTED | webui/grid/microtuning.js (retuneSemitones · retunePitchBend)the semitone offset (and the composed 14-bit per-note pitch-bend, reusing mpe.js) to bend a 12-EDO note to its pitch under a tuning — play a microtonal scale on a 12-EDO instrument. Unit-tested (12-EDO retune is ~0, just major-third bent −13.7¢, retune-bend centres when 12-EDO). |
| LFO / step / random sources | Modulators (Bitwig · Ableton M4L · Reason CV) | Bitwig·Ableton·Reason | PORTED | webui/grid/modulators.js (modLfo · modStep · modRandom)instantaneous modulation sources: an LFO (sine/tri/saw/ramp/square, unipolar 0..1 or bipolar −1..1, phase-wrapped), a step-sequence modulator sampled at phase, and a sample-&-hold random modulator that holds a seeded value across a window. Unit-tested (LFO shapes + key phases + wrap, step sampling+wrap, S&H hold/change/seed). |
| Envelope follower | Modulators (Bitwig · Ableton M4L · Reason CV) | Bitwig·Ableton·Reason | PORTED | webui/grid/modulators.js (envFollow)a one-pole envelope-follower modulator: move toward the input by the attack coefficient when rising / the release coefficient when falling, fed back per sample. Unit-tested (rise/fall coefficients, instant attack, convergence over time). |
| Route + stack modulations onto a parameter | Modulators (Bitwig · Ableton M4L · Reason CV) | Bitwig | PORTED | webui/grid/modulators.js (applyModulation · sumModulations)route a source to a param (base + depth·mod, clamped to the param range, depth may invert), and STACK several modulators additively onto one target (Bitwig's modulation stacking). Distinct from a baked automation lane — this is the live modulation matrix. Unit-tested (route + clamp + custom range, additive stack + clamp, empty). |
| MIDI Clock (24 PPQN) | MIDI sync (Clock · SPP · MTC — every DAW) | all DAWs | PORTED | webui/grid/midisync.js (midiClockInterval · clockPulsesPerBar)the F8 clock interval in ms at a BPM (24 pulses per quarter note) and pulses-per-bar — drive or follow external gear. Unit-tested (120/60 BPM intervals, 96/72 pulses per bar). |
| Song Position Pointer (F2) | MIDI sync (Clock · SPP · MTC — every DAW) | all DAWs | PORTED | webui/grid/midisync.js (songPositionPointer · sppToSixteenths)encode a sixteenth-note position as the 14-bit SPP LSB/MSB pair (clamped 0..16383) and decode it back. Unit-tested (split incl. 200→{72,1}, clamp, round-trip inverse). |
| MTC quarter-frame + full-frame | MIDI sync (Clock · SPP · MTC — every DAW) | all DAWs·video | PORTED | webui/grid/midisync.js (mtcQuarterFrame · mtcQuarterFrames · mtcFullFrame · mtcRateCode)MIDI Time Code: the eight F1 quarter-frame messages streaming the low/high nibbles of frames/seconds/minutes/hours (hours-MSN carrying the 2-bit frame-rate code), and the full-frame SysEx (F0 7F 7F 01 01 …) for locates. Spec-faithful nibble encoding. Unit-tested (all 8 pieces for 01:02:03:04@30, status 0xF1, rate in piece 7, full-frame SysEx bytes, rate-code map). |
| 14-bit CC (MSB/LSB controller pair) | High-resolution MIDI (14-bit CC · NRPN · RPN) | all DAWs | PORTED | webui/grid/hires-cc.js (cc14ToBytes · bytesToCc14)a 14-bit continuous controller as its MSB on CC c and LSB on CC c+32, and the inverse — high-resolution automation. Unit-tested (split incl. 8256→{64,64}, 14-bit clamp, round-trip inverse). |
| NRPN (Non-Registered Parameter Number) | High-resolution MIDI (14-bit CC · NRPN · RPN) | all DAWs | PORTED | webui/grid/hires-cc.js (nrpnMessages)select a 14-bit parameter (CC99/98) then send 14-bit data (CC6/38) — the four CC messages in order. Unit-tested (param 1234 + value 8256 → the exact CC99/98/6/38 sequence). |
| RPN (Registered Parameter Number) + Null | High-resolution MIDI (14-bit CC · NRPN · RPN) | all DAWs | PORTED | webui/grid/hires-cc.js (rpnMessages · rpnParam · rpnNull)RPN parameter select via CC101/100 then CC6/38 data, the well-known RPN names (pitch-bend range / fine / coarse tune / tuning program+bank), and the RPN Null (CC101=127/CC100=127) deselect. Unit-tested (pitch-bend-range sequence, name map, null). |
| Bars:Beats:Ticks ↔ ticks | Transport & playback engine (every DAW) | all DAWs | PORTED | webui/grid/transport.js (ticksToBBT · bbtToTicks)convert an absolute tick position to 1-indexed bar/beat + 0-indexed tick and back, honouring the time-signature denominator (x/4 vs x/8 beat size) — the transport display's position math. Unit-tested (4/4 positions, 6/8 denominator, round-trip inverse). |
| Event chasing (held notes + CC state) | Transport & playback engine (every DAW) | all DAWs | PORTED | webui/grid/transport.js (chaseNotes · chaseCC)when playback starts mid-clip: retrigger notes held across the start point (onset-shifted to the start with their remaining length), and restore each controller's last value at/before the start (a filter sweep set earlier is correct). Core 'chase events' playback behaviour. Unit-tested (held-note retrigger vs ended/future, last-CC-per-controller incl. same-step tiebreak). |
| Note-overlap cleanup | Transport & playback engine (every DAW) | Logic·Cubase·FL | PORTED | webui/grid/transport.js (removeNoteOverlaps)trim overlapping SAME-PITCH notes so none overlap (a mono voice can't hold two of a pitch) — an earlier note shortened to the next same-pitch onset; different pitches independent. Distinct from force-legato (which extends). Unit-tested (same-pitch trim, other pitch untouched, abutting left alone). |
| SMF format 0 ↔ 1 conversion | Transport & playback engine (every DAW) | all DAWs | PORTED | webui/grid/export/smf-convert.js (mergeTracksToType0 · splitToType1ByChannel · smfFormatOf)convert between Standard MIDI File formats at the event level — merge N tracks into one tick-sorted stream (format 0, stable across equal ticks), and split a stream into a conductor track (meta events) + one track per channel (format 1); split→merge round-trips. Complements smf-io.js's parse/write. Unit-tested (merge sort + stability, conductor+per-channel split, round-trip, format detect). |
| Audio clip import + waveform | Audio clips (JUCE audio engine — phased build) | all | PORTED | webui/clip/clip-seq.js (importAudio) · webui/grid/grid-core.js (drawClipCells waveform)Phase 1 (webui, verified): decode an audio file → normalized peak columns + duration; kind:'audio' clip draws its waveform in the block; persisted in the project. |
| Audio clip playback (C++ processBlock) | Audio clips (JUCE audio engine — phased build) | all | PARTIAL | include/zpc/AudioClip.h · include/zpc/ClipAudio.h · tests/audio_clip_render_test.cppVoice path (AudioClipPlayer voice pool + lock-free FIFO), the clipAudio* native-fn hook contract, and the JS arrangement trigger/import/stop-all are all written and wired. Now OFFLINE-RENDER-VERIFIED headlessly (AudioClipRenderTest, under ctest): a real WAV is decoded through loadFile → trigger → process and the output is asserted to match the source sample-for-sample, non-silent, correct length, finite/bounded/click-free, mono fanning to L/R. PARTIAL: subjective audible sign-off through a compiled synth playing a device is the remaining human step — never marked ported on faith. |
| Audio fades / crossfades | Audio clips (JUCE audio engine — phased build) | all | PARTIAL | include/zpc/AudioClip.h (crossfadeTo) · tests/audio_clip_render_test.cpplinear fade in/out + equal-power (cos/sin) crossfade. Render-verified headlessly (AudioClipRenderTest): fade envelopes ramp exactly (per-sample vs reference, <1e-4), and a crossfade keeps summed power flat on the constant-power law (not the mid-dip a linear fade gives), measured with integer-cycle-orthogonal tones. PARTIAL: audible sign-off pending. |
| Audio slip-edit | Audio clips (JUCE audio engine — phased build) | ProTools | PARTIAL | include/zpc/AudioClip.h (AudioTriggerOpts::slipSec) · tests/audio_clip_render_test.cppcontent start-offset, composes through stretch. Render-verified headlessly: on a silence-then-tone clip the slipped voice starts on the tone while the unslipped one starts silent (>10× directional RMS shift). PARTIAL: audible sign-off pending. |
| Time-stretch / repitch | Audio clips (JUCE audio engine — phased build) | all | PARTIAL | include/zpc/AudioClip.h (AudioTriggerOpts::stretch/rate) · tests/audio_clip_render_test.cpprate repitch (resample) + pitch-preserving WSOLA stretch. Render-verified headlessly with objective Goertzel: repitch rate=2 makes 2·F0 dominate (octave up) and halves duration; WSOLA stretch=2 keeps F0 dominant with an absolute energy floor AND rejects an octave-down resample (F0/2 non-dominance) while doubling length. PARTIAL: audible sign-off pending. |
| Warp markers | Audio clips (JUCE audio engine — phased build) | Ableton | PARTIAL | include/zpc/AudioDsp.h (WarpMap) · include/zpc/AudioClip.h (AudioTriggerOpts::warp) · tests/audio_clip_render_test.cpppiecewise-linear invertible src↔arr time map, now CONSUMED by the voice (a warped voice reads its source position via WarpMap.arrToSrc per sample). Render-verified headlessly: a tone's onset lands at its MAPPED arrangement position (not its source position) and a half-speed warp region repitches the tone as the map dictates; a mutation that ignores the warp fails the assertions. PARTIAL: audible sign-off pending. |
| Audio comping / take lanes | Audio clips (JUCE audio engine — phased build) | Logic·ProTools·Cubase | PARTIAL | include/zpc/AudioDsp.h (CompLane) · tests/audio_clip_render_test.cppcomp/take SELECTION model + PLAYBACK render-verified headlessly: a CompLane drives which take sounds per segment (Goertzel confirms take A's frequency in its segment, take B's in the next, gap = silence). PARTIAL: the audio-input RECORDING half (capturing takes from a live device, punch/loop-record) needs hardware, and sample-accurate mid-voice take switching without host retrigger would need a comp-aware player mode; audible sign-off pending. |