P1c: microphone recording through the material pipeline

This commit is contained in:
Emil
2026-11-01 01:44:36 +03:00
parent 0acf11ccb0
commit 88663a384e
14 changed files with 421 additions and 18 deletions
+45
View File
@@ -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.