ルギア君の戯言

雑多な記事。

最強の Linux サウンドシステム (多分)


OSS, ALSA, Jack, PulseAudio のアプリを全部同時に使える、まさに究極のシステム…だと思う。

図の黒線は再生系統、赤線は録音系統。

制限事項

  • OSS については占有までシミュレーションする (というか API がファイルロックする?) ため、同方向の OSS のアプリを同時に2つ使うことはできない。
  • OSS アプリと ALSA アプリを同時に使った場合はブロックされないが、後から起動した方は音が鳴らない (ALSA アプリ同士は平気:snd-pcm-oss の仕様?)。
  • MIDI 関係は未確認 (ハードウェア音源を持っているわけでもないし)。

メモ

  • サウンドカードが 2 枚以上装着されている場合、snd-aloop のデバイスは hw:2、hw:3、…と末尾の番号を使うので読み替えてくれ。
  • Jack が握るサウンドカードは通常は 1 枚だけだが、この方法を使うことで Jack ですべてのサウンドカードを統括的に扱うことができるようになる。
  • できる限り Jack を使ったほうが繋ぎ変えなどで有利になるが遅延しやすい場合もある (後述)
  • できる限り他の人に影響を与えないようにする設定である。

必要なカーネルモジュール

  • snd-aloop
  • snd-pcm-oss

Momonga Linux では snd-aloop のモジュールを提供していない(現在の trunk では提供するよう変更済みですのでリビルドは不要です)ため、config ファイルを弄って kernel をリビルドすることで作成する。

ちなみに、再起動してもロードするようにするためには

/etc/module-load.d

に適当な名前のファイルを作って

snd-aloop
snd-pcm-oss

て書いておけば OK。ただし、これは systemd を使っている場合で、init や upstart の場合は設定はまた別なのでご注意を。

リビルド

有りそうでなかった。が、Jack の Firewire サポートの影響でクラッシュしてしまうので、これだけ切ってリビルドする(現在 trunk ではデフォルトでオフになるよう変更済みです)

  • qjackctl (お好みで)
  • jack
  • pulseaudio-module-jack
  • python (2.x 系 3.x 系どちらでも可。)

はインストールする。

OSS の設定

各アプリは ALSA の hw:1 に対応する

/dev/dsp1

を使わせる必要がある (が、これは非対応なアプリも多い)。

ALSA の設定

pcm.dsp0 {      type plug      slave.pcm "default" }

# ------------------------------------------------------
# Custom asoundrc file for use with snd-aloop and JACK
#

# ------------------------------------------------------
# playback device
pcm.aloopPlayback {
  type dmix
  ipc_key 1
  ipc_key_add_uid true
  slave {
    pcm "hw:Loopback,0,0"
    format S32_LE
    rate {
      @func igetenv
      vars [ JACK_SAMPLE_RATE ]
      default 44100
    }
    period_size {
      @func igetenv
      vars [ JACK_PERIOD_SIZE ]
      default 1024
    }
    buffer_size 4096
  }
}

# capture device
pcm.aloopCapture {
  type dsnoop
  ipc_key 2
  ipc_key_add_uid true
  slave {
    pcm "hw:Loopback,0,1"
    format S32_LE
    rate {
      @func igetenv
      vars [ JACK_SAMPLE_RATE ]
      default 44100
    }
    period_size {
      @func igetenv
      vars [ JACK_PERIOD_SIZE ]
      default 1024
    }
    buffer_size 4096
  }
}

# duplex device
pcm.aloopDuplex {
  type asym
  playback.pcm "aloopPlayback"
  capture.pcm "aloopCapture"
}

# ------------------------------------------------------
# default device

pcm.!default {
  type plug
  slave.pcm "aloopDuplex"
}

# ------------------------------------------------------
# alsa_in -j alsa_in -dcloop -q 1
pcm.cloop {
  type dsnoop
  ipc_key 3
  ipc_key_add_uid true
  slave {
    pcm "hw:Loopback,1,0"
    format S32_LE
    rate {
      @func igetenv
      vars [ JACK_SAMPLE_RATE ]
      default 44100
    }
    period_size {
      @func igetenv
      vars [ JACK_PERIOD_SIZE ]
      default 1024
    }
    buffer_size 4096
  }
}

# ------------------------------------------------------
# alsa_out -j alsa_out -dploop -q 1
pcm.ploop {
  type plug
  slave {
    pcm "hw:Loopback,1,1"
  }
}

Jack の設定

Driver を ALSA にし、メインのデバイスを hw:0 にしておくことだけ注意する。(default にしてはいけない)

端末で起動する場合は、

$ jackd -d alsa -d hw:0

QJackCtl を使って ~/.jackdrc を作ってもらうと楽。

PulseAudio の設定

$ cat ~/.pulse/default.pa 
#!/usr/bin/pulseaudio -nF

.nofail

load-module module-jack-sink channels=2 channel_map=front-left,front-right
load-module module-jack-source channels=2 channel_map=front-left,front-right

load-module module-native-protocol-unix
## The following is not mandatory

.ifexists /usr/lib/pulse-0.9/modules/module-x11-publish.so
load-module module-x11-publish
.endif
set-default-sink jack_out
set-default-source jack_in

ALSA と Jack の橋渡し

これをログイン時に動くようにしておく。同時に Jack も起動する。

Phonon

Gstreamer の jack sink を使うように変更する。そのほうが遅延が少ない。変更は qtconfig (Qt4) で。

OSS を使わないといけないアプリ

基本的にはないのだが、一部の Legacy アプリで必要な場合がある。1つ前の記事も参照。

ALSA を使わないといけないアプリ

  • Audacity
  • Timidity (Timidity は OSS と ESD にも対応している。)

など。

Jack を使わないといけないアプリ

  • Qtractor

など。

PulseAudio を使わないといけないアプリ

  • FlashPlayer-plugin + libflashsupport

など。

VLC

Jack よりも ALSA の方が遅延が少ない。うまくプログラムされていないのだろうか。

MPlayer

VLC ほどではないが、ALSA の方が遅延は少ないようである。

ffmpeg

Jack を使う。

$ ffmpeg -f jack -ac 2 -ar 44100 -acodec pcm_f32le -i FFMpeg_output ...

SDL

ALSA

$ SDL_AUDIODRIVER=alsa [SDL Application]

または OSS

$ SDL_AUDIODRIVER=dsp SDL_PATH_DSP=/dev/dsp1 [SDL Application]

http://www.libsdl.org/docs/html/sdlenvvars.html を参照。