P1c: microphone recording through the material pipeline
This commit is contained in:
+45
@@ -98,3 +98,48 @@ Screenshots: `preview-p1b-quarry.png`, `preview-p1b-restored.png`.
|
||||
- Only the source bytes are archived; trimming/recording will add derived assets.
|
||||
- The engine is still the standalone daemon; the Tauri backend does not host it yet.
|
||||
- A failed autosave logs a warning and leaves the in-memory session running; the surface does not yet show a save error.
|
||||
|
||||
---
|
||||
|
||||
# P1c · recording
|
||||
|
||||
The quarry can now take a microphone take and turn it into material.
|
||||
|
||||
## Path
|
||||
|
||||
```
|
||||
record click
|
||||
→ getUserMedia({ mono, no AGC/NS/echo })
|
||||
→ AudioContext (requested 48 kHz) → AudioWorklet 'zhila-recorder'
|
||||
→ Float32 chunks on the main thread
|
||||
→ 16-bit PCM WAV encoder (in the surface)
|
||||
→ the existing binary import path with seal 'recorded'
|
||||
→ material decode + onset analysis + sixteen faces
|
||||
→ project asset + autosave
|
||||
```
|
||||
|
||||
The worklet copies each 128-frame render quantum; the main thread owns the growing chunk list so the audio thread never allocates the take. A mute GainNode keeps the input out of the speakers. The take name is `take-01.wav`, `take-02.wav`, …; the core name drops the extension. The recorder stops at 30 s; the user can stop earlier. Errors (permission denied, no device, worklet failure) surface under the quarry header.
|
||||
|
||||
The WAV is mono 16-bit PCM at the AudioContext rate (requested 48 kHz). The material crate already handles WAV; no daemon or protocol change was needed beyond `Seal::Recorded`.
|
||||
|
||||
## UI
|
||||
|
||||
- `record` in the quarry header and in the empty state: dot + label; `stop 0:12` while active with a pulsing dot.
|
||||
- `take a core` is disabled while recording; import is disabled while recording.
|
||||
- The take is imported with the recorded seal; the core strip and side facts show `recorded`.
|
||||
- The timer is in the button; no modal, no separate recorder panel.
|
||||
|
||||
## Verification
|
||||
|
||||
- `npm --prefix ui run record-smoke` launches Chromium with `--use-fake-ui-for-media-stream --use-fake-device-for-media-stream --use-file-for-fake-audio-capture=fixtures/clicks-01.wav`, records 2.3 s through the real UI/worklet/encoder, stops, waits for `take-01`, and checks 16 faces, the recorded seal, and the wire import.
|
||||
- The take is persisted in `~/.local/share/zhila/descent-04` (`core-4525165cd5.wav`, 16 faces, seal recorded) and shown by the state.
|
||||
- `./scripts/check.sh` remains green.
|
||||
|
||||
Screenshot: `preview-p1c-record.png`.
|
||||
|
||||
## Limits
|
||||
|
||||
- Mono, 16-bit, 30 s max, no monitor, no device picker, no gain control.
|
||||
- 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.
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
# ZHILA — план проекта
|
||||
|
||||
Черновик v1.1 · 1 ноября 2026
|
||||
Статус: **P0, P1a и P1b выполнены** (см. `P0.md`, `P1.md`). Демо `reference/demo/` — референс, не кодовая база.
|
||||
Статус: **P0, P1a, P1b и P1c выполнены** (см. `P0.md`, `P1.md`). Демо `reference/demo/` — референс, не кодовая база.
|
||||
|
||||
**Зафиксировано 1 ноября:** descent — основной вид; камень = паттерн; климат — на жилу (концепт погоды остаётся); платформа v1 — Linux; UI — Svelte 5. Журнал — §9.
|
||||
|
||||
|
||||
@@ -152,3 +152,7 @@ Events: `pattern_step`, `pattern_face`, `face_struck`.
|
||||
`State` adds `project_name` (string), `can_undo` and `can_redo` (bools). Commands `undo` and `redo` take no arguments; event `history { can_undo, can_redo }` is broadcast after them.
|
||||
|
||||
The project is loaded by the daemon from its `--project` folder and saved after every project command or import. The protocol only exposes the project name; the path, SQLite file and assets stay server-side. There is no explicit save command: autosave is the contract. The journal is persisted, but undo history is not reconstructed on load.
|
||||
|
||||
## 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.
|
||||
|
||||
Reference in New Issue
Block a user