Comment obtenir du son sous Linux?
Sommaire
Motivation
- Qui intervient?
- Qui envoie des données à qui?
- Comment contrôler le passage effectif de ces données?
Une page brève mais qui m'a bien mis sur la voie: Ted's Linux MIDI Guide Pour les systèmes (nombreux) qui utilisent pulseaudio, les choses à ne pas faire.
Ai-je pulseaudio quelque-part?
La page de Ted demande de tester si pulseaudio est là. Je veux bien:
$ ps -ef | grep puls moi 1600 1 0 Sep14 ? 00:00:07 /usr/bin/pulseaudio --start moi 1608 1600 0 Sep14 ? 00:00:00 /usr/libexec/pulse/gconf-helper moi 30715 2075 0 15:02 pts/1 00:00:00 grep --color=auto puls
Par où passe le son?
Selon cette présentation, la plupart des systèmes sous Linux ressemblent à cela:
- User space:
- "Media player" ==> "GStreamer" ==> "PulseAudio" ==> "ALSA Lib"
- VOIP(Skype) ==> "PulseAudio" ==> "ALSA Lib"
- Kernel space:
- "ALSA Kernel" ==> "HDA Controller Driver" <==> "HDA Codec Driver"
- Hardware:
- "HDA Southbridge" ==> "HDA Codec Chip"
ALSA
Mais n'anticipons pas et testons si ALSA fonctionne bien à l'aide des programmes du package alsa-utils
$ speaker-test -s 1 -t wav
Pas de son? Regarder le volume du point de vue d'ALSA:
alsamixer
- F6 - : devrait afficher le volume principal "MASTER". Vérifier qu'il n'est pas nul.
- F6 "HDA Intel" : volume des différents canaux du périphérique concerné. Vérifier notamment que "PCM" n'est pas à zéro
PulseAudio
Si du son est sorti plus haut, alors ALSA fonctionne et on peut regarder un peu ce qui se passe plus haut, i.e. chez PulseAudio.
L'interface la plus conviviale pour pulseaudio est l'outil graphique pavucontrol
$ yum install pavucontrol $ pavucontrol &
- L'onglet Output Devices correspond au master de alsamixer: faire varier l'un fait varier l'autre.
- L'onglet Playback, affiche le volume de chaque application qui
produit du son pour PulseAudio. Par exemple:
- Lancer une lecture par VLC crée une section VLC Media Player
- Ecouter une radio internet crée ALSA plug-in
Particularités MIDI
Jusqu'à présent il n'a pas été question de MIDI. La nature des données MIDI est en effet assez différente: le système transmet la hauteur des notes à jouer ou à stopper (avec pas mal d'autres infos), mais pas le son de l'instrument correspondant.
Il nous faut donc de quoi convertir les données MIDI en signaux sonores: un synthétiseur. Les deux plus connus sont Timidity et FluidSynth.
La partie de notre chaîne consacrée au MIDI serait donc:
(programme MIDI) ==> Synthétiseur ==> PulseAudio
Connexions
Lançons donc le synthétiseur fluidsynth, en lui disant de se connecter à PulseAudio, et un programme MIDI comme le petit clavier virtuel vkeybd
$ fluidsynth -a pulseaudio /usr/share/soundfonts/FluidR3_GM.sf2 $ vkeybd
Assez curieusement, ALSA offre un service de routage/connexion MIDI que l'on ne va pas se priver d'utiliser.
Le clavier apparaît parmi les producteurs de signaux midi (INPUT):
$aconnect -i -l client 0: 'System' [type=kernel] 0 'Timer ' 1 'Announce ' client 14: 'Midi Through' [type=kernel] 0 'Midi Through Port-0' client 128: 'Virtual Keyboard' [type=user] 0 'Virtual Keyboard
Et le synthétiseur apparaît parmi les consommateurs de signaux midi (OUTPUT):
$ aconnect -o -l client 14: 'Midi Through' [type=kernel] 0 'Midi Through Port-0' client 129: 'FLUID Synth (3793)' [type=user] 0 'Synth input port (3793:0)'
Il nous faut connecter notre clavier (INPUT) au synthétiseur (OUTPUT):
$ aconnect 128:0 129:0
Bonne musique!
Si l'on veut voir les événements MIDI qui sont envoyés au synthétiseur, le package alsa-utils fournit aseqdump: il suffit de le connecter aussi à la sortie de notre clavier MIDI. On lance donc dans un terminal à part:
$ aseqdump
Puis on procède aux opérations de connexion:
$ aconnect -o ... client 130: 'aseqdump' [type=user] 0 'aseqdump $ aconnect 128:0 130:0
A présent chaque appui sur une touche du clavier virtuel devrait provoquer l'affichage d'un message dans la fenêtre de aseqdump
. Par exemple , au bout de quelques notes tapées, mon terminal ressemble à:
$ aseqdump Waiting for data at port 130:0. Press Ctrl+C to end. Source Event Ch Data 0:1 Port subscribed 129:0 -> 130:0 129:0 Note on 0, note 65, velocity 127 129:0 Note off 0, note 65, velocity 0 129:0 Note on 0, note 59, velocity 127 129:0 Note off 0, note 59, velocity 0 129:0 Note on 0, note 55, velocity 127 129:0 Note off 0, note 55, velocity 0 129:0 Note on 0, note 66, velocity 127 129:0 Note off 0, note 66, velocity 0 129:0 Note on 0, note 65, velocity 127 129:0 Note off 0, note 65, velocity 0 ...
Enregistrer la sortie
Problème ultra-courant: vous écoutez quelque-chose (au hasard, une webradio) et vous voudriez enregistrer ce qu'il se passe.
Trouver le peripherique de capture
$ alsamixer | Card: PulseAudio F1: Help | | Chip: PulseAudio F2: System information | | View: F3:[Playback] F4: Capture F5: All F6: Select sound card | | Item: Master Esc: Exit | | | | | | +--+ | | |**| | | |**| | | |**| | | |**| | | |**| | | |**| | | |**| | | |**| | | +--+ | | |OO| | | +--+ | | 142<>160 | | < Master >
Attention à ne pas se faire avoir à ce stade:
- La ligne "View" indique "Playback": ce qui est affiché ne nous est donc d'aucune utilité pour l'enregistrement.
- Cette meme ligne nous dit qu'il faut appuyer sur "F4" pour voir les périphéques de capture.
- Le 00 n'indique pas un volume à 0. En fait le 00 vert signifie un canal activé (sinon ce serait MM)
Appuyons donc sur F4 comme nous y avons implicitement été invités:
| Card: PulseAudio F1: Help | | Chip: PulseAudio F2: System information | | View: F3: Playback F4:[Capture] F5: All F6: Select sound card | | Item: Capture Esc: Exit | | | | | | | | +--+ | | |* | | | |**| | | |**| | | |**| | | |**| | | |**| | | |**| | | |**| | | |**| | | |**| | | L+--+R | | CAPTURE | | 100<>95 | | <Capture > |
Deux détails extrêmement importants;
- Si vous voyez "-----" au lieu de "CAPTURE", rien ne sera enregistré
- Si le volume est à 0, rien ne sera enregistré non plus
- Les lettre L..R situent chaque canal (gauche/droite) du périphérique courant.
Régler le volume de la capture
Ce qui suit est largement extrait du manuel d'AlsaMixer: man alsamixer
- m: pour activer/désactiver un canal
- SPC: pour activer/désactiver l'enregistrement (on vient de le dire plus haut)
- =: pour régler la balance entre les canaux du contrôle courant (si le périphérique le permet, ce qui ne semble pas le cas chez moi)
| Card: HDA Intel F1: Help | | Chip: C-Media CMI9880 F2: System information | | View: F3: Playback F4:[Capture] F5: All F6: Select sound card | | Item: Input Source [Front Mic] Esc: Exit | | | | | | +--+ +--+ | | | | | | | | | | | | | | |**| |**| | | |**| |**| | | |**| |**| | | |**| |**| | | |**| |**| | | |**| |**| | | |**| |**| | | L+--+R L+--+R Front Mic Front Mic | | ------- CAPTURE CAPTURE | | 70<>70 70<>70 | | S/PDIF Capture Capture 1 Input Source Input Source 1 |
Pour en arriver là:
- F4 affiche les périphériques de capture (déjà fait, en principe)
- F6 en choisit un: on a pris le 0 ("Intel HDA" chez moi)
- la mention CAPTURE s'obtient par un appui sur SPC
- Il est souvent recommandé de ne pas aller jusqu'à 100%de volume
Trouver le format de capture
On va enregistrer avec le périphérique de capture par défaut que nos manips précédentes ont activé.
Il nous faut savoir quel type d'échantillons il fournit, et quelle est la fréquence d'échantillonnage:
$ arecord -D hw:0,0 --dump-hw-params Recording WAVE 'stdin' : Unsigned 8 bit, Rate 8000 Hz, Mono HW Params of device "hw:0,0": -------------------- ACCESS: MMAP_INTERLEAVED RW_INTERLEAVED FORMAT: S16_LE SUBFORMAT: STD SAMPLE_BITS: 16 FRAME_BITS: 32 CHANNELS: 2 RATE: [44100 96000] PERIOD_TIME: (333 11888617) PERIOD_SIZE: [32 524288] PERIOD_BYTES: [128 2097152] PERIODS: [2 32] BUFFER_TIME: (666 23777234) BUFFER_SIZE: [64 1048576] BUFFER_BYTES: [256 4194304] TICK_TIME: ALL -------------------- arecord: set_params:1102: Sample format non available Available formats: - S16_LE
Les échantillons sont 16 bits, signés, ce qui correspond à S16_LE., et le taux d'échantillonnage 44100 correspond à celui d'un CD.
... ce qui veut dire que l'on pourra enregistrer au format CD: -f cd
Capturer
$ arecord -f cd -D hw:0,0 test.wav Recording WAVE 'test.wav' : Signed 16 bit Little Endian, Rate 44100 Hz, Stereo
Pourr mettre fin à l'enregistrement, Ctrl-C suffit.
Verifier le resultat
$ aplay test.wav
Chez moi on entend bien le son, mais assez faible et couvert par pas mal de bruit.
C'est peut-être dû à une piètre qualité du circuit audio, mais plus probablement à un truc qu'il me reste à découvrir ...
Pour aller plus loin
Il y aurait beaucoup à dire! Je débute sur le sujet. Quelques précisions, notamment, sur ce que font réellement les outils.
$ cat /proc/asound/seq/clients Client info cur clients : 1 peak clients : 1 max clients : 192 Client 0 : "System" [Kernel] Port 0 : "Timer" (Rwe-) Port 1 : "Announce" (R-e-) Client 14 : "Midi Through" [Kernel] Port 0 : "Midi Through Port-0" (RWe-) $ aconnect -l -i client 0: 'System' [type=kernel] 0 'Timer ' 1 'Announce ' client 14: 'Midi Through' [type=kernel] 0 'Midi Through Port-0'
Des explications détaillées sur ce système de fichiers /proc/asound sont disponibles sur le wiki ALSA.
Quelques articles font comprendre à quel point le système est inutilement compliqué et sous-documenté ....
- Un tutorial sur l'API ALSA par un connaisseur
- Une explication de la Structure d'ALSA (le commentaire à la fin habille les développeurs pour l'hiver...)