LECTURE 1 カーネル組み込みサウンド機能の設定

○ はじめに

ここでは、以降のサンプルプログラムで使用する API を提供している OSS ( Open Sound System ) ( 正しくは OSS/Free ) について説明した後、サウンド機能の設定について簡単に説明していきます。

○ OSS ( Open Sound System )

Linux® のサウンド機能は、当初 OSS ( Open Sound System、商用 ) の非商用版である OSS/Free がカーネルに取りこまれる形で提供されました。その後カーネル 2.2 系列に移行する際に若干仕組みが変わったようで、新たなサウンド機能の枠組みが構築され従来の OSS/Free 提供のモジュールはその枠組みの配下で動作する様になりました (と思います m(__)m )。

この流れとは別に、ALSA ( Advanced Linux Sound Architecture ) と呼ばれるサウンドドライバシステムがあります。ALSA は OSS よりも強力なサウンド API を作ろうという意図でたちあがったプロジェクトで、OSS の方で対応していないサウンドカードにも対応している場合があります。あちこちの情報を見ると、ALSA の方が音質が良いという意見が多数うかがえます。なお、Linux カーネル 2.5.x において ALSA がカーネルにマージされた様です ( 正確にどのバージョンからかは調査していません )。

ALSA は OSS 互換 API を提供しているので、OSS API によるプログラミングが可能です。

OSS API では、通常のキャラクタデバイスの操作と同様にサウンドドライバを操作します。つまり、open() でデバイスファイルを開き、read() で読み出し、write() で書き出し、ioctl() でデバイスの設定を行います。OSS でのサウンドドライバの構成は図 1 の様になっています。

--- 図 1 ---
001structure.jpg

以下に各デバイスファイルの概要を記します。

  • /dev/mixer

    /dev/mixer は、様々な入出力音源のレベルの調整、入力源の選択、入力信号の重ね合わせを 行うためのデバイスファイルです。複数のミキサーデバイスが存在する場合は、/dev/mixer1 以降 のデバイスファイルが存在します。

  • /dev/sndstat

    このデバイスファイルは、サウンドドライバの情報を人間が読みやすい形式にして 出力するためのものであり、サウンドプログラミングには使用しません。'cat /dev/sndstat' とするとサウンドドライバに関する情報が出力されます。

  • /dev/dsp

    /dev/dsp は、PCM データの再生、およびアナログ入力をサンプリングして 録音するためのデバイスファイルです。デジタルサンプリング用のデバイスが複数存在する場合は /dev/dsp1 以降のデバイスファイルが存在します。デフォルトの入力源はマイク入力 になっています。

  • /dev/audio

    /dev/dsp とデフォルトのサウンドフォーマットが異なるだけで、他は全く /dev/dsp と同じです。

  • /dev/sequencer

    サウンドカード内部のシンセサイザデバイスや、MIDI ポートへ接続された外部シンセサイザ デバイスに対するアクセスを提供するデバイスファイルです。

  • /dev/midi

    MIDI バスへの低レベルなアクセスを行うためのデバイスファイルです。


○ カーネルの設定およびモジュールのロード

実際に音を鳴らすためには、まずカーネルのサウンド機能を有効にする必要があります。以降の説明は Linux カーネル 2.2.x を対象とします ( 2.4.x でも同様に設定できます。2.5.x で ALSA がマージされた以降については調べてないので分かりません m(__)m )。なお、( カーネル 2.2.x 〜 2.4.x で ) ALSA を使用する場合でも、以下の手順の 1 のみは行う必要があります ( ALSA のドライバが 1 で有効になるモジュールを必要としている )。

make menuconfig、make xconfig などでカーネルの設定メニューに入り、Sound について設定します。

  1. Sound を y か m にする。
  2. OSS sound modules という項目までに自分が使用するサウンドカードが存在するなら、 その項目を y か m にして終了する。
  3. 2 で該当項目が存在しなかったら、OSS sound modules を y か m にする。
  4. Additional low level sound drivers までに自分が使用するサウンドカードが存在するなら、 その項目を y か m にして終了する。
  5. Additional low level sound drivers を y か m にして、自分が使用するサウンドカード を y か m にして終了する。
  6. まだ使用するサウンドカードが出て来なかったら、Linux Sound System ではまだ対応していないので、あきらめて ALSA を導入する。

以上を設定したらカーネルをコンパイルして、そのカーネルでシステムを再起動します。全てについて y を選択した場合はサウンド機能が完全にカーネルに組み込まれるため、起動時にサウンドカードを認識するはずです。起動中のメッセージで確認してみて下さい。

一部、あるいは全てをモジュールにした場合は、起動した後にモジュールをロードする必要があります。

前述の手順の 1 に対応するモジュールは soundcore.o です。これを m にした場合は soundcore.o をロードします。

insmod soundcore.o

2 で使用するサウンドカードが存在した場合は、対応するモジュールをロードします。下の例では insmod を使っていますが、ロード時に unresolved symbol なんとかがたくさん出る様であれば modprobe を使用して下さい。必要なモジュールを全てロードしてくれます。なお、2 で選択できるモジュールは全て soundcore.o を必要とします。

insmod [自分が選択したカードに対応するモジュール].o

3 を m にした場合は、sound.o をロードします。

insmod sound.o

sound.o は、元々 OSS/Free として配布されていたサウンドモジュールを使用するためのモジュールの様です。もしくは、これも OSS/Free として配布されていたのかもしれません。その辺良く分かっていませんが、4 で選択できるモジュールは OSS/Free として配布されていたものであり、それらを使用するためにこのモジュールが必要です。また、この sound.o は soundcore.o を使用します。

4 で使用するサウンドカードが存在した場合は、対応するモジュールをロードします。ここで選択できるモジュールは sound.o を使用するため、先に sound.o ( + soundcore.o ) をロードしておかなければいけません。また他のモジュールの機能を使用する場合もある様なので、こちらは modprobe で組み込む方が無難かもしれません。

5 については soundlow.o をロードします。このモジュールは OSS/Free に含まれない低レベルのサウンドドライバを使う場合に必要と Help に書かれています。この場合は、6 で選択したモジュールも併せてロードします。

○ /etc/modules.conf の記述

前節で説明した様にしてモジュールをロードしますが、毎回手動でロードするのは面倒です。ので、起動時に実行されるスクリプト ( rc.local など ) に処理を記述しておくか、/etc/modules.conf に必要な事項を記述しておくことで自動的にモジュールをロードしてくれる様にします。ここでは modules.conf に何を書いておけば良いかについて説明します。

まず、modules.conf ではなく conf.modules なのではないか?とか、どっちに設定するのが正しいのか?とかいろいろ意見があるかもしれませんが、これは modutils のバージョンによるというのが回答です。

modutils とはカーネルと一緒の場所で配布されているユーティリティプログラムの集まりで、insmod や modprobe などのツールが含まれています。カーネルが必要に応じてモジュールをロードする場合、ユーザ空間で modprobe を実行します。この時、設定ファイルの指定無しで modprobe を実行するのですが、設定ファイルの指定無しの場合に参照されるデフォルト値が modutils 2.3.4 以降では /etc/modules.conf であり、それより前のバージョンでは /etc/conf.modules になっているのです。なお、modutils のバージョンは /sbin/lsmod --version か /sbin/modprobe -V で確認できます。

次に何を書けば良いかについて、最も単純な記述例をお見せします。

  1. soundcore.o をカーネル組み込みにした場合
      alias sound-slot-0 [使用するサウンドカードに対応したモジュール名]
    
    
  2. soundcore.o をモジュールにした場合
      alias char-major-14 [使用するサウンドカードに対応したモジュール名]
    
    

    もしくは

      alias char-major-14 soundcore
      alias sound-slot-0 [使用するサウンドカードに対応したモジュール名]
    
    

上の記述例において、使用するサウンドカードに対応したモジュール名には .o を付けません。

何故この様な記述をするかについて、アプリケーションが /dev/dsp などのサウンド用デバイスファイルにアクセスした際にカーネルがどのようにモジュールを組み込むかと共に説明します。

アプリケーションが /dev/dsp などのキャラクタデバイスファイルにアクセスした場合、対応するモジュールが組み込まれていればそのモジュールにアクセスが転送されます。前述の 1 の例の場合、soundcore.o は既にカーネルに組み込まれています。soundcore.o に初めてアクセスした時には、sound-slot-%i という名前で参照されるモジュールのロードが実行されます ( %i はサウンドカードの番号。1枚目は 0、それ以降 1, 2, ... と続く )。よって、1 の例の様に sound-slot-%i という名前に対して使用するサウンドカード用のモジュールを割り当てておけば良いのです。

次に 2 の例の様にデバイスファイルに対応するモジュールがロードされていない場合、カーネルは対象のデバイスファイルのメジャー番号を指定して modprobe を実行します。メジャー番号とはデバイスを区別するための番号であり、/dev/dsp などのサウンド用デバイスファイルは通常 14 となっています。この時 modprobe の引数には char-major-14 という文字列が指定されます。よって、char-major-14 という名前に対して使用するモジュールを割り当てておけば良いことが分かります。

1 の例の説明を考えると、2 の例の場合は後者の方が正当な書き方だと僕は思いますが、前者の様に書くと必要なモジュールが順次組み込まれるためそれはそれで問題は無いと思います。ちなみに modutils 2.3.5 以降では char-major-14 に対してデフォルトで soundcore が設定されているため、その行は省略できます。modutils 2.3.5 以前では char-major-14 に対して sound がデフォルト値に設定されていますが、sound.o が soundcore.o を使用するため soundcore.o も自動的にロードされます。

書いてみて気付きましたが、結局 soundcore の設定は省略できるのですね。。。(笑)

以上の設定によって基本的にはサウンドを使用できるはずなのですが、モジュールによっては /dev/dsp は有効になるけど /dev/mixer は有効にならないとか、/dev/midi は使えないといった差異が生じる場合があります。ドライバが全く対応していない場合を除けば、以下の様にして直接指定すれば使用できる可能性もあります。

alias sound-service-0-0 [/dev/mixer     用のモジュール名]
alias sound-service-0-1 [/dev/sequencer 用のモジュール名]
alias sound-service-0-2 [/dev/midi      用のモジュール名]
alias sound-service-0-3 [/dev/dsp       用のモジュール名]
alias sound-service-0-6 [/dev/sndstat   用のモジュール名]

sound-service-%i-%n は、soundcore.o が sound-slot-%i に対応したモジュールをロードした後に続けてロードされます。%i はサウンドカード番号 ( 1 枚目は 0、2 枚目は 1、... )、%n はサウンド機能の別を表す番号です。%i が 0 の場合はデバイスファイルのマイナー番号になります。%i が 0 で無い場合は、%i とサウンド機能番号の組に対応した値になっています ( 具体的な値の算出については調べていません )。また、使用するモジュールによって対応しているサウンド機能が異なります。

なお、モジュールによってはオプション値を設定しなければならない場合もあります。例えば ISA のカードを使用する場合などには、ベース IO ポートなどを指定しなければなりません。オプション値を指定する例として、ISA の SoundBlaster を使用する場合の記述例を以下に示します。

alias sound-slot-0 sb
options sb io=0x220 irq=7 dma=1 dma16=5 mpu_io=0x330

insmod などで直接ロードする場合は、/sbin/insmod sb io=0x220 irq= ... の様に指定します。オプションとして指定できる変数に何があるのか、そのオプションにどういう値を指定すれば良いのかについてはサウンドドライバ次第になるので、ここでは説明しきれません。個々の詳細についてはサウンドカード名などで検索するなどして調べてみて下さい。