Comment obtenir du son sous Linux?

Retour à la page Systèmes

Motivation

Ayant parfois du mal à obtenir du son sur des programmes d'édition musicale, j'ai tâché d'y voir clair en voyant quels services entraient en jeu dans la production du son sous Linux.
C'est assez confus, mais les choses deviennent beaucoup plus logiques lorsque l'on se les représente en terme de connexions
  • 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
Donc j'ai pulseaudio sur mon système, et il va falloir en tenir compte par la suite. En particulier, et contrairement à ce que le susdit Ted recommande, il vaut mieux ne pas intégrer l'utilisateur courant au groupe audio
Tant mieux, c'est cela de moins à faire.

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

ALSA, pour "Advanced Linux Sound Architecture", est l'interface entre l'espace utilisateur et le noyau.
Schématiquement, il n'admet qu'une entrée, ce qui est gênant si, par exemple, un programme veut nous informer par un signal sonore qu'un message électronique vient d'arriver, alors que l'on est déjà en train de regarder un film.
C'est pourquoi on aura besoin de programmes de mixage comme PulseAudio.

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.

L'utilitaire alsamixer offre une interface synthetique pour le contrôle des volumes.
C'est en fait une interface pour l'outil de commande amixer plus complet mais bien plus obscur.

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.

La plupart des ressources utilisées par ALSA sont décrites dans /proc/asound.
Par exemple, la commande aconnect -i -l ne fait que reformater /proc/asound/seq/clients. Illustration:
$ 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...)