試験運用中なLinux備忘録・旧記事

はてなダイアリーで公開していた2007年5月-2015年3月の記事を保存しています。

/dev/dspを使用するアプリケーションからaossを使用してALSAで音を鳴らすときの設定

GNU/Linux上で音を出すアプリケーションには、新しいALSAライブラリ経由で出すものと、古いOSS APIを使用して出すものとがある。*1
ALSAにはOSSエミュレーションモードがあり、snd-pcm-oss,snd-seq-oss,snd-mixer-ossといったカーネルモジュールが読み込まれているか、これらの機能をカーネルに組み込んでビルドして使っている場合、そのままでも音は鳴らせるし、シーケンサやミキサーもエミュレーションで使用できる。
しかし、その場合、OSS APIを使用したアプリケーションがデバイス/dev/dspを握ってしまい、そのアプリケーションが動作している間、他のアプリケーションからは音が出せなかったりする。更に、ミキサーの設定がALSA用と完全互換でなかったりなど制約もあるため、OSSサウンドAPIアプリからALSAライブラリ経由で音を出す「alsa-oss」というパッケージに含まれる、aossというコマンドを使用するとよい。
aossを使用した場合、ALSAのデフォルトのPCMデバイスは使用されず、pcm.dsp0というデバイスが使用される*2。Web上の設定例を参考に、ソフトウェアボリューム(softvol)と、多重再生をするためのdmixを通して使用するための設定を作成した。

ファイル名: ~/.asoundrc

pcm.dsp0
{
  type plug
  slave.pcm
  {
    type softvol  # ALSAのソフトウェアボリュームコントロールを使用
      # 必要に応じてdmixへの引数(CARD, DEV, SUBDEV, FORMAT, RATE)を指定
      # 「slave.pcm "dmix"」だけで不具合が無ければそれでもOK
    slave.pcm "dmix:0,0,-1,S16_LE,44100"
    control
    {
      name "PCM Playback Volume"
      card 0
    }
  }
}

ctl.mixer0
{
  type hw
  card 0
}

上の設定では、dmixで多重再生する場合、先にALSA対応プレーヤーで音声を再生していると、dmixのレートがデフォルト値(defaults.pcm.dmix.rate)=48000Hzで使用されるため、後から入るaoss経由の音声(44100Hz)は途切れ途切れになる(逆の順番の場合はALSAのプレーヤーが44100Hzに合わせて綺麗に音が出る)。これを防ぎたい場合は
ファイル名: ~/.asoundrc

defaults.pcm.dmix.rate 44100

と、dmixのデフォルトのレートを44100Hzにする設定を追加する。
なお、この設定では、予め定義されているdmixデバイス「pcm.dmix」を使用し、独自のdmixデバイスの定義はしていない(手抜きのためと、設定を短くするため)。
(2011/1/20)出力先のPCM名は環境変数ALSA_OSS_PCM_DEVICEでも指定可能で、${HOME}/.asoundrcの記述よりも優先順位が高い。まとめドキュメントも参照。

まとめドキュメント:

*1:プレーヤーなどで、どちらにも対応している場合もあるし、各種サウンドサーバを経由して音を出すようなものもある

*2:環境変数ALSA_OSS_PCM_DEVICEでPCMデバイス名は変更可能

LADSPAについて

Linux Audio Developer's Simple Plugin API (LADSPA)は、既存の音声データに対して様々なフィルタをかけたり、音声を生成したりといったことを行うプラグインAPI。これに基づいて作成されたプラグインを用いると、LADSPAに対応したアプリケーション全てで同じように利用できる*1

プラグインの入手

ディストリのパッケージになっているものが多い。他にもまだある。下はGentoo Linuxのパッケージ名だが、DebianUbuntuにも結構用意されているようだ。

  • ladspa-sdk
  • ladspa-cmt
  • caps-plugins
  • fil-plugins
  • mcp-plugins
  • rev-plugins
  • swh-plugins
  • tap-plugins

プラグインの配置場所と環境変数LADSPA_PATH

プラグインの標準的な配置場所は/usr/lib/ladspa/以下になる。対応ソフトウェアから利用する場合、この場所を環境変数LADSPA_PATHの値に設定しておく必要があるが、Gentoo Linuxでは自動的に設定されている。

プラグインの情報を取得

LADSPAプラグインは、ライブラリと同様、.soファイルという形で存在しているが、1つの.soファイルには複数のプラグインを含めることができるため、どのプラグインを使うのかをファイル名だけでは識別できない。
LADSPAプラグインには、プラグインを識別するためのユニークIDとラベルが存在する。このいずれかを指定することで、使用するプラグインが定まるのだが、これらは、プラグイン情報の取得を行うanalyzepluginというコマンドで行う。下の例では、IDが1950でラベルが「G2reverb」であることが分かる。更に、その他の様々な情報が取得できていることも分かる。

$ analyseplugin /usr/lib/ladspa/g2reverb.so

Plugin Name: "Stereo reverb"
Plugin Label: "G2reverb"
Plugin Unique ID: 1950
Maker: "Fons Adriaensen <fons.adriaensen@alcatel.be>"
Copyright: "GPL"
Must Run Real-Time: Yes
Has activate() Function: Yes
Has deativate() Function: Yes
Has run_adding() Function: No
Environment: Normal or Hard Real-Time
Ports:  "In L" input, audio
        "In R" input, audio
        "Out L" output, audio
        "Out R" output, audio
        "Room size" input, control, 10 to 150
        "Reverb time" input, control, 1 to 20
        "Input BW" input, control, 0 to 1
        "Damping" input, control, 0 to 1
        "Dry sound" input, control, -80 to 0
        "Reflections" input, control, -80 to 0
        "Reverb tail" input, control, -80 to 0

プラグインへの引数

上のanalyzepluginの例の出力結果の後ろのほうに「Ports:」というセクションがあり、その中に「control」を含む幾つかの項目があるのが分かる。この部分がプラグインへの引数に関する記述で、項目名とデータ範囲(例: 10 to 150)が指定されている。更にデフォルト値が表示されるものもあるが、データ範囲すら表示されないものもある。

引数の調整・テスト

実際の引数を色々といじって調整しながら値を決めてゆくことになるが、その際には、Audaciousのエフェクトプラグイン「LADSPA host」を使うことで、自由にLADSPAプラグイン(複数可)を登録でき、値もGUIでリアルタイムに設定・反映できるので便利。
(2008/1/16)JACK Audio Connection KitとJACK Rack(http://jack-rack.sourceforge.net/)を使用することでも色々なLADSPAプラグインを試すことができ、エフェクタとしての用途でも使える。

*1:AudaciousMPlayerのようなプレーヤーでは、再生フィルタとして、Audacityのようなオーディオエディタではデータを編集するフィルタ機能として、という違いはある

ALSAでLADSPAプラグインを使用する

ALSAのPCMプラグインの中に、LADSPAプラグインを扱う「ladspa」という種類がある。これを使用することで、ALSA経由で音を出す際にフィルタがかけられる*1
(2007/6/29)alsa-libのバージョン1.0.14_rc4を含む、それ以降のバージョンにおいて、LADSPAプラグインの使用に不具合が出るようになっていて、再生ができない。1.0.14_rc3を使用すれば問題ないが、今後、注意が必要。
(2007/9/30)上記不具合は、alsa-lib 1.0.15_rc2の時点では解消された。

設定例(仮)

ファイル名: ~/.asoundrc

pcm.test
{
  type softvol  # softvolを使用
  slave.pcm "plug:ladspa-test"
  control
  {
    name "PCM Playback Volume"
    card 0
  }
}

pcm.ladspa-test
{ # CAPS-plugins (caps.so)
  type ladspa
  slave.pcm "plug:dmix:0"  # plugでdmixにつなげる(別のladspaを経由してもOK)
  playback_plugins
  [
    {
      id 1773  # ラベルで指定するのであれば「label Eq」と記述
      input
      { # 31 Hz | 63 | 125 | 250 | 500 | 1k | 2k | 4k | 8k | 16k
        # controls [0 0 0 0 0 0 0 0 0 0] # -48 ... 0(default) ... 30
        controls [8.5 8.5 7.5 5 -2 -4 -2 7 9 10]  # 好みに応じて設定
      }
    }
  ]
}

この設定では、デフォルトのPCMデバイスを上書きしているわけではないので、実験するためには、ALSAのPCMデバイス名を明示的に指定する必要がある。

$ mplayer -ao alsa:device=test /path/to/audiofile

複数のプラグインを組み合わせる

1つの「ladspa」なPCM定義の中に複数のプラグインの記述をすることは可能だが、個人的にはPCMデバイス当たり1プラグインにして、次々とつなげてゆく形にしたほうが便利と思い、以下のような設定を作成した。

ファイル名: ~/.asoundrc

pladspa.slave.pcm "plug:ladspa-1773-Eq:ladspa-1950-G2reverb:plug:dmix:0"
#pladspa.slave.pcm "plug:ladspa-1773-Eq:plug:dmix:0"

pcm.pladspa
{
  type softvol  # softvolを使用
  slave.pcm
  {
    @func refer
    name pladspa.slave.pcm  # pladspa.slave.pcmの値をslave.pcmに指定
  }
  control
  {
    name "PCM Playback Volume"
    card 0
  }
}

pcm.ladspa-1773-Eq
{ # CAPS-plugins (caps.so)
  @args [ SLAVE ]  # 引数SLAVEを取る
  @args.SLAVE.type string
  type ladspa
  slave.pcm $SLAVE  # 引数名が次のPCM名になる
  playback_plugins
  [
    {
      id 1773
      input
      { # 31 Hz | 63 | 125 | 250 | 500 | 1k | 2k | 4k | 8k | 16k
        # controls [0 0 0 0 0 0 0 0 0 0] # -48 ... 0(default) ... 30
        controls [8.5 8.5 7.5 5 -2 -4 -2 7 9 10]
      }
    }
  ]
}

pcm.ladspa-1950-G2reverb
{ # REV-plugins (g2reverb.so)
  @args [ SLAVE ]
  @args.SLAVE.type string
  type ladspa
  slave.pcm $SLAVE
  playback_plugins
  [
    {
      id 1950
      input
      { # Room size | Reverb time | Input BW | Damping
        #  | Dry sound | Reflections | Reverb tail
        # controls [80 10.5 0 0 0 0 0]
        controls [150 1 0 0 0 -15 0]
      }
    }
  ]
}

(2007/11/23)「ladspa.slave.pcm」が定義されているとAudacity 1.3.4

$ audacity
audacity: pcm_params.c:187: snd_pcm_hw_param_get_min: Assertion `!snd_interval_empty(i)' が失敗しました.

となってアボートするため、「ladspa」の部分を「pladspa」に変更したところがある


下は、MPlayerを用いた実験例。

$ mplayer -ao alsa:device=pladspa (ここに適当な音声ファイルの場所を指定)

このような形で書いておくと、使用するプラグイン構成を変更したいときにslave.pcmをいちいち書き換えないで、簡単に管理できる。

*1:プラグインの種類や数によっては、多少の遅延とCPU負荷がかかる

ALSA対応アプリケーションのPCMデバイス指定

${HOME}/.asoundrcなどに独自のPCMデバイスの定義をしている場合、アプリケーションからはそのままでは使用されず、使用するには、アプリケーションごとに固有の方法で指定する必要がある。

ALSA PCMデバイス名の指定方法
アプリケーション設定方法
Audaciousオーディオの設定のALSA出力プラグインの「オーディオデバイス」にデバイス名を入力
MPlayerコマンドラインオプションに-ao alsa:device=[デバイス名]
SDLアプリケーション(ALSA有効)環境変数AUDIODEVにデバイス
TiMidity++環境変数TIMIDITY_PCM_NAMEにデバイス
QEMU環境変数QEMU_ALSA_DAC_DEVにデバイス*1

(2008/1/6)SDLアプリケーションにはALSAサポートが必要な件について補足すると、Debian/Ubuntuでは「libsdl1.2debian-alsa」が入っている必要がある。GentooではlibsdlのUSEフラグに「alsa」が必要。
(2008/10/30)SDLALSA以外のオーディオのサポートが有効な場合、環境変数SDL_AUDIODRIVERの値を「alsa」にした上でAUDIODEVによるPCMデバイス名を指定することになる。

*1:QEMU_AUDIO_DRV=alsa QEMU_AUDIO_DAC_FIXED_FREQ=48000 QEMU_AUDIO_ADC_FIXED_FREQ=48000 QEMU_ALSA_DAC_DEV=[デバイス名] qemu ... のような形で実行