Phase 22: add non-destructive audio splitting, clip gain and fades, and cached waveforms
This commit is contained in:
parent
73fc5eea8d
commit
01d8c1d661
23 changed files with 650 additions and 18 deletions
|
|
@ -137,3 +137,82 @@ Recordings remain RIFF mono float32, bounded to roughly 4 GiB; the preloaded
|
|||
player still limits each asset to 16M frames. Longer valid takes may require
|
||||
external splitting before import. No directory fsync/power-loss guarantee is
|
||||
claimed. WAV destinations are chosen explicitly by the user.
|
||||
|
||||
## Phase 22: non-destructive clip editing
|
||||
|
||||
Move clips by dragging their body; drag the left/right edge to trim within the
|
||||
existing source length. Ctrl+D duplicates adjacent to the selected clip. Delete
|
||||
removes the reference. With an audio clip selected, click the ruler while stopped
|
||||
to position the cursor strictly inside it, then choose **Edit / Split audio at
|
||||
cursor**, press S with timeline focus, or use the clip context menu. The right
|
||||
piece becomes selected. The four-pixel minimum draw width is also selectable for
|
||||
very short clips; zoom in for precise edge gestures.
|
||||
|
||||
**Edit / Audio clip gain and fades** (A with timeline focus, also in the context
|
||||
menu) takes three numbers: linear gain 0..4, fade-in ticks, fade-out ticks.
|
||||
Defaults are `1 0 0`; 0 fade disables that explicit fade. Each duration can be up
|
||||
to the original source length, even after trimming; overlapping long fades
|
||||
attenuate a short clip without extending it. MIDI clips reject these operations;
|
||||
silent metadata regions support them for later audio relinking.
|
||||
|
||||
These operations are one undo step each, stop playback before model edits and
|
||||
are refused while recording. Main Edit / Undo and Redo restore the model and
|
||||
prepare its matching stopped engine plan; Play uses the latest settings.
|
||||
Splitting and duplication allocate metadata IDs only: no media copies. All
|
||||
operations preserve original WAV bytes, including Delete and undoing recording.
|
||||
No destructive audio processing or file deletion command is supplied.
|
||||
|
||||
A split retains the original source length/path/name/gain on both pieces. Its
|
||||
right offset advances by the left length, keeping trims reversible within the
|
||||
same source. Left keeps its ID and fade-in; right gets a fresh ID and fade-out.
|
||||
Inner explicit fades are cleared. Gain/fades are retained on duplication.
|
||||
Moving does not alter offsets; trimming changes only timeline/source bounds and
|
||||
makes explicit fades follow the new audible boundaries.
|
||||
|
||||
The renderer maps tick boundaries by the existing absolute floor conversion,
|
||||
linearly resamples the source and never reads beyond its samples. Its audible
|
||||
end is the earlier of the trimmed end and actual WAV end (imports round metadata
|
||||
length up to a tick). A fade uses `age / fade_in_frames` at the start and
|
||||
`remaining_frames / fade_out_frames` at the end, capped at 1; overlapping fades
|
||||
use the smaller value. The first/last audible samples are zero when their
|
||||
respective fade has a positive sample duration. Durations rounding to zero
|
||||
samples are disabled. A one-sample clip with any active fade is silent. Explicit
|
||||
fade gain multiplies the existing optional safety envelope, then clip gain,
|
||||
then track gain/pan/automation. No limiter is added; gains/overlaps may clip.
|
||||
|
||||
The GUI retains its 5 ms boundary safety fades, including new split edges, so
|
||||
cuts can introduce a brief dip rather than an abrupt discontinuity. The raw C
|
||||
plan still defaults to zero safety fade for exact-sample/offline consumers;
|
||||
callers requesting raw cuts accept possible clicks. Tick quantization can place
|
||||
an edit up to one output sample away from a separately rounded boundary; this
|
||||
is not sample-resolution audio editing. Manual listening remains pending.
|
||||
Time-stretching, independent pitch shifting and crossfade tools are future work;
|
||||
no suitable algorithm/quality target or new dependency has been selected.
|
||||
|
||||
### Cached waveform display
|
||||
|
||||
Timeline audio clips show mono min/max peaks from an immutable C summary,
|
||||
shared by reference path across split/duplicated clips. Up to 64 paths each
|
||||
cache at most 1024 bins (fewer for short files). It uses playback's WAV parser,
|
||||
downmix and file/frame bounds; creation temporarily loads one WAV then frees
|
||||
its sample storage. Bins cover every source sample, including a final partial
|
||||
bin. The display follows source offsets and current tempo; it shows **raw source
|
||||
peaks before clip/track gain and fades**, clamped visually to +/-1. It is an
|
||||
arrangement aid, not a sample editor or loudness meter.
|
||||
|
||||
Loading/rebuilding is synchronous on the GUI/control thread during project
|
||||
binding or edits that introduce media paths. Large files/slow disks can delay
|
||||
that UI operation. Draw/redraw, scrolling and playback never load a WAV or build
|
||||
peaks; the audio callback does not use this cache at all. Missing/invalid assets
|
||||
show no waveform and keep the existing playback issue reporting. Failures are
|
||||
cached, removed paths are evicted, and Open rebuilds caches, including changed
|
||||
external files. No persistent disk cache, file watcher or background loader is
|
||||
claimed. Source files should remain unchanged during a session; reopen after
|
||||
external replacement. Cache allocation failure omits previews without changing
|
||||
music metadata.
|
||||
|
||||
`make test-audio-editing` verifies exact split/gain/fade playback, odd blocks,
|
||||
seeks, shortened media tails, one-frame files, source/project limits, capacity
|
||||
rollback, duplication/fade inheritance, persistence/invalid metadata, undo, peak
|
||||
bins after source removal and byte-identical source preservation. GUI tests
|
||||
cover short-clip selection, shared previews, split/duplicate/delete and undo.
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
zoom/selection and graph positions are session UI state. Undo retains 32 edits
|
||||
plus baseline; allocation failures are reported, not silently hidden. Media is
|
||||
never removed by undo/delete. Broad screen-reader/accessibility testing is pending.
|
||||
- Format v7 reads v1–v6 and uses relative local media references. External absolute
|
||||
- Format v8 reads v1–v7 and uses relative local media references. External absolute
|
||||
media/module paths need manual repair after relocation. Saving does not bundle
|
||||
media; missing media stays referenced, missing plugins reject GUI installation.
|
||||
Unknown data is rejected rather than stripped. Post-rename directory-sync errors
|
||||
|
|
@ -33,3 +33,8 @@
|
|||
|
||||
See ROADMAP.md, AUDIO_QUALITY.md, CONTROL.md, WORKFLOW.md, PROJECT_FORMAT.md,
|
||||
PERFORMANCE.md, PLUGIN_HOSTING.md and RECOVERY.md for tested contracts/evidence.
|
||||
|
||||
- Waveform previews load synchronously on the control thread and cache at most
|
||||
64 paths/1024 bins each. Reopen after external media replacement. Audio cuts
|
||||
use tick resolution; GUI safety fades can create a short dip at split edges.
|
||||
Time stretching, independent pitch shifting and crossfades are deferred.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# Project format v7 (reads v1–v6)
|
||||
# Project format v8 (reads v1–v7)
|
||||
|
||||
Phases 5–15 use a bounded text format implemented in C99 without a parser library.
|
||||
The extension is `.xtc`. File operations run exclusively on the control thread.
|
||||
|
|
@ -151,7 +151,7 @@ discrete-mode compatibility are checked on control-thread compilation. Versions
|
|||
|
||||
## Phase 18: version 7 and project folders
|
||||
|
||||
Current writer emits v7; readers migrate v1–v6. Record ordering and field bounds
|
||||
Phase 18 introduced v7; its readers migrated v1–v6. Record ordering and field bounds
|
||||
are otherwise unchanged from v6. v7 ASSET may contain a relative path, interpreted
|
||||
against the actual containing directory of the named project file (resolved on
|
||||
the control thread), never the launch working directory. Opening a symlink to a project uses the
|
||||
|
|
@ -189,3 +189,29 @@ truncation and deterministic byte mutations, malformed plugin metadata, interrup
|
|||
writers and write-limit failures. ASan/UBSan/static analysis additionally audit the
|
||||
bounded parser. This is regression/fault-injection coverage, not exhaustive fuzzing
|
||||
or a claim of power-cut qualification.
|
||||
|
||||
## Phase 22: version 8 audio clip settings
|
||||
|
||||
Current writer emits v8 and reads v1–v7 with unity clip gain and no explicit
|
||||
clip fades. After **every** clip's `MIDI` record (including silent and MIDI
|
||||
clips), v8 requires:
|
||||
|
||||
```text
|
||||
AUDIO gain_float32_hex_bits fade_in_ticks fade_out_ticks
|
||||
```
|
||||
|
||||
Gain is finite, linear and within 0..4. Fade durations are unsigned decimal,
|
||||
0..source_length_tick; zero disables that explicit fade. MIDI clips require
|
||||
gain exactly 1 and both fades zero. Invalid or missing AUDIO records reject the
|
||||
whole candidate. All v7 media-folder rules and atomic-save guarantees remain.
|
||||
Older applications reject v8 rather than silently stripping clip settings.
|
||||
Rebuild C/C++ consumers against the extended `xtc_clip_info` public struct;
|
||||
this development release does not promise an unchanged struct binary layout.
|
||||
|
||||
Fades follow the audible trimmed clip boundaries, in current-tempo ticks, with
|
||||
sample endpoints defined in AUDIO_FILES.md. Duplicating retains settings and
|
||||
source references; splitting keeps the original ID on the left, gives the right
|
||||
a fresh ID/source offset, retains outer explicit fades and clears inner ones.
|
||||
No waveform cache or source audio is serialized. Checked-in v1–v7 migrations,
|
||||
v8 exact roundtrips, malformed new metadata and byte-mutation tests cover the
|
||||
format change (`make test test-portability test-audio-editing`).
|
||||
|
|
|
|||
|
|
@ -516,6 +516,23 @@ Provide focused, non-destructive audio editing tools for arranging and preparing
|
|||
- Clip boundaries do not produce unintended clicks from invalid offsets or discontinuities.
|
||||
- Editing and waveform generation never perform blocking work in the real-time audio callback.
|
||||
|
||||
Implemented: transactional audio/silent-clip splitting with stable IDs and source
|
||||
offsets; persisted linear clip gain and explicit in/out fades in v8 (v1–v7 migrate
|
||||
to unity/no explicit fades); undoable sequencer menu/context/keyboard controls;
|
||||
immutable bounded source-peak summaries shared across clips and drawn from
|
||||
cached memory. Existing move/trim/duplicate/delete remain supported; very short
|
||||
clip hit testing now matches drawing. See AUDIO_FILES.md and PROJECT_FORMAT.md.
|
||||
Stretch/pitch processing and crossfades remain future work; waveform loading is
|
||||
synchronous on the control thread, and physical listening remains pending.
|
||||
|
||||
Acceptance evidence:
|
||||
- [x] Core/GUI regressions cover split/duplicate/delete and snapshot undo.
|
||||
- [x] Exact byte comparison verifies source files survive all metadata edits.
|
||||
- [x] Boundary tests cover invalid offsets, short tails, one-frame media, explicit
|
||||
fade endpoints, gain, block partitions, seeks and capacity rollback.
|
||||
- [x] Waveform construction stays on control-thread paths; redraw reads cached
|
||||
peaks and audio rendering retains immutable/preloaded callback storage.
|
||||
|
||||
## Phase 23 — Modular Workflow and Routing Refinement
|
||||
|
||||
### Goal
|
||||
|
|
|
|||
|
|
@ -105,3 +105,14 @@ Click selects a single note; Ctrl+A selects all filtered notes. Ctrl+D repeats
|
|||
that selection at a chosen spacing within the existing clip source. Up/Down
|
||||
transposes by a semitone. Commands are undoable through the main Edit menu.
|
||||
See [MIDI.md](MIDI.md#phase-21-composition-commands) for shortcuts, timing and limits.
|
||||
|
||||
## Audio clip tools
|
||||
|
||||
Select an audio clip, click the ruler at the desired cut while stopped, then
|
||||
choose Edit / Split audio at cursor (S with timeline focus). Ctrl+D duplicates;
|
||||
Delete removes the clip reference. Drag the body to move and edges to trim.
|
||||
Edit / Audio clip gain and fades (A) sets linear gain and fade durations in ticks.
|
||||
All are undoable and preserve the WAV file. Waveforms show cached raw source
|
||||
peaks, before gain/fades; large media can take time to load on Open/import.
|
||||
See [AUDIO_FILES.md](AUDIO_FILES.md#phase-22-non-destructive-clip-editing) for
|
||||
boundary behavior, preview limits and the deferred stretch/pitch tools.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue