翻訳元:Audio Queue Services Programming Guide: About Audio Queues
Audio Queueについて
本章では、Mac OS XにおけるAudio Queueの能力、アーキテクチャ、そして内部の仕組みを学びます。 Audio Queueサービスが録音や再生に使用する、Audio Queue、Audio Queue Buffer、そしてコールバック関数を紹介します。 また、Audio Queueのステータスやパラメータについても見ていきます。 本章を終える頃には、あなたはこの技術を効果的に使うために必要となる概念を、理解していることでしょう。
Audio Queueとは?
Audio Queueは、Mac OS Xで音声の記録、再生を行うために使用するソフトウェアオブジェクトです。
AudioQueueRef
という不透明型で表され、AudioQueue.h
ヘッダファイルで宣言されています。
Audio Queueは以下の働きをします:
- 音声装置との接続
- メモリ管理
- 必要に応じて、音声圧縮形式に見合ったコーデックの使用
- 録音や再生の調停(mediating)
Audio Queueは他のCore Audioインタフェースと一緒に利用することが出来、比較的少ないコード量でアプリケーションに完全なデジタル音声の記録、再生策を構築します。
Audio Queueのアーキテクチャ
全てのAudio Queueは、以下の構成要素から成る同じ一般的な構造を持ちます:
- 少数の音声データの一時的な保管場所となる、一組のAudio Queue Buffer(a set of audio queue buffers)
- Audio Queue Bufferの規則正しい列であるAudio Buffer Queue
- あなたが記述するAudio Queueコールバック関数
アーキテクチャは、Audio Queueの用途が録音なのか再生なのかによって変わります。 その違いは、Audio Queueが自身の入出力を接続方法と、コールバック関数の役割にあります。
録音用のAudio Queue
録音用途のAudio QueueはAudioQueueNewInput
関数で生成され、図1-1で示す構造を持ちます。
録音用Audio Queueの入力側は通常、マイクといった外部の音声ハードウェアと接続されます。 標準の状態では(in the default case)、音声はユーザーがシステム環境設定で設定した、システムのデフォルト音声入力装置から入ってきます。
録音用Audio Queueの出力側は、あなたが記述するコールバック関数を利用します。 ディスクに記録する時は、バッファがAudio Queueから受信した新しい音声データを、コールバックが音声ファイルへと記録します。 しかし、録音用Audio Queueの用途はファイルへの書き込みだけに留まりません。 例えばもう1つの使い方として、リアルタイム音声解析にも利用できます。 このような場合、コールバックは音声データを直接アプリケーションに提供すればよいでしょう。
“録音用Audio Queueのコールバック関数” で、このコールバックについてより詳しく学びます。
全てのAudio Queueは、録音であろうが再生であろうが、1つないしそれ以上のAudio Queue Bufferを持ちます。 これらバッファは、Buffer Queueと呼ばれる特定の配列の中に配置されます。 図中、Audio Queue Bufferは(データで)埋められた順に番号付けがなされます。これは、バッファがコールバックに渡された順番と一致します。
“Buffer Queueとエンキュー”で、Audio Queueがそのバッファを扱う方法について学びます。
再生用Audio Queue
再生用途のAudio Queue(AudioQueueNewOutput
関数で生成されます)は、図1-2に示す構造を持ちます。
再生用Audio Queueでは、コールバックは入力側にあります。 そのコールバックは、ディスク(または他のソース)から音声データの取得と、Audio Queueへのデータ引き渡しの責任を負います。 また、再生コールバックは再生するデータが無くなった際、Audio Queueに停止指示を伝えます。 “再生用Audio Queueのコールバック関数” で、このコールバックについてより詳しく学びます。
再生用Audio Queueの出力は通常、スピーカといった外部音声ハードウェアに接続されます。 標準の状態では(in the default case)、音声はユーザーがシステム環境設定で設定した、システムのデフォルト音声出力装置から出力されます。
Audio Queue Buffer
Audio Queue Bufferは、AudioQueue.h
ヘッダファイルで宣言されている、AudioQueueBufferRef
型のデータ構造です:
typedef struct AudioQueueBuffer { const UInt32 mAudioDataBytesCapacity; void *const mAudioData; UInt32 mAudioDataByteSize; void *mUserData; } AudioQueueBuffer; typedef AudioQueueBuffer *AudioQueueBufferRef;
上記リスト中で強調表記されている(訳註:本Wikiの仕様上、ここでは強調表記されていません)mAudioData
領域はバッファを指していますが、本質的には、録音や再生に使用される音声データの一時的な塊を格納する、メモリ区画です。
(構造体の)他のメンバが持つ情報は、Audio Queueがバッファを管理するのに使用されます。
Audio QueueはAudio Queue Bufferをいくつでも持つことが出来ます−つまり、アプリケーションで幾つ必要かを決めます。 通常、この個数は3個です。 これにより、バッファの1つがディスクへの書き出しで使用される一方で、2つめのバッファで新しい音声データの受け取りを可能にします。 残りの3つ目のバッファは、ディスク入出力の遅延等を吸収する目的で、必要となれば利用されます。 図1-3は、その様子を示しています。
Audio Queueは、これらバッファの全てのメモリ管理を行います。 この仕掛け(helps)は、開発者がアプリケーションに録再機能を追加する労力を低減(improve)します。 またこれは、資源利用の最適化も図ります。
AudioQueueBuffer
データ構造の完全な解説は、Audio Queue Services Referenceをご覧下さい。
Buffer Queueとエンキュー
The buffer queue is what gives audio queues, and indeed Audio Queue Services, their names. “Audio Queueのアーキテクチャ”では、Buffer Queue−順番に並んだバッファ列-を見て来ました。 それでは、録音、再生におけるBuffer Queueの管理のし方について学びましょう。 特に、Audio Queue BufferをBuffer Queueに追加する、エンキューについて学習します。 実装するものが録音か再生かに因らず、エンキューはコールバックがしなければならない仕事です。
録音プロセス
録音の場合、Audio Queue Bufferの1つは、マイクなどの入力装置から得られる音声データで埋められます。 Buffer Queue中の残りのバッファは、現在使用中のバッファの後ろに並べられ、音声データで埋められる順番を待ちます。
Audio Queueは得られたバッファ順に、バッファを音声データで満たし、コールバックに渡します。 図1-3はAudio Queueを用いた録音作業の様子を示しています。
図1-3の手順1で、録音を開始します。 Audio Queueは得た音声データでバッファを埋めます。
手順2において、最初のバッファは既に埋められています。 Audio Queueはコールバックを呼び出し、コールバックに満タンのバッファ(buffer 1)を渡します。 手順3で、コールバックはそのバッファの中身を音声ファイルへ書き出します。 時を同じくして、Audio Queueは別のバッファ(buffer 2)を新しく得られたデータで埋めます。
手順4で、コールバックは書き出しが終わったバッファ(buffer 1)を、キューの最後に加え(enqueue)、そして再度データで埋められる状態にします。 手順5で、Audio Queueは再びコールバックを呼び、満タンとなった次のバッファ(buffer 2)を渡します。 手順6で、コールバックはこのバッファの中身を音声ファイルに書き出します。 この定常データ取得状態(looping steady state)は、ユーザーが録音を停止するまで続けられます。
再生プロセス
再生の場合、Audio Bufferの1つが、スピーカなどの出力装置に送られます。 Buffer Queue中の残りのバッファは、現在使用中のバッファの後ろに並べられ、再生される番を待ちます。
Audio Queueは再生される順番に、音声データを入れるバッファをコールバックに渡します。 コールバックは新しい音声データを読み込みこんでバッファへと格納し、それからバッファをキューの最後尾へと追加します(enqueue)。 図1-4はAudio Queueを用いた再生作業の方法を示しています。
図1-4の手順1で、アプリケーションは再生用Audio Queueの準備をします。
アプリケーションは、個々のAudio Queue Bufferのために1度コールバックを呼び出し、それらを音声データで満たしBuffer Queueへと追加します。
このデータ充填作業は、アプリケーションがAudioQueueStart
関数を呼んだ際(手順2)、再生が直ぐに始まる事を保証します。
手順3で、Audio Queueは最初のバッファ(buffer 1)を出力に送ります。
最初のバッファが再生されると直ちに、再生用Audio Queueは定常データ取得状態(looping steady state)へと移行します。 Audio Queueは次のバッファ(buffer2)の再生を開始し(手順4)、コールバックを呼び(手順5)、先ほど再生されたバッファ(buffer 1)を渡します。 手順6で、コールバックはそのバッファを音声ファイルからのデータで埋め、再生に向けバッファをキューに追加します。
再生プロセスの制御
Audio Queue Bufferは必ず、キューに追加された順番で再生されます。
しかし、Audio Queue ServiceはAudioQueueEnqueueBufferWithParameters
関数で、この再生過程の制御を可能としています。
この関数で出来る事は以下の通りです:
- バッファを再生する正確な時間の設定。これにより同期に対応します。
- Audio Queue Bufferの開始・終了フレームの調整(trim)。これにより先頭や終端の無音部分を除去できます。
- バッファ単位による再生利得の設定(Set the playback gain at the granularity of a buffer.)
再生利得に関するより詳しい情報は、“Audio Queueのパラメータ”をご覧下さい。
AudioQueueEnqueueBufferWithParameters
関数の完全な解説については、Audio Queue Services Referenceをご覧下さい。
Audio Queueコールバック関数
典型的に、Audio Queue Serviceを利用したプログラミング作業の大部分が、Audio Queueコールバック関数の記述に費やされます。
録音中や再生中は、Audio QueueコールバックはAudio Queueによって繰り返し呼び出されます。 呼び出し間隔(the time between calls)は、Audio Queueのバッファ容量に依存し、通常、0.5秒〜3、4秒(several seconds)程度の範囲になります。
Audio Queueコールバックの責任の1つは、それが録音か再生かに拘らず、Buffer QueueへAudio Queue Bufferを返す事です。
コールバックは、AudioQueueEnqueueBuffer
関数を用いて、バッファをBuffer Queueの最後へ加えます。
再生の場合は、必要とあればその代わりに、“再生過程の制御”で解説したAudioQueueEnqueueBufferWithParameters
関数を使う事ができます。
録音用Audio Queueのコールバック関数
本項は、あなたが記述するであろう、ディスク上のファイルへ録音するという一般的なコールバックを紹介します。
以下はAudioQueue.h
ヘッダファイルで宣言されている、録音用Audio Queueコールバックのプロトタイプです:
AudioQueueInputCallback ( void *inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer, const AudioTimeStamp *inStartTime; UInt32 inNumberPacketDescriptions, const AudioStreamPacketDescription *inPacketDescs );
コールバック呼び出しにおいて、録音用Audio Queueは、コールバックが前に続く次の音声データ集合を音声ファイルに書き出すために必要となる、全ての情報を提供します:
- inUserData は通常、Audio Queueとそのバッファ用のステータス情報、データ書き込み先のファイルを表すAudio Fileオブジェクト(
AudioFileID
型)、そしてそのファイルの音声データ形式を含む、あなたの設定した独自の構造体です。 - inAQ は、コールバックを呼び出したAudio Queueです。
- inBuffer は、Audio Queueによって新しく埋められたAudio Queue Bufferで、コールバックがディスクに書き出すために必要となる新しいデータが含まれています。このデータは、(inUserData引数で渡される)独自構造体に含まれる、あなたが指定した音声データ形式情報に合わせて、既に形式が整えられています。より詳しい情報については、“コーデックと音声データ形式を使う”をご覧下さい。
- inStartTime は、バッファの最初のサンプルのサンプル時間です。基本的な録音では、このパラメータを使う必要はないでしょう。
- inNumberPacketDescriptions は、inPacketDescs引数で記述されるパケットの番号です。VBR(可変ビットレート)形式で記録する場合、Audio Queueがこのパラメータをコールバックに提供します。そして、これを順番に
AudioFileWritePackets
関数に渡します。CBR(固定ビットレート)形式では、パケット記述子は使いません。CBR記録の場合、Audio Queueは本引数とinPacketDescs引数をNULLにします。 - inPacketDescs は、バッファ中のサンプルと合致するパケット記述子が設定されます。繰り返しになりますが、音声データがVBR形式の場合、Audio Queueはこのパラメータに値を提供するので、コールバックはこれを
AudioFileWritePackets
関数(Audiofile.h
ヘッダで宣言)に渡します。
録音コールバックのより詳しい情報については、本資料の“音声の記録”をご覧下さい。また、合わせてAudio Queue Services Referenceもご覧下さい。
再生用Audio Queueのコールバック関数
本項は、あなたが記述するであろう、ディスク上のファイルから音声を再生するという一般的なコールバックを紹介します。
以下はAudioQueue.h
ヘッダファイルで宣言されている、再生用Audio Queueコールバックのプロトタイプです:
AudioQueueOutputCallback ( void *inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer );
コールバック呼び出しにおいて、再生用Audio Queueは、コールバックが次の音声データ集合を音声ファイルから読み出すために必要となる、全ての情報を提供します:
- inUserData は通常、Audio Queueとそのバッファ用のステータス情報、データ読み込み元のファイルを表すAudio Fileオブジェクト(
AudioFileID
型)、そしてそのファイルの音声データ形式を含む、あなたの設定した独自の構造体です。再生用Audio Queueでは、コールバックはこの構造体中に要素を設けて、現在のパケット番号(packet index)を保持しなければなりません。 - inAQ は、コールバックを呼び出したAudio Queueです。
- inBuffer は、Audio Queueによって生成されたAudio Queue Bufferで、コールバックが再生中のファイルから次のデータ集合を読み、そのデータを格納するために使用されます。
アプリケーションがVBRのデータを再生する場合、コールバックは読み込んだ音声データのパケット情報を必要とします。
これにはAudioFile.h
ヘッダファイルで宣言されている、AudioFileReadPackets
関数を呼びます。
それから、再生用Audio Queueがパケット情報を利用できるように、それを独自データ構造体の中に設置します。
再生用コールバックのより詳しい情報は、本資料の“音声の再生”をご覧下さい。また、併せて Audio Queue Services Reference もご覧下さい。
コーデックと音声データ形式を使う
Audio Queue Serviceは、必要とあらば音声形式の変換にコーデック(音声データの符号化/復号を行うコンポーネント)を使用します。 録音、再生アプリケーションはインストールされているコーデックの、全ての音声形式を使う事が出来ます。 様々な音声形式を扱うために、独自のコードを記述する必要はありません。 具体的に言うと、コールバックはデータ形式について知る必要がありません。
コーデックが作用する様子を見ていきましょう。
各々のAudio Queueは、AudioStreamBasicDescription
構造体で表現される、音声データ形式を持ちます。
あなたが−構造体のmFormatID
フィールドで−形式を指定すると、Audio Queueは適切なコーデックを使用します。
更にまた、標本化周波数やチャンネル数を指定すると、同様に反映されます。
“音声の記録”や“音声の再生”で、音声データ形式の設定例を見る事ができます。
録音用Audio Queueは、図1-5に示すようにインストール済みのコーデックを使用します。
図1-5の手順1で、アプリケーションはAudio Queueに録音の開始を伝え、そしてまた、使用するデータ形式も伝えます。 手順2で、Audio Queueは新しい音声データを取得し、あまたが指定した形式に基づくコーデックを使い、データを変換します。 それからAudio Queueはコールバックを呼び、変換済み音声データを含むバッファを渡します。 手順3で、コールバックは変換済み音声データをディスクへ書き出します。 もう一度言いますが、コールバックはデータ形式について知っている必要はないのです。
再生用Audio Queueは、図1-6に示すようにインストール済みのコーデックを使用します。
図1-6の手順1は、アプリケーションがAudio Queueに再生の開始を伝え、そしてまた、再生する音声ファイルが持つでデータ形式も伝えます。 手順2で、Audio Queueがコールバックを呼び出し、音声ファイルからデータを読み込みます。 コールバックはそのデータを、読み込んだままの形式でAudio Queueに渡します。 手順3で、Audio Queueは適切なコーデックを使用し、音声を出力先へと送ります。
Audio Queueは、Mac OS Xが最初から対応しているものだろうが、サードパーティが提供したものだろうが、インストール済みの全コーデックを使う事が出来ます。
使用するコーデックを指定するには、Audio QueueのAudioStreamBasicDescription
構造体に、4文字から成るコーデックIDを設定します。
この設定例は“音声の記録”で見る事が出来ます。
Mac OS Xは、CoreAudioTypes.h
ヘッダファイルで宣言され、Core Audio Data Types Referenceで明文化されている、形式ID列挙子一覧からわかるように、広範囲に渡る音声コーデックを持ちます。
あなたは、Audio ToolboxフレームワークのAudioFormat.h
ヘッダファイルに含まれるインタフェースを用いて、システムで利用可能なコーデックの中から決定することができます。
Fiendishthngsアプリケーションを使って、システムの持つコーデックを表示することが出来ます。このサンプルコードはhttp://developer.apple.com/samplecode/Fiendishthngs/にあります。
Audio Queueの状態と制御
Audio Queueの一生は、生成(creation)で始まり開放(disposal)で終わります。
アプリケーションはこのライフサイクルの管理と、Audio Queueの状態の制御をAudioQueue.h
ヘッダファイルで宣言される、6つの関数で行います:
- 開始(AudioQueueStart)- 録音/再生の初期化のために呼びます。
- 準備(AudioQueuePrime)- 再生において、Audio Queueが再生に必要なデータを直ぐに利用できる事を保証するために、AudioQueueStartを呼ぶ前に呼びます。この関数は録音には関係ありません。
- 停止(AudioQueueStop)- Audio Queueのリセット(後述のAudioQueueResetの解説をご覧下さい)と、録音/再生を停止するために呼びます。再生用Audio Queueのコールバックは、再生するデータが無くなった時に本関数を呼び出さなければなりません。
- 一時停止(AudioQueuePause)- バッファに影響を与えたり、Audio Queueをリセットする事なく録音/再生を一時停止するために呼びます。再開するにはAudioQueueStart関数を呼びます。
- 更新(AudioQueueFlush)- 最後のAudio Queue Bufferのエンキューが終わった後で、全てのバッファ済みデータと処理中の全音声データが、確実に録音/再生されるように呼び出します。
- リセット(AudioQueueReset)- 前もって決められていた使用予定(previously scheduled use)から全てのバッファを削除し、直ちにAudio Queueを停止する(silence)と共に、全デコーダとDSPの状態をリセットするために呼びます。
AudioQueueStop)は、同期モードと非同期モードで使う事ができます:
- 同期停止は、バッファリング中の音声データ(の有無)に関係なく、直ちに停止します。
- 非同期停止は、キューにあるバッファの再生/録音の完了後に停止します。
Audio Queueの同期/非同期停止の詳しい情報も含め、これら関数の完全な解説はAudio Queue Services Referenceをご覧下さい。
Audio Queueのパラメータ
Audio Queueはパラメータと呼ばれる、変更可能な設定を持ちます。 それぞれのパラメータは、キーとなる列挙定数と、値となる浮動小数点値を持ちます。 通常、パラメータは再生で使用され、録音では使用されません。
Mac OS X v10.5で、唯一使用可能なAudio Queueパラメータは、利得(gain)です。
このパラメータの値の設定や取得は、kAudioQueueParam_Volume
定数を使い、0.0の無音から1.0の単位利得(unity gain)までの値が利用できます。
アプリケーションがAudio Queueパラメータを設定するには、2つの方法があります:
- AudioQueueSetParameter関数を用いてAudio Queue単位で設定する。これによる設定の変更はAudio Queueに対して直接行われます。この変更は直ぐに反映されます。
- AudioQueueEnqueueBufferWithParameters関数を用いて、Audio Queue Buffer単位で設定する。
#未訳:This lets you assign audio queue settings that are, in effect, carried by an audio queue buffer as you enqueue it. この変更はAudio Queue Bufferが再生を開始したときに反映されます。
どちらの場合も、Audio Queueのパラメータ設定は、それらを変更するまで持続(remain)します。
AudioQueueGetParameter関数で、いつでもAudio Queueの現在のパラメータ値にアクセスできます。 パラメータ値の設定/取得に関係する関数の完全な解説は、Audio Queue Services Referenceをご覧下さい。