Contrôle du volume par application sous Windows (comme SteelSeries Sonar), avec à terme un boîtier matériel physique pour piloter les canaux.
POC en C++ natif : binaire léger, aucun runtime, empreinte minimale.
Une interface unique (panneau Win32, aucun terminal) qui réunit tout :
- bouton Démarrer / Arrêter le moteur ;
- quatre pages (boutons Canaux / Applications / Égaliseur / Matériel) ;
- page Canaux : canaux dynamiques (bouton + Ajouter, Suppr par canal), renommables, chacun avec une sortie réelle optionnelle et un volume ;
- page Applications : seules les applis qui jouent réellement du son (sessions actives) sont listées ; chacune a son volume et un menu pour l'envoyer vers un canal OU directement vers un périphérique ;
- page Égaliseur (façon SteelSeries) : un égaliseur paramétrique 10 bandes (chaque bande : activée, fréquence, gain, Q) avec sa courbe de réponse dessinée en temps réel (dB affichés). Points déplaçables à la souris sur la courbe (glisser = fréquence + gain), Q à la molette, plus des sliders de gain et un éditeur clavier. Il s'applique à la cible choisie : un canal OU une appli ;
- règle anti-doublon : si une appli est envoyée vers un canal, seul l'EQ du canal s'applique (l'EQ de l'appli est ignoré). Une appli envoyée vers un périphérique utilise son propre EQ. Une appli sans cible reste audible sur ton ancienne sortie par défaut ;
- les basses/aigus simples ont été retirés (doublon avec l'égaliseur) ; il reste un volume rapide par app/canal ;
- page Matériel : associe un boîtier série (ex. COM8) qui envoie
sld<n>:<0-100>. Port + baud réglables, bouton Connecter, et 4 lignes pour mapper chaque slider physique vers le volume d'un canal ou d'une appli (la valeur reçue déplace le volume en direct) ; - liste qui se rafraîchit automatiquement quand une appli apparaît/disparaît ;
- bascule du périphérique par défaut : au Démarrer, CABLE devient la sortie
Windows par défaut (tout le son entre dans l'app) ; à l'Arrêter/fermeture, la
sortie réelle sélectionnée redevient le défaut (via l'API
IPolicyConfig) ; - réglages sauvegardés par application dans
%APPDATA%\SoundMapping\settings.cfg: ils reviennent au prochain lancement ; - tâche de fond : fermer ou minimiser la fenêtre la réduit dans la zone de notification (le moteur continue de tourner). Clic-droit sur l'icône → Ouvrir / Démarrer-Arrêter / Quitter ; double-clic → rouvrir.
Pourquoi pas un service Windows : un service tourne en session 0, isolée — il ne voit ni les sessions audio de l'utilisateur ni le périphérique par défaut. Le bon modèle (SteelSeries GG, EarTrumpet…) est une app utilisateur en arrière-plan avec icône tray.
Sous le capot : chaque appli est capturée séparément (process loopback,
MixEngine → AppAudioRouter), passe dans son EQ (ChannelEq) + volume, et est
rendue sur la sortie choisie. Windows mixe les flux automatiquement.
Les outils console (RouterTest, VirtualRoute, AppEq) restent disponibles
comme cibles séparées pour le debug.
- C++17 + Win32 (GUI native, zéro dépendance externe).
- Windows Core Audio (WASAPI / COM) pour le volume par application.
- Windows 10/11.
- Visual Studio 2022 avec la charge de travail « Développement Desktop en C++ » (ou Build Tools for Visual Studio + CMake).
cmake -S . -B build
cmake --build build --config ReleaseBinaire produit : build\Release\SoundMapping.exe
Depuis l'invite « x64 Native Tools Command Prompt for VS 2022 » :
cl /std:c++17 /O2 /EHsc /DUNICODE /D_UNICODE ^
src\main.cpp src\audio\AudioSessionManager.cpp ^
src\gui\MixerWindow.cpp src\hardware\SerialController.cpp ^
/link Ole32.lib Comctl32.lib /SUBSYSTEM:WINDOWS /OUT:SoundMapping.exeSoundMapping/
├── CMakeLists.txt
└── src/
├── main.cpp # WinMain + CoInitialize
├── audio/
│ ├── AudioSessionManager.{h,cpp} # volume par appli (Core Audio)
│ ├── EndpointEnumerator.{h,cpp} # liste les sorties (id + nom)
│ └── ProcessCapture.{h,cpp} # capture le son d'1 appli (Win11)
├── dsp/
│ ├── Biquad.h # filtre biquad (RBJ), pur C++
│ └── ChannelEq.{h,cpp} # EQ basses/aigus par canal
├── routing/
│ ├── AudioRouter.{h,cpp} # routage loopback -> sortie
│ └── AppAudioRouter.{h,cpp} # capture appli -> EQ+volume -> sortie
├── gui/MixerWindow.{h,cpp} # table de mixage (Win32)
├── hardware/SerialController.{h,cpp} # futur boîtier (stub)
└── tools/
├── router_test.cpp # test du routage (source -> sortie)
├── virtual_route.cpp # route le périph VIRTUEL -> sortie réelle
└── app_eq.cpp # EQ par appli (capture par processus)
Idée directrice : toute la logique audio est dans audio/. La GUI et le
futur hardware ne sont que des « clients » de cette couche. Brancher le boîtier
ne touchera donc pas au coeur.
Objectif final : des périphériques virtuels vers lesquels certaines applis envoient leur son, chacun avec ses réglages, tous mixés vers une sortie réelle sélectionnable.
Créer un périphérique virtuel nécessite un driver noyau signé (voir la
roadmap). On commence donc par la partie réutilisable et sans driver : le
moteur de routage (routing/AudioRouter). Il capture le son d'une sortie en
loopback, applique un volume, et le rejoue sur une autre sortie — avec
rééchantillonnage automatique. Quand le périphérique virtuel existera, seule
l'« id source » changera, le moteur restera identique.
cmake --build build --config Release --target RouterTest
.\build\Release\RouterTest.exeL'outil liste tes sorties, demande une source (capturée en loopback) et une
destination (sortie réelle), puis route le son. Tape un volume 0-100 à la
volée, q pour quitter.
Sans périphérique virtuel pour l'instant, teste avec de vrais périphériques : envoie une appli vers la sortie A (Paramètres Windows → Son), route A → B avec l'outil, et tu entendras le son aussi sur B. Le routage exclusif (son inaudible sur la source) viendra avec le driver virtuel.
Créer un périphérique audio se fait au niveau driver noyau. Plutôt que de le
réécrire, on utilise le driver open-source Virtual-Audio-Driver (dérivé du
sample officiel SYSVAD de Microsoft, licence MIT), puis notre AudioRouter
renvoie son son vers une sortie réelle.
- Désactiver Secure Boot (BIOS/UEFI) — sinon le test-signing ne s'active pas et le driver ne se chargera pas.
- Activer le test-signing (PowerShell admin), puis redémarrer :
Un filigrane « Mode test » apparaît : c'est normal.
bcdedit /set testsigning on - Télécharger la dernière release depuis VirtualDrivers/Virtual-Audio-Driver et la décompresser.
- Device Manager → menu Action → Ajouter un matériel d'ancienne
génération → Installer manuellement → Contrôleurs audio, vidéo et jeu →
Disque fourni… → sélectionner
VirtualAudioDriver.inf. - Vérifier qu'une sortie « Virtual Audio Driver » apparaît dans les Paramètres → Son.
Souci connu sur Windows 11 24H2 (périphérique absent, erreur de signature 52) : voir l'issue #1.
cmake --build build --config Release --target VirtualRoute
.\build\Release\VirtualRoute.exeL'outil détecte automatiquement le périphérique virtuel, te demande la sortie réelle de destination, et lance le routage. Mets ensuite le périphérique virtuel par défaut dans Windows : tout ton son y arrive, puis ressort sur la sortie réelle choisie. Volume réglable en direct.
Avec toutes les apps sur un seul CABLE, leurs sons sont déjà mélangés : on
ne peut pas leur appliquer des effets différents. Pour un EQ par appli, on
capture chaque application séparément grâce à l'API process loopback de
Windows 11 (ProcessCapture), on lui applique son propre EQ (ChannelEq :
basses + aigus), puis on rend le résultat sur la sortie choisie
(AppAudioRouter).
Prérequis : Windows 11 (ou Windows 10 build 20348+) pour la capture par processus.
cmake --build build --config Release --target AppEq
.\build\Release\AppEq.exeChoisis une application (ex. Spotify) et une sortie, puis règle en direct :
b6 # +6 dB de basses
t-3 # -3 dB d'aigus
v80 # volume 80 %
q # quitter
Astuce : mets la sortie de l'appli sur CABLE pour ne pas l'entendre en direct — tu n'entends alors que la version traitée. Le moteur EQ est validé par test (identité à 0 dB, boost basses/aigus ciblés, stabilité).
- POC — mixer logiciel fonctionnel. ✅
- Moteur de routage user-mode (
AudioRouter) — loopback → sortie réelle, avec volume. ✅ (testable viaRouterTest) - EQ par application — capture par processus (
ProcessCapture) + EQ (ChannelEq) + routeur per-app (AppAudioRouter), testable viaAppEq. ✅ - Application unifiée (
SoundMapping.exe) — GUI Win32 :MixEnginegère un canal par appli (volume + basses + aigus) vers une sortie sélectionnable. ✅ - Périphérique virtuel — driver open-source Virtual-Audio-Driver (SYSVAD,
test-signing local) + auto-routage virtuel → sortie réelle (
VirtualRoute). ✅ Plus tard : compiler notre propre driver depuis les sources si besoin. - Notifications de sessions (
IAudioSessionNotification) → mise à jour auto de la liste, sans bouton Rafraîchir. - Icône systray + lancement au démarrage.
⚠️ Une app utilisateur en arrière-plan, pas un service Windows (session 0) : un service ne voit pas les sessions audio de ta session interactive. - Hardware — Arduino + potentiomètres → lecture série →
SerialControllermappe les curseurs sur les volumes. - Persistance des réglages par application.