JavaTM Sound API では柔軟なシステム構成手法を採用しています。1 台のコンピュータにさまざまな種類のオーディオデバイス (ミキサー) をインストールできます。この API では、インストールされているデバイスの種類とその機能についての前提事項はほとんどありません。その代わりに、どのオーディオコンポーネントが利用可能であるか、およびそれらのコンポーネントにプログラムからアクセスする方法をシステムから通知させます。
この章では、どのようなサンプリングオーディオリソースがコンピュータにインストールされているかをプログラムで確認する方法、および利用可能なリソースへのアクセスを得る方法について説明します。この場合のリソースには、ミキサーおよび、ミキサーに所属する各種のラインも含まれます。
AudioSystem
クラスは、組み込みサービスおよびサードパーティプロバイダが個別にインストールしたサービスを含む、オーディオコンポーネントの情報センターの役目をします。AudioSystem
は、インストールされたサンプリングオーディオリソースにアプリケーションプログラムがアクセスするためのエントリポイントになります。AudioSystem
に問い合わせて、どのようなリソースがインストールされているかを調べ、次にそれらのコンポーネントへのアクセスを取得できます。たとえば、特定の構成 (例: 前章のラインの説明で記した入出力構成のいずれか) を持つミキサーがあるかどうかを AudioSystem
に問い合わせることからアプリケーションプログラムを始めることができます。次に、プログラムはミキサーからデータラインなどを取得できます。
アプリケーションプログラムが AudioSystem
から取得できるリソースには次のようなものがあります。
一般に、システムには複数のミキサーがインストールされています。通常はオーディオ入力用とオーディオ出力用の、少なくとも 1 つずつのミキサーがあるのが普通です。また、ミキサーに I/O ポートがない場合もありますが、その場合はこれらはアプリケーションプログラムから音声を受け取り、ミキシングした音声をプログラムに返送します。AudioSystem
クラスにより、インストールされているすべてのミキサーのリストが提供されます。
各々のラインはミキサーに関連づけられていますが、アプリケーションプログラムで明示的にミキサーを扱わなくても AudioSystem
から直接ラインを取得することができます。
アプリケーションプログラムは、形式変換を使用してオーディオデータの形式を別の形式に変換できます。変換については第 7 章「ファイルコンバータおよび形式コンバータの使用」を参照してください。
AudioSystem
クラスは、オーディオファイルとオーディオストリーム間の変換を行うためのメソッドを提供します。また、AudioSystem
クラスは、サウンドファイルのファイル形式を通知したり、別の形式でファイルを作成することができます。これらの機能については第 7 章「ファイルコンバータおよび形式コンバータの使用」を参照してください。
Java Sound API のクラスの中には、関連インタフェースについて有用な情報を提供するものがいくつかあります。たとえば、Mixer.Info
は、インストールされているミキサーのベンダー、名前、説明、バージョンなどの詳細情報を提供します。Line.Info
は特定のラインのクラスを取得します。Line.Info
のサブクラスには Port.Info
と DataLine.Info
があり、Port.Info
は特定のポート、DataLine.Info
は特定のデータラインに関する詳細を取得します。これらのクラスの各々についてはこのあとで、それぞれの節で説明します。Info
オブジェクトと、そのオブジェクトが記述するミキサーまたはラインオブジェクトを混同しないよう注意してください。
通常、Java Sound API を使用するプログラムは最初の仕事の 1 つとして、ミキサー、またはミキサーのラインの少なくとも 1 本を取得します。それによりコンピュータの内外にサウンドを移動できます。使用するプログラムで特定の種類のミキサーが必要な場合や、利用可能なミキサーのリストを表示してユーザがミキサーを選択できるようにする場合があります。どちらの場合も、どのような種類のミキサーがインストールされているかを知る必要があります。AudioSystem
には次のメソッドがあります。
このメソッドから返されるstatic Mixer.Info[] getMixerInfo()
Mixer.Info
オブジェクトの各々は、インストールされているミキサーのタイプを示します。通常、1 つのシステムでは 1 つのタイプのミキサーが指定されている程度です。仮に複数タイプのミキサーが指定されていても、返された配列内にはそのタイプの Mixer.Info
は 1 つしかありません。アプリケーションプログラムは、Mixer.Info
オブジェクトの配列を反復して調べ、必要なミキサーを探します。Mixer.Info
には、ミキサーの種類を示す次の文字列が含まれています。
これらは任意の文字列なので、特定のミキサーを必要とするアプリケーションプログラムは、予期すべき文字列と文字列の比較対象を知っていなければなりません。 ミキサーの製造元は、この情報を文書に記載すべきですが、 一般には特定のミキサーを必要としない場合が多く、この場合はアプリケーションプログラムはすべての Mixer.Info
オブジェクトの文字列を表示して、ユーザにミキサーを選択させます。
適切なミキサーが見つかったら、アプリケーションプログラムは次の AudioSystem
メソッドを呼び出して、目的のミキサーを取得します。
プログラムが特定の機能を持つミキサーを必要とするが、特定のベンダーが製造したミキサーでなくてもよい場合があります。また、選択すべきミキサーをユーザが知っていることをあてにできない場合があります。このような場合は、static Mixer getMixer(Mixer.Info info)
Mixer.Info
オブジェクト内の情報はあまり役に立ちません。その代わり、getMixerInfo
から返されるすべての Mixer.Info
オブジェクトを繰り返し実行し、getMixer
を繰り返し呼び出すことによりミキサーを取得し、そのミキサーの機能を調べることができます。たとえば、ミキシング済みのオーディオデータを特定の本数のターゲットデータラインに同時に書き込むことのできるミキサーが必要だとします。この場合は、この Mixer メソッドを使って各々のミキサーに問い合わせを行います。
int
getMaxLines(Line.Info info)
ここで、Line.Info
は TargetDataLine
を指定します。Line.Info
クラスについては、次のセクションで説明します。
AudioSystem
オブジェクトからラインを直接取得
AudioSystem
オブジェクトからすでに取得済みのミキサーからラインを取得します (この章の「ミキサーの取得」を参照)。
ここでミキサーをまだ取得しておらず、使用するプログラムが特定の種類のラインだけを必要とする単純なプログラムだとします。ミキサーの詳細情報は重要ではありません。この場合は、 AudioSystem
メソッドを使用できます。
これは、すでに説明したstatic Line getLine(Line.Info info)
getMixer
メソッドと類似しています。Mixer.Info
と異なり、引数として使用される Line.Info
は目的のラインを指定するためのテキスト情報を持っていません。その代わり、目的のラインのクラスに関する情報を持っています。
Line.Info
は抽象クラスなので、ラインを取得するには、そのサブクラスのどれか (Port.Info
または DataLine.Info
) を使います。次のコード (抜粋) では、DataLine.Info
サブクラスを使ってターゲットデータラインを取得し、開きます。
このコードでは、クラスとオーディオ形式以外の属性を指定せずにTargetDataLine line; DataLine.Info info = new DataLine.Info(TargetDataLine.class, format); // format is an AudioFormat object if (!AudioSystem.isLineSupported(info)) { // Handle the error. } // Obtain and open the line. try { line = (TargetDataLine) AudioSystem.getLine(info); line.open(format); } catch (LineUnavailableException ex) { // Handle the error. //... }
TargetDataLine
オブジェクトを取得します。その他の種類のラインを取得するためにも、これに類似したコードを使用できます。SourceDataLine
または Clip
の場合は、そのクラスを line 変数のクラスとして TargetDataLine
の代わりに使用し、DataLine.Info
コンストラクタの最初の引数にもそのクラスを使用します。
Port
の場合は、次のようなコードの中で Port.Info
の static インスタンスを使用できます。
ミキサーが目的のタイプのラインを持っているかどうかを知るためのif (AudioSystem.isLineSupported(Port.Info.MICROPHONE)) { try { line = (Port) AudioSystem.getLine( Port.Info.MICROPHONE); } }
isLineSupported
メソッドの使用法に注目してください。
すでに説明したように、ソースラインは、ミキサーが音声入力デバイスを表している場合はミキサーへの入力すなわち Port
オブジェクトであり、ミキサーが音声出力デバイスを表している場合は SourceDataLine
または Clip
オブジェクトです。同様に、ターゲットラインはミキサーの出力です。つまり、音声出力ミキサーの場合は Port
オブジェクト、音声入力ミキサーの場合は TargetDataLine
オブジェクトです。ミキサーが外部ハードウェアデバイスにまったく接続されてない場合もあります。たとえば、アプリケーションプログラムから音声を受け取り、ミキシング済みの音声をそのプログラムに返送する内部ミキサーや完全なソフトウェアミキサーなどです。この種のミキサーには、入力ラインの代わりに SourceDataLine
または Clip
オブジェクトがあり、出力ラインの代わりに TargetDataLine
オブジェクトがあります。
インストールされているミキサーでサポートされているソースラインとターゲットラインのタイプを指定して詳細を調べるには、次の AudioSystem
メソッドを使用できます。
これらのメソッドの各々から返される配列内の各々のオブジェクトは一意のタイプのラインですが、必ずしもすべてのラインが示されるとは限りません。たとえば、1 つのミキサーのラインのうちの 2 本または、異なるミキサーの 2 本のラインが同一のstatic Line.Info[] getSourceLineInfo(Line.Info info) static Line.Info[] getTargetLineInfo(Line.Info info)
Line.Info
オブジェクトを持つ場合は、その 2 本のラインは返された配列の中の 1 つの Line.Info
によって表されます。
Mixer
インタフェースには、すでに説明したソースラインとターゲットラインのためのさまざまな AudioSystem
のアクセスメソッドがあります。これらの Mixer
メソッドには、AudioSystem
のメソッドと同様に Line.Info
引数をとるものもありますが、引数を取らない形式を含むものもあります。
これらのメソッドは、特定のミキサーのすべてのLine.Info[] getSourceLineInfo()
Line.Info[] getTargetLineInfo()
Line.Info
オブジェクトの配列を返します。配列を取得したら、繰り返し実行して、Mixer
の getLine
メソッドを呼び出して各ラインを取得し、次に Line
の open
メソッドを行って各々のラインをプログラムで使用できるよう予約します。
前節では目的のタイプのラインを取得する方法を説明しましたが、他のタイプのラインとポートについても同じことが当てはまります。Line.Info
引数を取る AudioSystem
(または Mixer
) メソッドであるgetSourceLineInfo
と getTargetLineInfo
に Port.Info
オブジェクトを渡すことにより、すべてのソース (入力) ポートとターゲット (出力) ポートを取得できます。次に、返されたオブジェクト配列に対して Mixer の getLine
メソッドを繰り返して、各ポートを取得します。
次に、Line
の open
メソッドを呼び出して各々の Port
を開きます。ポートを開くとは、そのポートをオンにすること、つまりポートを介したサウンドの往来を許可することを意味します。また、ポートを取得する前にいくつかのポートがすでに取得されている場合は、サウンドの移動に使用されるポートを閉じることができます。プラットフォームによってはデフォルトですべてのポートが解放されており、また、ユーザかシステム管理者が他のアプリケーションプログラムか OS のソフトウェアを使って特定のポートをオンまたはオフに設定している場合があります。
注意: ここで説明した方法でポートを開けば、特定のポートを選択して、そのポートに実際にサウンドが往来しているかどうかを確認することができます。しかし、これはユーザフレンドリーではない印象を与える場合があります。たとえば、同僚の迷惑にならないように、ユーザがスピーカのポートをオフにしているかもしれません。プログラムがユーザの意に反して突然音楽を鳴らし始めたら、気分を害することもありえます。別の例として、盗聴を防ぐために、ユーザが知らないときにコンピュータのマイクロフォンが絶対にオンにならない保証が欲しい場合があります。一般に、ユーザインタフェースによって表現されるようなユーザの意図に対して、プログラムが応答する場合以外は、プログラムでポートの開閉を行わないことを推奨します。ユーザまたは OS がすでに選択している設定を尊重してください。
必ずしも事前にポートの開閉を行わなくても、そのポートが取り付けられているミキサーは正しく機能します。たとえば、ミキサーのすべての出力ポートが閉じていても、サウンドの再生を開始してオーディオ出力ミキサーに送ることができます。データはミキサーに入り続け、再生は止まりません。ただし、ユーザには何も聞こえません。ユーザが出力ポートを開くと、その時点でポートから出るサウンドは聞こえる音になります。再生が及んだメディア内のどこからでも開始できます。
また、ミキサーに特定のポートがあるかどうかを知るためにポートをアクセスする必要はありません。たとえば、ミキサーが実際にオーディオ出力ミキサーかどうかを知るために、getTargetLineInfo
を呼び出して、そのミキサーが出力ポートを持っているかどうかを調べることができます。設定 (開閉状態、ポートに備わっているコントロールの設定など) を変更したい場合を除き、ポート自体をアクセスする必要はありません。
Java Sound API には、AudioPermission
クラスがあります。そのサンプリングオーディオシステムに対してアプレット (またはセキュリティマネージャ付きで実行しているアプリケーションプログラム) が実行できるアクセスの種類を示します。録音のパーミッションは別々に制御されます。不正な盗聴などのセキュリティ上の危険を防ぐため、このパーミッションを与える際は注意すべきです。デフォルトでは、アプレットとアプリケーションは次のようにパーミッションを与えられます。
アプレットとアプリケーションのどちらでも、録音のための明示的なパーミッションを与えられている場合は、セキュリティマネージャ付きで実行していても録音が可能です。
プログラムに録音 (または再生) のパーミッションが与えられていない場合は、ラインを開こうとすると例外がスローされます。パーミッションは API によって変更することができないので、この場合は、例外を受け取ってユーザに問題を報告する以外にプログラムでできることはありません。それ以外に何かを行っても、安全が保証されていないので無意味です。一般に、パーミッションは 1 つまたは複数のポリシー設定ファイルに設定されています。ユーザまたはシステム管理者はテキストエディタまたは Policy Tool プログラムを使ってこの設定ファイルを編集することができます。
セキュリティとパーミッションの詳細については、 http://java.sun.com/products/jdk/1.3/docs/guide/security の 「Security Architecture」 と 「Policy Permissions」、および Java Tutorial http://java.sun.com/docs/books/tutorial/ の 「Specialized Trails」 にあるセキュリティに関する項目を参照してください。