feat(midi): strum chords with preserved note ends and undo (phase 99)

This commit is contained in:
Johannes Findeisen 2026-11-06 02:16:46 +01:00
commit bd0a63c06d
17 changed files with 172 additions and 5 deletions

View file

@ -82,3 +82,14 @@ adjacency, cross-track selections and MIDI clips reject without partial edits.
This is a linear tick-based crossfade using existing clip envelopes; it does
not move clips, create overlaps or offer equal-power curves. Discrete sample
endpoints retain the engine's existing one-sample boundary convention.
## Chord strumming
Select MIDI clips and use **Edit → MIDI tools → Strum chords...**. Enter spacing
in ticks (1–960) and direction (0 ascending, 1 descending). Notes sharing a source
onset and MIDI channel within each clip form a chord. Equal pitches use stable
note-ID order. Each successive note starts one spacing later, while its end,
pitch, velocity and channel remain unchanged. Single notes remain unchanged.
Any resulting zero/negative duration rejects the entire edit; Undo restores the
whole selection. This edits source notes, including notes hidden by clip trims.
It does not generate an arpeggiator or schedule live input.

View file

@ -2193,15 +2193,33 @@ Implemented: allocation-free C99 validation applies paired linear overlap fades
Spread simultaneous chord notes in pitch order with a user-selected tick spacing and direction, preserving original ends and rejecting source overflow atomically. Expose a musical editing command with undo.
### Tasks and acceptance criteria
- [ ] Implement the workflow with bounded validation, safe preparation and documented limits.
- [ ] Pass meaningful core and/or GUI checks, including error and undo behavior.
- [ ] Document results and commit this phase separately.
- [x] Implement the workflow with bounded validation, safe preparation and documented limits.
- [x] Pass meaningful core and/or GUI checks, including error and undo behavior.
- [x] Document results and commit this phase separately.
### Implementation status
Planned.
Implemented: transactional C99 chord strumming groups source onsets by clip/channel, orders by pitch with stable-ID ties, preserves original note ends and rejects invalid durations atomically. Core ascending/descending/channel/singleton/mixed-selection/rollback checks, allocation-failure injection and real GUI editing/undo passed. A bounded spacing/direction dialog exposes the operation; source notes hidden by trims remain editable.
---
## Integrated Validation for Phases 90–99
Completed on 2026-11-06 with `BUILD_DIR=build/audio-editor`:
warning-enabled `all test test-reliability`, `test-gui-creative`,
`test-gui-track-fx`, full `test-gui`, modern-plugin/instrument/LADSPA GUI fixtures,
and `test-gui-jack`. Clang static analysis and both staged install layouts passed,
including C/C++ pkg-config consumers. ASan/UBSan creative core, allocation-failure
and focused/full GUI checks passed using only the existing Fontconfig leak
suppression; Clang/FLTK retains its existing instrumentation warning.
Four additional real screenshots show the Dub Echo rack, actions menu, strum
dialog and piano-roll result. Earlier gallery captures remain labeled Phase 89.
See [creative workflows](CREATIVE_WORKFLOWS.md) and
[the gallery](../screenshots/README.md) for reproduction and limits. Chains and
A/B snapshots copy supported metadata, not opaque plugin states or DSP histories.
Crossfades use existing linear envelopes; strumming is a source-note edit.
Project format remains 17, readable from versions 1–17; no dependencies were added.
## Recommended Execution Order
Reorder the phases when the audit reveals a blocking dependency. Do not mark a phase complete merely because code exists: its acceptance criteria must be demonstrated by builds, tests, or documented manual verification.