Concrétisons Nos Idées

Envoie le son ! mais dans l'autre pièce...

Rédigé par Sacha - - aucun commentaire

Bonjour les gens !

Me revoilà pour un projet que j'avais envie de faire depuis un moment. J'aime beaucoup mettre de la musique chez moi mais dès qu'on quitte la pièce il se trouve qu'on n'entend plus rien. Mets le son beaucoup plus fort me direz-vous, oui mais j'ai des voisins et ce n'est pas très agréable. Du coup, je me suis penché sur la possibilité de dupliquer le son de mon PC de salon pour l'envoyer par WIFI dans tout l'appartement.

Et bien c'est parti !

Pour ce projet, rien de révolutionnaire par rapport à mon ancien projet "Une radio vintage flambant neuve". D'ailleurs, c'est sensiblement la même chose en version salle de bain. Ben oui, j'ai déjà la radio vintage dans la cuisine et donc la prochaine pièce à équiper est la salle de bain. (C'est évident ! non?)

Donc pour la partie hardware, j'ai décidé d'aller vers une version résistante à l'humidité, donc j'ai choisi un design "U-bot". Eh bien c'est plus simple que mes anciens projets, il suffit d'une boîte de dérivation électrique assez grande pour tout mettre dedans, une enceinte de salle de bain, un raspberry Pi zero W avec sa carte son, un ampli, un convertisseur 12->5V et un bouton On/Off qui brille bien. Et hop on assemble le tout :).

trou_face trou_alim ampli rasp fini1 fini2 Vous aurez pu voir que je n'ai pas de scie cloche, ce qui m'a permis de bien galérer, sinon rien de particulier. J'ai tout bouché au pistolet à colle chaude pour rendre le tout un peu plus étanche.

Comme je me suis basé sur le même hardware et software que ma webradio pour construire mon enceinte de salle de bain, je vais donc pouvoir me servir de ma webradio comme enceinte aussi. J'ai donc maintenant deux enceintes connectées et il me faut un moyen d'envoyer le son à tout le monde en même temps et pour cela je vais utiliser une librairie qui s'appelle gstreamer en version 1.0 (il existe la 0.10 aussi). Cette librairie permet de faire du lego avec des briques de gestion audio et vidéo, même si dans notre cas, on va se limiter à l'audio. Le deuxième point important est de trouver un point de prise de son.
J'avais pensé au début faire un module qui récupère le son stéréo à la sortie de mon PC en analogique et qui le transmettrait ensuite. J'ai vite abandonné car il faut mettre en place ce module et rajouter encore un raspberry pi me paraissait "too much".

Dans un premier temps, je propose de tester que gstreamer et correctement installé et fonctionnel sur vos deux appareils avec ces deux commandes.
Sur l'enceinte:
$gst-launch-1.0 udpsrc port=5000 caps='application/x-rtp, media=(string)audio, clock-rate=(int)44100, encoding-name=(string)L16, encoding-params=(string)1, channels=(int)1, payload=(int)96' ! rtpL16depay ! audioconvert ! autoaudiosink
Sur le PC:
$gst-launch-1.0 audiotestsrc ! audioconvert ! audio/x-raw, format="(string)S16BE", layout="(string)interleaved", channels=1,rate=44100 ! rtpL16pay ! udpsink host=localhost port=5000
Vous devriez entendre une magnifique sinusoïde (Ironie !). Mais bon si ça casse les oreilles, c'est que ça fonctionne.

Il s'avère qu'avec gstreamer, il est possible de se connecter à un point de monitoring de votre gestion du son sous Linux (Ah oui, tout est Linux only, j'imagine que c'est transposable à d'autres systèmes d'exploitation mais je n'ai pas cherché !). A partir de là, il y a deux solutions. Soit vous avez une carte son interne (Intel de préférence) et vous pouvez faire un point de monitoring directement dessus. Vous aurez dans ce cas une duplication du son de sortie de votre PC. Soit vous créez une sortie virtuelle (ce que je vais détailler), et dans ce cas on peut rediriger les sources que l'on désire dessus.

Alors en détail :
- On crée une fausse sortie
$pactl load-module module-null-sink sink_name=multiHP
- On connecte une entrée à la fausse sortie
$pacmd list-sinks (liste les outputs)
$pacmd list-sink-inputs (liste les inputs)
$pacmd move-sink-input %input %output (remplacer %input et %output par les valeurs numériques souhaitées)
- On met la carte son à fond
$pactl set-sink-volume 0 100% (si on veut)
- On récupère le flux
$gst-launch-1.0 pulsesrc device=multiHP.monitor ! audioconvert ! autoaudiosink
A ce stade, on doit avoir le son normalement sur le PC. On a redirigé les flux désirés sur la fausse sortie et avec gstreamer, on joue cette fausse sortie sur la vraie. Pour la copie de votre carte son, je vous renvoie sur l'article d'un autre blog afin de trouver le nom de l'option device pour vous y connecter.

Maintenant, on sait capter le son et l'envoyer, on assemble, on remue et on teste.
Sur l'enceinte:
gst-launch-1.0 udpsrc port=5000 caps='application/x-rtp, media=(string)audio, clock-rate=(int)44100, encoding-name=(string)L16, encoding-params=(string)2, payload=(int)96' ! rtpL16depay ! audioconvert ! autoaudiosink
Sur le serveur:
gst-launch-1.0 pulsesrc device=multiHP.monitor ! audioconvert ! audio/x-raw, format="(string)S16BE", layout="(string)interleaved", channels=2,rate=44100 ! rtpL16pay ! tee name=t t. ! queue ! udpsink host=%addrpi1 port=5000 t. ! queue ! udpsink host=%addrpi2 port=5000 t. ! queue ! udpsink host=localhost port=5000
Et voilà, on envoie la source choisie sur les deux enceintes (IP à remplir) et le PC. C'est pas chouette ça ? :).
Alors deux petites choses : j'ai commencé une application python qui gère la partie chiante de création de la sortie virtuelle et les envoie. Elle n'est pas transcendante mais je la partage si ça intéresse quelqu'un. La deuxième chose est que la qualité dépend grandement de votre WIFI (et de celui de vos voisins en fait), de plus j'utilise un protocole UDP alors que le TCP serait bien mieux dans ce monde chaotique des micro-ondes. Gstreamer le permet, alors avec un peu de changement ça devrait le faire ;). En passant, j'ai remarqué que j'avais moins de soucis avec un pi zero et un dongle WIFI qu'avec un pi zero W. A méditer.

J'espère que ça vous aura donné envie de faire la même chose et je vous souhaite de bonnes bidouilles à tous !

Écrire un commentaire

Capcha
Entrez le code de l'image :