# Prompt #4 — D4 Audio-in (Micro / VAD / RMS)

**Rôle :**
Tu es _Développeur Audio-in_ du projet **Skull Pi**. Tu livres un service Python (`svc-audioin`) qui capture le signal micro (HAT ReSpeaker 2-Mic I²S), calcule en temps réel l’énergie RMS et un **VAD** (Voice Activity Detection), puis publie ces mesures sur MQTT. Langue : FR. Cible : Raspberry Pi Zero 2 W.

**Contexte & contraintes :**

- Dossier : `/opt/Skull/apps/audioin`.
- Exécution : `python -m audioin.main`.
- Bus : MQTT local `127.0.0.1:1883`.
- Micro : ReSpeaker 2-Mic Pi HAT, entrée I²S (driver ALSA).
- Traitement : RMS glissant + VAD (seuil énergie + durée).
- Paramètres configurables : `threshold`, `attack_ms`, `release_ms`, `eos_ms`.
- Perf : temps de latence < 50 ms/frame.

---

## Objectif fonctionnel

1. Capturer audio brut micro en continu (16 kHz mono, 16 bits).
2. Calculer RMS par fenêtres 20 ms (320 samples).
3. Déterminer activité vocale (VAD) :

   - **active = true** si RMS > seuil pendant ≥ `attack_ms`.
   - **active = false** si RMS < seuil pendant ≥ `release_ms`.
   - Détection fin de parole : `eos_ms` (silence prolongé).

4. Publier `audio/vad` et `audio/rms`.
5. Publier capabilities retained.
6. Paramètres ajustables via MQTT config.

---

## Spécification MQTT

### Sorties

- `audio/rms` (20 ms)

  ```json
  { "ts_ms": 0, "rms": 0.27 }
  ```

- `audio/vad`

  ```json
  { "ts_ms": 0, "active": true, "rms": 0.41 }
  ```

- `audio/capabilities` (retained)

  ```json
  { "mic": "respeaker-2mic", "rate": 16000, "vad": true, "channels": 1 }
  ```

### Entrées (config)

- `audio/vad/config`

  ```json
  { "threshold": 0.3, "attack_ms": 80, "release_ms": 200, "eos_ms": 800 }
  ```

---

## Implémentation attendue

1. **Capture micro**

   - Backend ALSA (ex. `sounddevice` ou `pyaudio`).
   - Frame size = 320 samples (20 ms).

2. **RMS**

   - RMS normalisé sur \[0..1].
   - Publier chaque frame sur `audio/rms`.

3. **VAD**

   - État machine `idle|active|release`.
   - Attack = seuil franchi x ms → active.
   - Release = sous seuil x ms → inactive.
   - EOS = silence prolongé → signaler fin segment (champ optionnel `end_of_speech:true`).

4. **Config dynamique**

   - Souscrit `audio/vad/config` (retained).
   - Applique immédiatement nouveaux seuils.

5. **Logs**

   - `/opt/Skull/logs/audioin.log`, JSON lignes.
   - Inclure RMS moyenne, ratio frames actives.

---

## Déploiement / systemd

- Service `skull-audioin.service`.
- Wrapper `/opt/Skull/bin/skull-audioin.sh` :

  ```bash
  #!/usr/bin/env bash
  set -euo pipefail
  source /opt/Skull/venv/bin/activate
  exec python -m audioin.main
  ```

---

## Livrables

- Code Python type-hinté, `ruff` + `mypy` clean.
- Tests unitaires avec fichiers WAV simulés (sine, bruit, voix).
- `README.md` (config seuils, ex. MQTT publish).

---

## Critères d’acceptation

- RMS publié toutes les 20 ms ± 5 ms.
- VAD bascule active/inactive correctement avec latence < 100 ms.
- `end_of_speech` publié après silence ≥ `eos_ms`.
- Config retenue appliquée à chaud.
- `audio/capabilities` retained correct.

---

## Plan de tests unitaires

1. **RMS constant**

   - Input sine 1 kHz à amplitude fixe → RMS stable ±0.01.

2. **VAD seuil simple**

   - Entrée RMS < threshold → `active=false`.
   - Entrée RMS > threshold → `active=true` après `attack_ms`.

3. **Release**

   - Descente RMS sous seuil → retour `active=false` après `release_ms`.

4. **EOS**

   - Silence prolongé → publication `end_of_speech:true`.

5. **Config dynamique**

   - Publier nouveau `threshold` → VAD réagit immédiatement.

6. **Capabilities retained**

   - Restart service → vérifier `audio/capabilities` dispo.

---

## Test manuel rapide

1. Lancer service :

   ```
   mosquitto_sub -t 'audio/#' -v
   ```

2. Parler dans le micro → voir `audio/vad.active=true`.
3. Rester silencieux → `audio/vad.active=false`, puis `end_of_speech`.
4. Jouer un son continu (ex. `aplay sine.wav`) → RMS constant.
5. Modifier seuil en live :

   ```
   mosquitto_pub -t audio/vad/config -m '{"threshold":0.1}'
   ```

   → VAD devient plus sensible.

---

**À livrer** : MR “D4 Audio-in — VAD+RMS micro” avec code, tests, service, README.
