P1d: manual face cuts and trim in the quarry
This commit is contained in:
+33
@@ -143,3 +143,36 @@ Screenshot: `preview-p1c-record.png`.
|
||||
- WebKitGTK/Tauri microphone support is untested; the Tauri binary also embeds an older surface build and must be rebuilt to see the record button.
|
||||
- No trim, fade or manual loop points yet; the take is cut by the automatic seams.
|
||||
- The take is stored as the encoded WAV, not the float PCM; trimming will later add derived assets.
|
||||
|
||||
---
|
||||
|
||||
# P1d · manual faces and trim
|
||||
|
||||
The waveform is now an editor. A core's sixteen faces are seventeen contiguous boundaries; dragging any seam updates the core.
|
||||
|
||||
## Backend
|
||||
|
||||
- `Core::set_face_boundaries(&[f32])` validates seventeen strictly ascending cuts inside the core, recomputes each face's RMS from the source samples and reranks the faces. The source bytes and the waveform peaks are untouched.
|
||||
- `Core::face_boundaries()` / `summary_boundaries()` expose the cuts.
|
||||
- `Command::SetCoreFaces { core, boundaries }`, event `CoreFaces { core: CoreSummary }`. The core rejects unordered/out-of-range cuts with `InvalidFaces`; a no-op does not journal.
|
||||
- Face edits are project edits: they journal, autosave and push the undo snapshot. `ProjectEdit` now snapshots every core's boundaries as well as bpm/gains/pattern, so undo restores cuts and trim. The edit remains valid when the pattern references the same face indices.
|
||||
- The store gained a `faces` JSON column on `cores` (migrated with `ALTER TABLE`); it saves the boundaries and applies them after re-importing the asset on load. Invalid stored cuts warn and fall back to the analysis.
|
||||
|
||||
## Surface
|
||||
|
||||
- The waveform draws the seventeen seams; the outer seams are the trim, the inner are cuts. Drag with the pointer; the neighboring seams constrain the move (20 ms minimum); on release the command is sent.
|
||||
- The side facts show the current `trim`; the selected face keeps its shade and label.
|
||||
- The hint says "drag a seam to cut · outer seams trim".
|
||||
|
||||
## Verification
|
||||
|
||||
- `cargo test --workspace`: 13 core tests (manual faces, undo, invalid cuts), 1 store test with a manual face across save/load.
|
||||
- `node scripts/persistence-smoke.mjs`: imports, cuts face 8 by 20 ms, restarts the daemon and verifies the loaded face edge and trim.
|
||||
- `npm --prefix ui run faces-smoke`: drags the left outer seam in Chromium; checks the trim text, the `cut` wire command and the enabled undo; writes `preview-p1d-faces.png`.
|
||||
- The default project now carries the cut `clicks-01` core.
|
||||
|
||||
## Limits
|
||||
|
||||
- Seventeen contiguous cuts only: no zoom, fade, loop points or per-face gain.
|
||||
- The trim is the outer boundaries of the sixteen faces; the original asset is not rewritten.
|
||||
- Cut history survives the session but not yet a reload (the next slice).
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
# ZHILA — план проекта
|
||||
|
||||
Черновик v1.1 · 1 ноября 2026
|
||||
Статус: **P0, P1a, P1b и P1c выполнены** (см. `P0.md`, `P1.md`). Демо `reference/demo/` — референс, не кодовая база.
|
||||
Статус: **P0, P1a, P1b, P1c и P1d выполнены** (см. `P0.md`, `P1.md`). Демо `reference/demo/` — референс, не кодовая база.
|
||||
|
||||
**Зафиксировано 1 ноября:** descent — основной вид; камень = паттерн; климат — на жилу (концепт погоды остаётся); платформа v1 — Linux; UI — Svelte 5. Журнал — §9.
|
||||
|
||||
|
||||
@@ -156,3 +156,7 @@ The project is loaded by the daemon from its `--project` folder and saved after
|
||||
## P1c addition
|
||||
|
||||
`Seal` gains `recorded`. Recording introduces no new wire messages: the surface encodes a WAV and uses the existing `import_core` header + binary payload. The recorded seal is persisted with the core row and is visible in the snapshot.
|
||||
|
||||
## P1d additions
|
||||
|
||||
`Command::set_core_faces` takes `{ core, boundaries: [f32; 17] }` (seconds, strictly ascending). The daemon answers with the state and broadcasts `core_faces { core: CoreSummary }`. The core rejects unordered or out-of-range boundaries. Boundaries are persisted in the project's `cores.faces` column and applied after the asset is decoded again on load; the source bytes and peaks stay unchanged.
|
||||
|
||||
Reference in New Issue
Block a user