first commit
This commit is contained in:
105
readme_audio.md
Normal file
105
readme_audio.md
Normal 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** l’audio 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 s’attend à des données audio **continues et naturelles**.
|
||||
|
||||
---
|
||||
|
||||
## ⏱️ Pas de timer à 20ms
|
||||
|
||||
- Ne jamais baser l’envoi des paquets audio sur une **horloge ou un cycle fixe**.
|
||||
- L’encodage doit être déclenché **uniquement** par la disponibilité d’une 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 d’allocation après init,
|
||||
- Idéal pour de l'audio pro mais limité à 1 producer / 1 consumer.
|
||||
|
||||
---
|
||||
|
||||
## 📊 Latence et performance
|
||||
|
||||
- Encodage Opus d’une 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 d’or
|
||||
|
||||
- 🎧 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).
|
||||
Reference in New Issue
Block a user