first commit

This commit is contained in:
2025-06-13 18:10:27 +02:00
commit e2f8bba35e
21 changed files with 2773 additions and 0 deletions

105
readme_audio.md Normal file
View File

@@ -0,0 +1,105 @@
# Audio Capture & Processing — Architecture Notes
Ce document résume les décisions techniques et bonnes pratiques concernant la capture, l'encodage, et la transmission de la voix en temps réel dans un logiciel de type Discord/TeamSpeak, basé sur `cpal` (Rust) et `Opus`.
---
## 🎤 Capture audio avec `cpal`
### ✅ Bonnes pratiques
- Utiliser `cpal` en **mode callback** pour une capture audio fiable et efficace.
- **Ne jamais traiter** laudio directement dans le callback.
- Le callback doit être **minimaliste** : uniquement pousser les échantillons dans un buffer partagé/thread-safe.
### ❌ Mauvaises pratiques
- Encoder dans le callback → risque de **décrochage audio**.
- Loguer ou dormir dans le callback → **clics, perte de données**.
---
## 🎯 Taille des frames : 960 *samples*, pas 960 *ms*
- Pour un encodage **Opus en 20 ms à 48 kHz mono**, il faut **960 samples par frame**.
- Les chunks reçus de CPAL ne garantissent **jamais** dêtre exactement de cette taille.
---
## 🧱 Bufferisation : découpage rigide
- Mettre en place un **buffer circulaire** (ex : `VecDeque<i16>`) pour accumuler les samples reçus.
- Dès que `buffer.len() >= 960` :
- Extraire les 960 premiers samples,
- Encoder via Opus,
- Transmettre immédiatement.
### Pourquoi ne **pas** compléter avec des zéros ?
- Cela introduit des **artefacts audio**,
- L'encodeur Opus sattend à des données audio **continues et naturelles**.
---
## ⏱️ Pas de timer à 20ms
- Ne jamais baser lenvoi des paquets audio sur une **horloge ou un cycle fixe**.
- Lencodage doit être déclenché **uniquement** par la disponibilité dune frame complète.
---
## 🧵 Architecture multithread recommandée
```
[ CPAL Callback ]
[ Channel / Ring Buffer ]
[ Encode Thread (Opus) ]
[ Network Sender (UDP) ]
```
- Le callback ne fait que `send(samples)` dans un channel rapide.
- L'encodage Opus est fait dans un thread séparé dès qu'une frame de 960 samples est disponible.
---
## 🔄 Communication entre threads
### Option 1 Crossbeam channel (recommandé au départ)
```rust
use crossbeam_channel::{bounded, Receiver, Sender};
```
- Solide, rapide, facile à intégrer.
- Peut être remplacé plus tard si besoin de plus de performance.
### Option 2 `ringbuf` (optimisé audio)
- Ultra rapide, pas dallocation après init,
- Idéal pour de l'audio pro mais limité à 1 producer / 1 consumer.
---
## 📊 Latence et performance
- Encodage Opus dune frame 960 mono ≈ **0.1 à 0.5 ms** sur PC moderne.
- Aucun besoin d'ajouter de délai artificiel.
- **Pas de risque de “fractionner la voix”** si le buffer est bien géré.
---
## ✅ Récapitulatif des règles dor
- 🎧 Ne pas encoder dans le callback CPAL.
- 🔁 Accumuler les samples dans un buffer jusqu'à 960.
- ✂️ Ne jamais compléter une frame incomplète avec des zéros.
- 🚫 Ne pas timer les envois → laisser le flux audio dicter le tempo.
- 🧵 Utiliser des channels ou buffers inter-threads pour le découplage.
---
## 📌 TODO futur
- [ ] Comparer performance `crossbeam_channel` vs `ringbuf` dans ton usage réel.
- [ ] Implémenter détection de silence (VAD) pour ne pas encoder à vide.
- [ ] Ajouter sequence number + timestamp (RTP-like) dans les paquets réseau.
- [ ] Implémenter jitter buffer côté client (récepteur).