見出し画像

Linuxオーディオ:ALSAとPulseAudioの関係

音関係に詳しくないので、Linuxで音声を扱っていると、なんだかよく分からないけどまあ音が出たからいいかとやり過ごしてしまう場面が多々あります。
その原因の1つはALSAとPulseAudioの関係をきちんと理解していないためだと思われるので、自分なりに少し整理してみました。

ALSA

ALSA(Advanced Linux Sound Architecture)はサウンドデバイスへアクセスするためのAPIを提供するものです。
例えば、ラズパイ5にIQaudioのPiDAC+を取り付けた場合は、下記のようにHDMIのカード2つと、DACのサウンドカード1つがALSAから利用できる感じになります。

ALSAのレイヤ

どのようなサウンドカードが利用できるかは、aplayに-lオプションを付けて実行すればリストが表示されます。

$ aplay -l
**** ハードウェアデバイス PLAYBACK のリスト ****
カード 0: vc4hdmi0 [vc4-hdmi-0], デバイス 0: MAI PCM i2s-hifi-0 [MAI PCM i2s-hifi-0]
  サブデバイス: 1/1
  サブデバイス #0: subdevice #0
カード 1: vc4hdmi1 [vc4-hdmi-1], デバイス 0: MAI PCM i2s-hifi-0 [MAI PCM i2s-hifi-0]
  サブデバイス: 1/1
  サブデバイス #0: subdevice #0
カード 2: DAC [RPi DAC+], デバイス 0: Raspberry Pi DAC+ HiFi pcm512x-hifi-0 [Raspberry Pi DAC+ HiFi pcm512x-hifi-0]
  サブデバイス: 1/1
  サブデバイス #0: subdevice #0

例えば、音楽CDからリッピングしたwavファイル(16bit/44.1kHz/2ch)をPiDAC+で再生させたいなら、デバイス指定(-D)にhw:2,0を付けて実行すれば再生されます。"hw:2,0"は”hw:CARD=DAC,DEV=0”という書き方でも良いです。

$ aplay -D hw:2,0 test.wav 
再生中 WAVE 'test.wav' : Signed 16 bit Little Endian, レート 44100 Hz, ステレオ

しかし、例えばJVCハイレゾリューションサイトに置いてある24bit/192kHzのハイレゾ音源のwavファイルを指定した場合には、下記のようにフォーマットが違うということでエラーになってしまい、再生できません。

$ aplay -D hw:2,0 Keep_your_side_24bit192kHz_short.wav 
再生中 WAVE '/home/kaneko/Music/Keep_your_side_24bit192kHz_short.wav' : Signed 24 bit Little Endian in 3bytes, レート 192000 Hz, ステレオ
aplay: set_params:1352: サンプルフォーマットが使用不可能
Available formats:
- S16_LE
- S24_LE
- S32_LE

この場合、デバイスの指定を"hw:2,0"の代わりに"plughw:2,0"とすると再生できます。hwの場合は、入力のデータフォーマットをそのまま出力先デバイスに送りますが、plughwを指定した場合には、出力先デバイスに合わせて変換が行われるようです。どのような変換が行われたかは、aplayで-vオプションを付けて実行すると表示されます。
今回の場合だと下記に示すように、format:S24_3LE, mbits:24が、format:S24_LE, mbits:32に変換されてPiDAC+に送られています。3バイトに24bitデータが格納されている元のデータが、4バイトに24bitデータが格納されているデータへ変換されているようです。

$ aplay -v -D plughw:2,0 Keep_your_side_24bit192kHz_short.wav 
再生中 WAVE '/home/kaneko/Music/Keep_your_side_24bit192kHz_short.wav' : Signed 24 bit Little Endian in 3bytes, レート 192000 Hz, ステレオ
Plug PCM: Linear conversion PCM (S24_LE)
Its setup is:
  stream       : PLAYBACK
  access       : RW_INTERLEAVED
  format       : S24_3LE
  subformat    : STD
  channels     : 2
  rate         : 192000
  exact rate   : 192000 (192000/1)
  msbits       : 24
  buffer_size  : 65536
  period_size  : 512
  period_time  : 2666
  tstamp_mode  : NONE
  tstamp_type  : MONOTONIC
  period_step  : 1
  avail_min    : 512
  period_event : 0
  start_threshold  : 65536
  stop_threshold   : 65536
  silence_threshold: 0
  silence_size : 0
  boundary     : 4611686018427387904
Slave: Hardware PCM card 2 'RPi DAC+' device 0 subdevice 0
Its setup is:
  stream       : PLAYBACK
  access       : MMAP_INTERLEAVED
  format       : S24_LE
  subformat    : STD
  channels     : 2
  rate         : 192000
  exact rate   : 192000 (192000/1)
  msbits       : 32
  buffer_size  : 65536
  period_size  : 512
  period_time  : 2666
  tstamp_mode  : NONE
  tstamp_type  : MONOTONIC
  period_step  : 1
  avail_min    : 512
  period_event : 0
  start_threshold  : 65536
  stop_threshold   : 65536
  silence_threshold: 0
  silence_size : 0
  boundary     : 4611686018427387904
  appl_ptr     : 0
  hw_ptr       : 0

では、plughwにすれば何でも変換してくれるかというとそうでも無いようで、HDMIデバイスに対しては、hwでもplughwでも再生できません。

$ aplay -D hw:0,0 test.wav 
再生中 WAVE 'test.wav' : Signed 16 bit Little Endian, レート 44100 Hz, ステレオ
aplay: set_params:1352: サンプルフォーマットが使用不可能
Available formats:
- IEC958_SUBFRAME_LE
$ aplay -D plughw:0,0 test.wav 
再生中 WAVE 'test.wav' : Signed 16 bit Little Endian, レート 44100 Hz, ステレオ
aplay: set_params:1352: サンプルフォーマットが使用不可能
Available formats:
- IEC958_SUBFRAME_LE

デバイス名に指定できるのはhwやplughwだけでなく色々なものがあるようです。それらは、aplayで-Lオプションを付けて実行すると一覧が表示されます。

$ aplay -L
null
    Discard all samples (playback) or generate zero samples (capture)
default
    Playback/recording through the PulseAudio sound server
sysdefault
    Default Audio Device
lavrate
    Rate Converter Plugin Using Libav/FFmpeg Library
samplerate
    Rate Converter Plugin Using Samplerate Library
speexrate
    Rate Converter Plugin Using Speex Resampler
jack
    JACK Audio Connection Kit
oss
    Open Sound System
pulse
    PulseAudio Sound Server
speex
    Plugin using Speex DSP (resample, agc, denoise, echo, dereverb)
upmix
    Plugin for channel upmix (4,6,8)
vdownmix
    Plugin for channel downmix (stereo) with a simple spacialization
hw:CARD=vc4hdmi0,DEV=0
    vc4-hdmi-0, MAI PCM i2s-hifi-0
    Direct hardware device without any conversions
plughw:CARD=vc4hdmi0,DEV=0
    vc4-hdmi-0, MAI PCM i2s-hifi-0
    Hardware device with all software conversions
sysdefault:CARD=vc4hdmi0
    vc4-hdmi-0, MAI PCM i2s-hifi-0
    Default Audio Device
hdmi:CARD=vc4hdmi0,DEV=0
    vc4-hdmi-0, MAI PCM i2s-hifi-0
    HDMI Audio Output
dmix:CARD=vc4hdmi0,DEV=0
    vc4-hdmi-0, MAI PCM i2s-hifi-0
    Direct sample mixing device
usbstream:CARD=vc4hdmi0
    vc4-hdmi-0
    USB Stream Output
hw:CARD=vc4hdmi1,DEV=0
    vc4-hdmi-1, MAI PCM i2s-hifi-0
    Direct hardware device without any conversions
plughw:CARD=vc4hdmi1,DEV=0
    vc4-hdmi-1, MAI PCM i2s-hifi-0
    Hardware device with all software conversions
sysdefault:CARD=vc4hdmi1
    vc4-hdmi-1, MAI PCM i2s-hifi-0
    Default Audio Device
hdmi:CARD=vc4hdmi1,DEV=0
    vc4-hdmi-1, MAI PCM i2s-hifi-0
    HDMI Audio Output
dmix:CARD=vc4hdmi1,DEV=0
    vc4-hdmi-1, MAI PCM i2s-hifi-0
    Direct sample mixing device
usbstream:CARD=vc4hdmi1
    vc4-hdmi-1
    USB Stream Output
hw:CARD=DAC,DEV=0
    RPi DAC+, Raspberry Pi DAC+ HiFi pcm512x-hifi-0
    Direct hardware device without any conversions
plughw:CARD=DAC,DEV=0
    RPi DAC+, Raspberry Pi DAC+ HiFi pcm512x-hifi-0
    Hardware device with all software conversions
sysdefault:CARD=DAC
    RPi DAC+, Raspberry Pi DAC+ HiFi pcm512x-hifi-0
    Default Audio Device
dmix:CARD=DAC,DEV=0
    RPi DAC+, Raspberry Pi DAC+ HiFi pcm512x-hifi-0
    Direct sample mixing device
usbstream:CARD=DAC
    RPi DAC+
    USB Stream Output

ここでは、"hw:0,0"という略した表記でなく、"hw:CARD=vc4hdmi0,DEV=0"というCARD名とDEV番号での表記になっています。

先ほどのHDMIへの出力の場合では、"sysdefault:CARD=vc4hdmi0"という指定をすれば再生してくれます。"sysdefault:0"という表記でもOKです。先ほどのハイレゾのwavファイルでも同じ指定で再生してくれます。

$ aplay -v -D sysdefault:0 Keep_your_side_24bit192kHz_short.wav 
再生中 WAVE 'Keep_your_side_24bit192kHz_short.wav' : Signed 24 bit Little Endian in 3bytes, レート 192000 Hz, ステレオ
Plug PCM: Rate conversion PCM (48000, sformat=S24_3LE)
Converter: libspeex (external)
Protocol version: 10003
Its setup is:
  stream       : PLAYBACK
  access       : RW_INTERLEAVED
  format       : S24_3LE
  subformat    : STD
  channels     : 2
  rate         : 192000
  exact rate   : 192000 (192000/1)
  msbits       : 24
  buffer_size  : 96000
  period_size  : 24000
  period_time  : 125000
  tstamp_mode  : NONE
  tstamp_type  : MONOTONIC
  period_step  : 1
  avail_min    : 24000
  period_event : 0
  start_threshold  : 96000
  stop_threshold   : 96000
  silence_threshold: 0
  silence_size : 0
  boundary     : 6755399441055744000
Slave: Soft volume PCM
Control: PCM Playback Volume
min_dB: -51
max_dB: 0
resolution: 256
Its setup is:
  stream       : PLAYBACK
  access       : MMAP_INTERLEAVED
  format       : S24_3LE
  subformat    : STD
  channels     : 2
  rate         : 48000
  exact rate   : 48000 (48000/1)
  msbits       : 24
  buffer_size  : 24000
  period_size  : 6000
  period_time  : 125000
  tstamp_mode  : NONE
  tstamp_type  : MONOTONIC
  period_step  : 1
  avail_min    : 6000
  period_event : 0
  start_threshold  : 24000
  stop_threshold   : 24000
  silence_threshold: 0
  silence_size : 0
  boundary     : 6755399441055744000
Slave: IEC958 subframe conversion PCM (IEC958_SUBFRAME_LE)
Its setup is:
  stream       : PLAYBACK
  access       : MMAP_INTERLEAVED
  format       : S24_3LE
  subformat    : STD
  channels     : 2
  rate         : 48000
  exact rate   : 48000 (48000/1)
  msbits       : 24
  buffer_size  : 24000
  period_size  : 6000
  period_time  : 125000
  tstamp_mode  : NONE
  tstamp_type  : MONOTONIC
  period_step  : 1
  avail_min    : 6000
  period_event : 0
  start_threshold  : 24000
  stop_threshold   : 24000
  silence_threshold: 0
  silence_size : 0
  boundary     : 6755399441055744000
Slave: Hooks PCM
Its setup is:
  stream       : PLAYBACK
  access       : MMAP_INTERLEAVED
  format       : IEC958_SUBFRAME_LE
  subformat    : STD
  channels     : 2
  rate         : 48000
  exact rate   : 48000 (48000/1)
  msbits       : 24
  buffer_size  : 24000
  period_size  : 6000
  period_time  : 125000
  tstamp_mode  : NONE
  tstamp_type  : MONOTONIC
  period_step  : 1
  avail_min    : 6000
  period_event : 0
  start_threshold  : 24000
  stop_threshold   : 24000
  silence_threshold: 0
  silence_size : 0
  boundary     : 6755399441055744000
Slave: Hardware PCM card 0 'vc4-hdmi-0' device 0 subdevice 0
Its setup is:
  stream       : PLAYBACK
  access       : MMAP_INTERLEAVED
  format       : IEC958_SUBFRAME_LE
  subformat    : STD
  channels     : 2
  rate         : 48000
  exact rate   : 48000 (48000/1)
  msbits       : 24
  buffer_size  : 24000
  period_size  : 6000
  period_time  : 125000
  tstamp_mode  : NONE
  tstamp_type  : MONOTONIC
  period_step  : 1
  avail_min    : 6000
  period_event : 0
  start_threshold  : 24000
  stop_threshold   : 24000
  silence_threshold: 0
  silence_size : 0
  boundary     : 6755399441055744000
  appl_ptr     : 0
  hw_ptr       : 0

各オーディオカードの設定は、alsamixerを実行すると行うことができます。
F6キーでサウンドカードを選択でき、PiDAC+の場合は下記の画面になります。上下左右のカーソルキーを使って設定を変更できます。PiDAC+ではDSPのフィルタの変更などもできるようです(私の耳では音の違いが分からないので、本当に変わっているのかどうかは不明です)。

alsamixerの画面

ちなみに、alsamixerを起動したときに最初に出てくるマスターの音量調整は、次に説明するPulseAudioの音量調整となっているので、直接hwなどで出力先デバイスを指定して再生している場合には、このボリュームを変更しても音量は変わりません。

PulseAudio

PulseAudioはサウンドサーバーと呼ばれる物で、アプリケーションとサウンドカード(ALSAのレイヤ)との間に入って動作するものです。
現在では、ラズパイOSも含め多くのLinuxでは、インストールしたときに最初から動作しているように思います。

イメージとしては、下記の図のような信号の流れになる感じです。

ALSAとPluseAudioの関係

先ほどまでのALSAの説明で、aplayで出力先デバイスを明示的に指定する方法を説明しました。それは、この図の青線やオレンジ線に相当します。一方、デバイスの指定をしない場合は、デフォルトとしてPluseAudioに入力されるようになっているようで、これは緑線に相当します。

したがって、aplayで出力先デバイスの指定なしで音声ファイルを再生すると、色々なフォーマットの音声ファイルであっても、そのデータはPluseAudioが受け取ってくれるので、エラーも無く再生が実行されます。出力先のデバイスやそれに合わせたフォーマット変換、音量調整などはすべてPulseAudioが行っているようです。

pavucontrolを起動すると下図のようなウインドウが開き、出力先のデバイスの指定や、音量調整などのPulseAudioの設定が行えます。

pavucontrolの画面

PulseAudioが間に入るメリットの1つに、複数のアプリケーションが同一のサウンドデバイスに対して同時に再生が行える点があります。
例えば、aplayが直接サウンドカードを使って再生しているときに、別のaplayを使って同一デバイスに再生をすると、デバイスが利用できないとエラーになってしまいます。

一方、PulseAudioを介した場合、いくつでも再生を実行することができます。PulseAudioがミックスして、同一のデバイスに出力してくれます。

また、それぞれの出力先を異なるものにすることもできます。

再生アプリケーションごとの音量調整や出力先の設定はpavucontrolでできます。下記はaplayで3つ同時に音声ファイルを再生した場合の画面です。
この例では、2つはミックスしてHDMI出力へ、1つはPiDAC+へ出力設定しています。

3つの音声を再生している例

この記事が気に入ったらサポートをしてみませんか?