docs: add nested CLAUDE.md tree
Root CLAUDE.md (overview, where-to-look, conventions) plus nested files for data_only_viz, oscope-of, launcher. sound_algo already had its own nested tree. Sized for the ~150-instruction budget: root 43 lines, each nested 43-52 lines, telegraphic style.
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
# AV-Live
|
||||
|
||||
Live coding audio-visual performance system : moteur SuperCollider, visualiseur openFrameworks piloté par un oscilloscope Hantek 6022BL, app menubar macOS qui orchestre le tout.
|
||||
|
||||
## Communication
|
||||
|
||||
Toujours répondre en français à l'utilisateur. Code, commentaires de code, commits et docs en anglais.
|
||||
|
||||
## Stack par sous-projet
|
||||
|
||||
| Sous-projet | Stack |
|
||||
|-------------|-------|
|
||||
| `sound_algo/` | SuperCollider (sclang + scsynth), 1099 SynthDefs, 345 tracks |
|
||||
| `oscope-of/` | openFrameworks C++, libusb (Hantek bulk), GLSL 150 GL 3.2 core |
|
||||
| `launcher/` | SwiftUI menubar app, Swift Package Manager |
|
||||
| `data_only_viz/` | Python 3.11+ via `uv`, Metal natif (pyobjc), multi-backends pose |
|
||||
| `web_realart/` | Node.js, Express, OSC bridge |
|
||||
|
||||
## Where to Look
|
||||
|
||||
| Tâche | Emplacement |
|
||||
|-------|-------------|
|
||||
| Ajouter / modifier un SynthDef, track, palette | `sound_algo/` (déjà documenté en nested) |
|
||||
| Toucher au visualiseur, shaders, FFT, Hantek | `oscope-of/` |
|
||||
| Modifier l'app menubar macOS | `launcher/` |
|
||||
| Détection pose / mesh / body tracking | `data_only_viz/` |
|
||||
| Bridge web / UI de live coding | `web_realart/` |
|
||||
| Plans / specs en cours | `docs/superpowers/plans/` |
|
||||
|
||||
## Conventions globales
|
||||
|
||||
- Python : **uv** systématiquement (jamais pip/poetry/conda directs).
|
||||
- Pas d'emojis dans code/docs/commits sauf demande explicite.
|
||||
- Commits : sujet ≤ 50 char, body ≤ 72 char/ligne, pas d'attribution AI, pas de `--no-verify`, pas d'underscore dans le scope (hooks enforcent).
|
||||
- `*.pt`, `*.ckpt`, `*.safetensors`, `*.mlpackage` exclus par `.gitignore` racine.
|
||||
|
||||
## Agent Workflow
|
||||
|
||||
Explore localise → librarian lit (>500 lignes) → tu raisonnes → general-purpose implémente → validator vérifie. Lance les tâches indépendantes en parallèle.
|
||||
|
||||
## Guidance imbriquée
|
||||
|
||||
Chaque sous-projet majeur a son propre `CLAUDE.md`. Claude charge automatiquement le plus proche du fichier édité (« closest wins »). N'ajouter ici que ce qui s'applique à TOUS les sous-projets.
|
||||
@@ -0,0 +1,52 @@
|
||||
# data_only_viz
|
||||
|
||||
Visualiseur natif Metal (pyobjc) pour le mode data-only d'AV-Live : capture caméra → détection pose multi-personne → tracker → rendu Metal → OSC out vers `oscope-of`.
|
||||
|
||||
## Environnement
|
||||
|
||||
```bash
|
||||
cd data_only_viz
|
||||
uv sync # base
|
||||
uv sync --extra pose # MediaPipe + YOLO + Ultralytics
|
||||
uv sync --extra nlf # Neural Localizer Fields (SMPL body mesh)
|
||||
uv sync --extra detrpose # DETRPose transformer (clone manuel — voir detrpose.py)
|
||||
uv run python -m data_only_viz.main # lancement standard
|
||||
```
|
||||
|
||||
Python **3.11+** requis. `pyproject.toml` est la source de vérité — ne jamais éditer `uv.lock` à la main.
|
||||
|
||||
## Backends pose disponibles
|
||||
|
||||
| Backend | Fichier | Statut |
|
||||
|---------|---------|--------|
|
||||
| MediaPipe Holistic | `holistic.py` | stable |
|
||||
| Ultralytics YOLOv8-pose | `pose.py` | stable, modèle `yolov8n-pose.pt` à la racine repo |
|
||||
| Apple Vision (Core ML) | `apple_vision_pose.py`, `coreml_pose.py` | macOS uniquement |
|
||||
| DETRPose | `detrpose.py` | clone manuel + checkpoint, voir docstring |
|
||||
| NLF (SMPL body mesh) | `nlf_worker.py` | TorchScript, **bloqué CPU/MPS** (NotImplementedError 2026-05-13), CUDA-only ; checkpoints via `scripts/setup_nlf.sh` |
|
||||
| Multi-HMR | `multi_hmr_scaffold.md` | scaffold seulement |
|
||||
| SMPLER-X / WHAM-TRAM | `*_scaffold.md` | scaffold seulement |
|
||||
|
||||
## Conventions
|
||||
|
||||
- État partagé multi-thread : `state.py` expose `State.lock()` — toujours mutationner sous lock.
|
||||
- Filtrage temporel : `euro_filter.py` (One Euro Filter) sur les keypoints avant tracker.
|
||||
- Association multi-personne : `tracker.py` IoU-based, `scipy.optimize.linear_sum_assignment`.
|
||||
- Shaders Metal dans `shaders/` (`.metal`), recompilés au runtime ; topologie mesh (SMPL faces) en binaire dans `mesh_topology.py`.
|
||||
- OSC out : `osc_listener.py` / `pose_bridge.py` — destination `oscope-of` sur `:57123`.
|
||||
|
||||
## Tests
|
||||
|
||||
```bash
|
||||
uv run pytest tests/ -v
|
||||
```
|
||||
|
||||
Tests TDD-first pour `nlf_worker.py` ; valider avant chaque commit qui touche un worker.
|
||||
|
||||
## Anti-patterns
|
||||
|
||||
- Ne pas charger un modèle ML sans guard `try/except ImportError` — les optional-extras peuvent manquer.
|
||||
- Ne pas committer `*.pt`, `*.ckpt`, `*.safetensors`, `*.mlpackage` (gitignore racine).
|
||||
- Ne pas appeler `state.persons_nlf = ...` hors `with state.lock():`.
|
||||
- Ne pas hardcoder le device (`cuda`/`mps`/`cpu`) : détecter via `torch.backends.mps.is_available()` puis fallback.
|
||||
- Pas de `print` dans la boucle de rendu — utiliser un logger conditionnel.
|
||||
@@ -0,0 +1,43 @@
|
||||
# launcher — AVLiveLauncher
|
||||
|
||||
App menubar macOS (SwiftUI, SwiftPM, macOS 11+) qui démarre/arrête `sclang+scsynth`, le serveur web et `oscope-of`, log les sorties, et expose un mode picker.
|
||||
|
||||
## Build
|
||||
|
||||
```bash
|
||||
cd launcher
|
||||
./build.sh # script standard
|
||||
# ou manuellement :
|
||||
swift build -c release
|
||||
.build/release/AVLiveLauncher
|
||||
```
|
||||
|
||||
Cible : **macOS 11+**, Swift 5.7+. Package Swift, pas de Xcode project requis.
|
||||
|
||||
## Modules
|
||||
|
||||
| Fichier | Rôle |
|
||||
|---------|------|
|
||||
| `AVLiveLauncherApp.swift` | `@main`, scene menubar, app lifecycle |
|
||||
| `MenuBarContent.swift` | UI du menu (start/stop, état des process) |
|
||||
| `ModePickerWindow.swift` | Fenêtre picker de mode (data-only vs full vs ...) |
|
||||
| `ProcessManager.swift` | Spawn / kill / monitor des process enfants |
|
||||
| `OSCSender.swift` | Envoi OSC (typiquement vers `:57121` sclang, `:57123` oscope) |
|
||||
| `LogView.swift` | UI live des logs stdout/stderr des process |
|
||||
| `AV-Live-Body/` | Ressources / modèles annexes (body mesh assets) |
|
||||
|
||||
## Conventions
|
||||
|
||||
- Toute opération asynchrone : `Task { @MainActor in ... }` pour UI updates.
|
||||
- Pas de bloc `DispatchQueue.main.sync` (deadlock garanti depuis MainActor).
|
||||
- `ProcessManager` est `@MainActor` — interactions process via async/await, jamais `Process.waitUntilExit()` bloquant en main.
|
||||
- Chemins absolus vers les binaires (sclang, node, oscope-of) résolus une fois au startup et stockés ; ne pas redécouvrir à chaque démarrage.
|
||||
- Logs ring-buffer borné (pas de croissance illimitée dans `LogView`).
|
||||
|
||||
## Anti-patterns
|
||||
|
||||
- Ne pas committer `build/` ni `.build/`.
|
||||
- Ne pas hardcoder un chemin utilisateur (`/Users/electron/...`) — passer par `FileManager` + chemins relatifs au repo ou bookmarks.
|
||||
- Ne pas mélanger `Process.terminate()` et `kill -9` sans escalade (SIGTERM → wait → SIGKILL).
|
||||
- Pas d'AppKit `NSApp.terminate` direct depuis un closure background — toujours hop sur MainActor.
|
||||
- Ne pas dépendre d'un Xcode project : le SwiftPM `Package.swift` est la source de vérité.
|
||||
@@ -0,0 +1,43 @@
|
||||
# oscope-of
|
||||
|
||||
Visualiseur openFrameworks C++ : capture Hantek 6022BL via libusb → FFT 2048 → 41 backgrounds + 14 OS pixel-art + 10 scrollers + chaîne post-FX GLSL.
|
||||
|
||||
## Build
|
||||
|
||||
```bash
|
||||
cd oscope-of
|
||||
make # debug
|
||||
make Release # release
|
||||
make RunRelease # lance bin/oscope-of (Release)
|
||||
```
|
||||
|
||||
Dépendances oF dans `addons.make`. Cible macOS principale (Hantek via libusb bulk transfers).
|
||||
|
||||
## Architecture
|
||||
|
||||
| Composant | Fichier |
|
||||
|-----------|---------|
|
||||
| Capture USB Hantek (1-48 MS/s, 2 ch 8-bit) | `HantekDevice.{h,cpp}` |
|
||||
| Downsampling + FFT 2048 bandes bass/mid/treble/kick/snare | `AudioAnalyzer.{h,cpp}`, `FFT.{h,cpp}` |
|
||||
| Données scope partagées | `ScopeData.h` |
|
||||
| 41 backgrounds + 5 OS shaders + 14 logos + scrollers | `visualizers/` |
|
||||
| Chaîne post-FX (ACES, bloom, chroma, scanlines, glitch...) | `PostFx.{h,cpp}` |
|
||||
| Demo FX (copper bars, sine scroller, bobs) | `DemoFx.{h,cpp}` |
|
||||
| OSC reçu depuis sound_algo (`:57123`) + envoyé | `OscClient.{h,cpp}` |
|
||||
| App lifecycle | `ofApp.{h,cpp}`, `main.cpp` |
|
||||
|
||||
## Conventions
|
||||
|
||||
- **GLSL 150 GL 3.2 core** uniquement — pas de GL 2.1 legacy. Shaders en `bin/data/shaders/`.
|
||||
- Pas d'allocations dans `update()` / `draw()` — buffers FFT préalloués.
|
||||
- Hantek bulk transfer : timeout court, fallback gracieux si scope absent (mode démo).
|
||||
- Les 15 demoparties touchent un état global `currentDemo` dans `ofApp` — toujours mettre à jour les bindings clavier (`keyPressed`) AZERTY (`&é"'(§è!` → `1-8`).
|
||||
- `greetings.txt` (sine scroller) chargé depuis `bin/data/` au startup — éviter relectures.
|
||||
|
||||
## Anti-patterns
|
||||
|
||||
- Ne pas appeler `glDrawArrays` sans bind VAO préalable (GL 3.2 core l'exige).
|
||||
- Ne pas faire `new` dans la hot loop — utiliser `ofVbo` / `ofFbo` membres.
|
||||
- Ne pas faire d'I/O fichier dans `draw()`.
|
||||
- Ne pas committer `bin/oscope-of*` (binaires) ni `bin/data/*.mov` (gros).
|
||||
- Ne pas ajouter de dépendance non-headless sans l'inscrire dans `addons.make`.
|
||||
Reference in New Issue
Block a user