このページの翻訳:
ソースの表示
最近の変更サイトマップ

※以前のwikiで本章は翻訳途中だったため、10.9のリファレンスから再翻訳しています。

音声の記録

Audio Queue Serviceを使って録音する際、その保存先はディスク上のファイル、ネットワークの接続先、メモリ内のオブジェクトなど、殆ど何でも選択出来ます。 本章では最も一般的なシナリオである、ディスクのファイルへの基本的な録音方法を解説します。

本章はMac OS X Core Audio SDKのいくつかのC++クラスを用いた、ANSI-Cベースの録音の実装について解説します。Objective-Cベースの例は、iOS Dev CenterSpeakHereサンプルコードをご覧ください。

アプリケーションに録音機能を追加するには、一般的に以下の手順を踏みます:

  1. 状態(state)、フォーマット、ファイルパス情報を管理する独自構造体を定義する。
  2. 実際の録音を担うAudio Queueコールバック関数を書く。
  3. (任意で)Audio Queue Bufferの最適なサイズを決めるコードを書く。マジッククッキーを使うフォーマットで録音するなら、マジッククッキーが機能するコードを書く。
  4. 独自構造体のフィールドを埋める。これにはファイルへのパスは勿論、Audio Queueがファイルへ送る録音データストリームの指定も含む。
  5. 録音Audio Queueを生成し、Audio Queue Bufferセット作成のために問い合わせる。また、記録に使うファイルを作成する。
  6. Audio Queueに録音開始を伝える。
  7. 録音が終わったらAudio Queueを停止し、そして破棄する。Audio Queueは保持するバッファを破棄する。

以降、本章ではこれら手順の詳細を解説します。

状態を管理する独自構造体の定義

Audio Queue Serviceを使った録音ソリューション開発の第1ステップは、独自構造体の定義です。 この構造体を使い、音声フォーマットとAudio Queueの状態管理を行います。 リスト2-1は構造体の例です:

リスト 2-1 録音Audio Queueの独自構造体

static const int kNumberBuffers = 3;                            // 1
struct AQRecorderState {
    AudioStreamBasicDescription  mDataFormat;                   // 2
    AudioQueueRef                mQueue;                        // 3
    AudioQueueBufferRef          mBuffers[kNumberBuffers];      // 4
    AudioFileID                  mAudioFile;                    // 5
    UInt32                       bufferByteSize;                // 6
    SInt64                       mCurrentPacket;                // 7
    bool                         mIsRunning;                    // 8
};

この構造体のフィールドの解説です。

  1. 使用するAudio Queue Bufferの数の設定。
  2. AudioStreamBasicDescription構造体(CoreAudioType.hより)は、ディスクに書き込む音声データフォーマットを表します。このフォーマットはmQueueフィールドで指定されるAudio Queueによって使用されます。

    mDataFormatフィールドは、“Set Up an Audio Format for Recording”で解説されるように、最初はあなたのプログラムのコードによって埋められます。“Getting the Full Audio Format from an Audio Queue”で解説するように、Audio QueueにkAudioQueueProperty_StreamDescriptionプロパティを問い合わせて、このフィールドを更新するのが良い方法です。Mac OS X v10.5では、代わりにkAudioConverterCurrentInputStreamDescriptionプロパティを使います。

    AudioStreamBasicDescription構造体の詳細は、Core Audio Data Types Referenceをご覧ください。

  3. あなたのアプリケーションによって生成される録音Audio Queue。
  4. そのAudio Queueによって管理されるAudio Queue Bufferへのポインタの配列。
  5. プログラムが音声データを記録するファイルを表すAudio Fileオブジェクト。
  6. 各Audio Queue Bufferの大きさのバイト数。この値は、以下のサンプルのDeriveBufferSize関数で、Audio Queueが生成されAudio Queueが開始される前に計算されます。“Write a Function to Derive Recording Audio Queue Buffer Size”をご覧ください。
  7. 現在のAudio Queue Bufferから書き出される最初のパケットのパケットインデックス。
  8. Audio Queueが実行中かどうかを示すブール値。

録音Audio Queueコールバックの実装

次に、録音Audio Queueコールバックを書きます。 このコールバックには2つの目的(main things)があります:

  • 新しく埋められたAudio Queue Bufferの内容を記録中のファイルに書き出す。
  • (先ほど中身をディスクに書き出した)Audio Queue Bufferをバッファーキューに加える。

本項ではコールバック宣言の例を示してから、それら2つの仕事を個別に解説し、最後に録音コールバックの全体を示します。 録音Audio Queueコールバックの役割像については、図 ##を見直して下さい。

録音Audio Queueコールバックの宣言

リスト2-2は録音Audio Queueコールバック関数の宣言例で、AudioQueue.hヘッダでAudioQueueInputCallbackとして宣言されています:

リスト 2-2 録音Audio Queueコールバック宣言

static void HandleInputBuffer (
    void                                *aqData,             // 1
    AudioQueueRef                       inAQ,                // 2
    AudioQueueBufferRef                 inBuffer,            // 3
    const AudioTimeStamp                *inStartTime,        // 4
    UInt32                              inNumPackets,        // 5
    const AudioStreamPacketDescription  *inPacketDesc        // 6
)

コードの働きを見てみましょう:

  1. 典型的にはaqDataは、“状態を管理する独自構造体の定義”で解説したAudio Queueの状態データを含む独自構造体で
  2. このコールバックを所持するAudio Queueです。
  3. 録音で入ってくる音声データを含むAudio Queue Bufferです。
  4. Audio Queue Bufferの先頭サンプルのサンプル時間です(簡易的な録音では必要ありません)。
  5. inPacketDescパラメータが持つパケット記述子の数。0はCBRデータを表します。
  6. パケット記述子を必要とする圧縮音声データ形式のための、バッファ内のパケット用のエンコーダが提示するパケット記述子。

Audio Queue Bufferをディスクへ書き出す

録音Audio Queueコールバックの最初の仕事は、Audio Queue Bufferをディスクに書き出す事です。 このバッファは、たった今コールバックのAudio Queueが入力デバイスからの新しい音声データで埋めたものです。 リスト2-3で示すように、コールバックはAudioFile.hヘッダファイルのAudioFileWritePackets関数を使います。

リスト 2-3 Audio Queue Bufferをディスクに書き出す

AudioFileWritePackets (                     // 1
    pAqData->mAudioFile,                    // 2
    false,                                  // 3
    inBuffer->mAudioDataByteSize,           // 4
    inPacketDesc,                           // 5
    pAqData->mCurrentPacket,                // 6
    &inNumPackets,                          // 7
    inBuffer->mAudioData                    // 8
);

コードの働きを見てみましょう:

  1. AudioFile.hヘッダファイルで宣言されているAudioFileWritePackets関数は1つのバッファの内容を音声データファイルに書き出します。
  2. 音声ファイルオブジェクト(AudioFileID型)は書き出し先の音声ファイルを表します。pAqData変数はリスト2-1で解説したデータ構造体へのポインタです。
  3. falseは、関数が書き込み時にデータをキャッシュすべきではない事を示します。
  4. 書き出す音声データのバイト数です。inBuffer変数はAudio Queueがコールバックに渡したAudio Queue Bufferを表します。
  5. 音声データのパケット記述子配列です。NULLはパケット記述子が必要ない事を示します(CBRの音声データなど)。
  6. 書き出す先頭パケットのパケットインデックスです。
  7. 入力では出力するパケット数を表します。出力では実際に出力されたパケット数が返ります。
  8. 音声ファイルに書き出す新しい音声データです。

Audio Buffer Queueをキューに加える

Audio Queue Bufferの音声データは音声ファイルに書き出されたので、リスト2-4で示す通り、コールバックはそのバッファをキューに戻します。 バッファキューに戻した時点で、そのバッファは待ち行列に並び、次なる入力音声データの受け入れ態勢が整います。

リスト 2-4 ディスクへ出力後のAudio Queue Bufferのエンキュー

AudioQueueEnqueueBuffer (                    // 1
    pAqData->mQueue,                         // 2
    inBuffer,                                // 3
    0,                                       // 4
    NULL                                     // 5
);

コードの働きを見てみましょう:

  1. AudioQueueEnqueueBuffer関数はAudio Queue BufferをAudio Queueのバッファキューに追加します。
  2. 指定したAudio Queue Bufferを追加するAudio Queue。pAqData変数はリスト2-1で解説したデータ構造体へのポインタです。
  3. キューに追加するAudio Queue Buffer。
  4. Audio Queue Bufferのデータのパケット記述子の数。本パラメータは録音では使わないので、0を設定します。
  5. Audio Queue Bufferのデータのパケット記述子配列。本パラメータは録音では使わないので、0を設定します。

完全な録音Audio Queueコールバック

リスト2-5は完全な録音Audio Queueコールバックの基礎バージョンです。 本ドキュメント内の他のコード例と同様、以下のリストはエラー処理を考慮していません。

リスト 2-5 録音Audio Queueコールバック関数

static void HandleInputBuffer (
    void                                 *aqData,
    AudioQueueRef                        inAQ,
    AudioQueueBufferRef                  inBuffer,
    const AudioTimeStamp                 *inStartTime,
    UInt32                               inNumPackets,
    const AudioStreamPacketDescription   *inPacketDesc
) {
    AQRecorderState *pAqData = (AQRecorderState *) aqData;               // 1
 
    if (inNumPackets == 0 &&                                             // 2
        pAqData->mDataFormat.mBytesPerPacket != 0)
        inNumPackets = inBuffer->mAudioDataByteSize / pAqData->mDataFormat.mBytesPerPacket;
 
    if (AudioFileWritePackets (                                          // 3
            pAqData->mAudioFile,
            false,
            inBuffer->mAudioDataByteSize,
            inPacketDesc,
            pAqData->mCurrentPacket,
            &inNumPackets,
            inBuffer->mAudioData
        ) == noErr) {
            pAqData->mCurrentPacket += inNumPackets;                     // 4
    }
    if (pAqData->mIsRunning == 0)                                        // 5
        return;
 
    AudioQueueEnqueueBuffer (                                            // 6
        pAqData->mQueue,
        inBuffer,
        0,
        NULL
    );
}

コードの働きを見てみましょう:

  1. インスタンス化を行う際にAudio Queueオブジェクトに供給される、様々な状態データと共に書き出し先の音声ファイルを表すAudio Fileオブジェクトを含む独自構造体。“状態を管理する独自構造体の定義”をご覧ください。
  2. Audio Queue BufferがCBRデータを含む場合、バッファ内のパケット数を算出する。この値はバッファ内の合計バイト数を1パケット毎のバイト数(定数)で割った値に等しい。VBRデータでは、Audio Queueはコールバック呼び出し時のバッファ内のパケットデータ数を提供する。
  3. バッファの内容を音声データファイルに書き出す。詳しい解説は“Audio Queue Bufferをディスクへ書き出す”をご覧ください。
  4. 音声データの書き出しが成功すれば、音声データファイルのパケットインデックスをインクリメントし、バッファの次の音声データ書き出しに備える。
  5. Audio Queueが停止していたら関数を抜ける。
  6. 今しがた中身が音声ファイルに書き出されたAudio Queue Bufferをキューに戻す。詳しい解説は“Audio Buffer Queueをキューに加える”をご覧ください。

録音Audio Queue Bufferサイズを計算する関数の実装

Audio Queue Serviceは使用するAudio Queue Bufferサイズの特定を、アプリケーションが行うと期待します。 リスト2-6はその方法の1つです。 It derives a buffer size large enough to hold a given duration of audio data.

ここでの計算は録音する音声データ形式を考慮に入れます。 フォーマットは、音声チャンネル数などの、バッファサイズに影響するであろう全ての要因を含みます。

リスト 2-6 録音Audio Queue Bufferサイズの算出

void DeriveBufferSize (
    AudioQueueRef                audioQueue,                  // 1
    AudioStreamBasicDescription  &ASBDescription,             // 2
    Float64                      seconds,                     // 3
    UInt32                       *outBufferSize               // 4
) {
    static const int maxBufferSize = 0x50000;                 // 5
 
    int maxPacketSize = ASBDescription.mBytesPerPacket;       // 6
    if (maxPacketSize == 0) {                                 // 7
        UInt32 maxVBRPacketSize = sizeof(maxPacketSize);
        AudioQueueGetProperty (
                audioQueue,
                kAudioQueueProperty_MaximumOutputPacketSize,
                // in Mac OS X v10.5, instead use
                //   kAudioConverterPropertyMaximumOutputPacketSize
                &maxPacketSize,
                &maxVBRPacketSize
        );
    }
 
    Float64 numBytesForTime =
        ASBDescription.mSampleRate * maxPacketSize * seconds; // 8
    *outBufferSize =
        UInt32 (numBytesForTime < maxBufferSize ?
                numBytesForTime : maxBufferSize);             // 9
}

コードの働きを見てみましょう:

  1. サイズを特定したいバッファを持つAudio Queue。
  2. Audio QueueのAudioStreamBasicDescription構造体。
  3. 音声の秒数を単位とした、必要とするAudio Queue Bufferの大きさ。
  4. 出力で、バイト数を単位としたAudio Aueue Bufferのサイズ。
  5. Audio Queue Bufferサイズの上限(バイト数)。この例では320KBに設定されている。これはサンプリング周波数96kHz/24ビット/ステレオでおよそ5秒に対応する。
  6. CBR音声データ用に、AudioStreamBasicDescription構造体からパケットサイズ(定数)を得る。この値を最大パケットサイズとして使う。
  7. この割り当ては、その音声データの録音がCBRかVBRかを特定する副作用をもたらす。VBRならば、Audio QueueのAudioStreamBasicDescription構造体のbytes-per-packetの値は0を示す。
  8. VBR音声データ用に、Audio Queueに見積もり最大パケットサイズを問い合わせる。
  9. バイト数でバッファサイズを計算する。
  10. 必要ならば、前述の上限値にバッファサイズを制限する。

Audio File用マジッククッキーの設定

MPEG-4 AACなどのいくつかの圧縮音声形式は、オーディオメタデータを含む構造を利用します。 これら構造をマジッククッキーと呼びます。 Audio Queue Serviceを使ってこのような形式で録音する際は、録音開始前にAudio Queueからマジッククッキーを取得し、それをAudio Fileに追加しなければなりません。

リスト2-7はAudio Queueからマジッククッキーを得る方法と、Audio Fileへの適用方法を示します。 Your code would call a function like this before recording, and then again after recording—some codecs update magic cookie data when recording has stopped.

リスト 2-7 Audio File用マジッククッキーの設定

OSStatus SetMagicCookieForFile (
    AudioQueueRef inQueue,                                      // 1
    AudioFileID   inFile                                        // 2
) {
    OSStatus result = noErr;                                    // 3
    UInt32 cookieSize;                                          // 4
 
    if (
            AudioQueueGetPropertySize (                         // 5
                inQueue,
                kAudioQueueProperty_MagicCookie,
                &cookieSize
            ) == noErr
    ) {
        char* magicCookie =
            (char *) malloc (cookieSize);                       // 6
        if (
                AudioQueueGetProperty (                         // 7
                    inQueue,
                    kAudioQueueProperty_MagicCookie,
                    magicCookie,
                    &cookieSize
                ) == noErr
        )
            result =    AudioFileSetProperty (                  // 8
                            inFile,
                            kAudioFilePropertyMagicCookieData,
                            cookieSize,
                            magicCookie
                        );
        free (magicCookie);                                     // 9
    }
    return result;                                              // 10
}

コードの働きを見てみましょう:

  1. 録音に使うAudio Queue。
  2. 記録に使うAudio File。
  3. この関数の成否を表す返値変数。
  4. マジッククッキーのデータサイズを保持する変数。
  5. Audio Queueからマジッククッキーのデータサイズを取得し、cookieSize変数に格納します。
  6. マジッククッキー情報を保持するバイト列を確保します。
  7. Audio QueueのkAudioQueueProperty_MagicCookieプロパティを問い合わせてマジッククッキーを取得します。
  8. 記録するAudio Fileにマジッククッキーを設定します。AudioFileSetProperty関数はAudioFile.hヘッダファイルで宣言されています。
  9. 一時クッキー変数のメモリを解放します。
  10. 関数の成否を返します。

録音音声フォーマットの構成

本項ではAudio Queueの音声データ形式の構成方法を説明します。 Audio Queueはファイルへの記録にこのフォーマットを使用します。

音声データ形式の構成には、次の事柄を特定します:

  • 音声データ形式の種類(リニアPCM, AAC, その他など)
  • サンプリング周波数(44.1kHzなど)
  • 音声チャンネル数(ステレオには2など)
  • ビット深度(16ビットなど)
  • パケット毎のフレーム数(例えばリニアPCMでは1フレーム毎パケット)
  • 音声ファイルの種類(CAF, AIFF, その他など)
  • そのファイル種別が要求する音声データ形式の詳細

リスト2-8は、各属性を固定値とした録音用の音声形式の構成を示します。 製品コードでは、通常、音声形式の幾つかないし全ての項目をユーザーが設定できるようにすべきでしょう。 いずれのアプローチでも、目的は“状態を管理する独自構造体の定義”で解説したAQRecorderState独自構造体のmDataFormatのフィールドを埋めることです。

リスト 2-8 Audio Queueの音声データ形式の指定

AQRecorderState aqData;                                       // 1
 
aqData.mDataFormat.mFormatID         = kAudioFormatLinearPCM; // 2
aqData.mDataFormat.mSampleRate       = 44100.0;               // 3
aqData.mDataFormat.mChannelsPerFrame = 2;                     // 4
aqData.mDataFormat.mBitsPerChannel   = 16;                    // 5
aqData.mDataFormat.mBytesPerPacket   =                        // 6
aqData.mDataFormat.mBytesPerFrame    =
    aqData.mDataFormat.mChannelsPerFrame * sizeof (SInt16);
aqData.mDataFormat.mFramesPerPacket  = 1;                     // 7
 
AudioFileTypeID fileType             = kAudioFileAIFFType;    // 8
aqData.mDataFormat.mFormatFlags      =                        // 9
    kLinearPCMFormatFlagIsBigEndian
    | kLinearPCMFormatFlagIsSignedInteger
    | kLinearPCMFormatFlagIsPacked;

コードの働きを見てみましょう:

  1. AQRecorderState独自構造体の実体を生成します。構造体のmDataFormatフィールドはAudioStreamBasicDescription構造体を含みます。mDataFormatフィールドでセットされた値は、Audio Queueの音声フォーマットの初期定義を提供します—それはまた、記録先ファイルの音声フォーマットでもあります。リスト2-10では、より完全な音声フォーマット仕様を取得しますが、Core Audioはそれらをフォーマットタイプとファイルタイプに基づいて提供します。
  2. 音声データタイプをリニアPCMとして定義します。利用可能なデータ形式の完全なリストはCore Audio Data Types Referenceをご覧下さい。
  3. サンプリング周波数を44.1kHzとします。
  4. チャンネル数は2とします。
  5. チャンネルあたりのビット深度は16とします。
  6. パケットあたりのバイト数とフレームあたりのバイト数は4とします(2チャンネル×サンプルあたり2バイト)。
  7. パケットあたりのフレーム数は1とします。
  8. ファイルタイプはAIFFとします。利用可能なファイルタイプの完全なリストはAudioFile.hヘッダファイルの音声ファイルタイプ列挙値をご覧下さい。“コーデックと音声データ形式を使う”で解説したように、インストール済みコーデックが存在するあらゆるファイルタイプを書くことが出来ます。
  9. 特定のファイルタイプで必要となるフォーマットフラグを設定します。

録音Audio Queueの生成

それでは、録音コールバックと音声データ形式を設定して、録音Audio Queueの生成と設定をします。

録音Audio Queueを生成する

リスト2-9は録音Audio Queueの作り方を示したものです。 AudioQueueNewInput関数が、前のステップで構成したコールバック、独自構造体、音声データ形式を使う点に注目して下さい。

リスト 2-9 録音Audio Queueの生成

AudioQueueNewInput (                              // 1
    &aqData.mDataFormat,                          // 2
    HandleInputBuffer,                            // 3
    &aqData,                                      // 4
    NULL,                                         // 5
    kCFRunLoopCommonModes,                        // 6
    0,                                            // 7
    &aqData.mQueue                                // 8
);

コードの働きを見てみましょう:

  1. AudioQueueNewInput関数は新しい録音Audio Queueを生成します。
  2. 録音に使う音声データ形式です。“録音用音声フォーマットの構成”をご覧下さい。
  3. 録音Audio Queueが使うコールバック関数です。“録音Audio Queueコールバックの実装”をご覧下さい。
  4. 録音Audio Queueの独自データ構造体です。“状態を管理する独自構造体の定義”をご覧下さい。
  5. コールバックを呼び出す実行ループを指定します。NULLはデフォルトの挙動を示し、Audio Queue内部のスレッドでコールバックが呼ばれます。これは典型的な使い方で、アプリケーションのユーザーインタフェーススレッドが録音停止の入力を待つ間、Audio Queueによる録音を許可します。
  6. コールバック呼び出しの実行ループモードです。通常、ここにはkCFRunLoopCommonModes定数を使います。
  7. 将来拡張用です。0を指定して下さい。
  8. 新たに確保された録音Audio Queueが出力されます。

Audio Queueから完全な音声形式を取得する

Audio Queueの実体が出来ると(“録音Audio Queueの生成”をご覧下さい)、Audio Queueは特に圧縮フォーマットにおいて、あなたが持っているものより完全にAudioStreamBasicDescription構造体を埋めるでしょう。 完全なフォーマット記述を取得するには、リスト2-10で示すようにAudioQueueGetProperty関数を呼びます。 記録先のAudio Fileを作る際は、その完全な音声フォーマットをしようします(“Audio Fileの生成”をご覧下さい)。

リスト 2-10 Audio Queueから音声フォーマットを得る

UInt32 dataFormatSize = sizeof (aqData.mDataFormat);       // 1
 
AudioQueueGetProperty (                                    // 2
    aqData.mQueue,                                         // 3
    kAudioQueueProperty_StreamDescription,                 // 4
    // Mac OS Xでは代わりに↓を使ってください
    //    kAudioConverterCurrentInputStreamDescription
    &aqData.mDataFormat,                                   // 5
    &dataFormatSize                                        // 6
);

コードの働きを見てみましょう:

  1. Audio Queueに音声データ形式を問い合わせる時に使う、プロパティ値の期待サイズを得ます。
  2. AudioQueueGetProperty関数はAudio Queueから指定のプロパティ値を得ます。
  3. 音声データ形式を取得するAudio Queueです。
  4. Audio Queueのデータ形式値を得るためのプロパティIDです。
  5. 出力で、Audio Queueから得られたAudioStreamBasicDescription構造体による完全な音声データ形式です。
  6. 入力では、AudioStreamBasicDescription構造体の期待サイズです。出力では、実際のサイズが入ります。あなたの録音アプリケーションでは、この値を利用する必要はありません。

Audio Fileの生成

生成と設定が行われたAudio Queueを使って、リスト2-11のように録音データを保存するAudio Fileを生成します。 Audio Fileは、前述のAudio Queueの独自構造体に格納されたデータ形式とファイル形式仕様を使います。

リスト 2-11 記録用Audio Fileの生成

CFURLRef audioFileURL =
    CFURLCreateFromFileSystemRepresentation (            // 1
        NULL,                                            // 2
        (const UInt8 *) filePath,                        // 3
        strlen (filePath),                               // 4
        false                                            // 5
    );
 
AudioFileCreateWithURL (                                 // 6
    audioFileURL,                                        // 7
    fileType,                                            // 8
    &aqData.mDataFormat,                                 // 9
    kAudioFileFlags_EraseFile,                           // 10
    &aqData.mAudioFile                                   // 11
);

コードの働きを見てみましょう:

  1. CFURL.hヘッダファイルで宣言されるCFURLCreateFromFileSystemRepresentation関数は、記録に使うファイルを表すCFURLオブジェクトを生成します。
  2. NULL(またはkCFAllocatorDefault)を使うと、現在のデフォルトメモリアロケータを使います。
  3. CFURLオブジェクトに変換したいファイルシステムパスです。製品コードでは、通常、filePathからユーザー指定の値を得ます。
  4. ファイルシステムパスのバイト数です。
  5. falsefilePathがディレクトリではなくファイルである事を示します。
  6. AudioFile.hヘッダファイルのAudioFileCreateWithURL関数は、音声ファイルの新規作成ないし既存ファイルの初期化を行います。
  7. 新規音声ファイルの作成、もしくは既存ファイルの初期化の対象となるURLです。URLは手順1のCFURLCreateFromFileSystemRepresentationに由来します。
  8. 新しいファイルのファイルタイプです。本章のサンプルコードでは、前にkAudioFileAIFFTypeファイルタイプ定数を経由してAIFFに設定されています。“録音音声フォーマットの構成”をご覧下さい。
  9. AudioStreamBasicDescription構造体として指定される、ファイルに記録する音声のデータ形式です。本章のサンプルコードでは、これも“録音音声フォーマットの構成”で設定されています。
  10. ファイルが既に存在していた場合、そのファイルを消します。
  11. 出力で、記録先の音声ファイルを表す(AudioFileID型の)Audio Fileオブジェクトです。

Audio Queue Bufferサイズの設定

録音中に使うAudio Queue Bufferセットを準備する前に、先に書いたDeriveBufferSize関数(“録音Audio Queue Bufferサイズを計算する関数の実装”をご覧下さい)を使います。 このサイズを使用する録音Audio Queueのサイズに割り当てます。 リスト2-12がその様子を示します:

リスト 2-12 Audio Queue Bufferサイズの設定

DeriveBufferSize (                               // 1
    aqData.mQueue,                               // 2
    aqData.mDataFormat,                          // 3
    0.5,                                         // 4
    &aqData.bufferByteSize                       // 5
);

コードの働きを見てみましょう:

  1. 録音Audio Queue Bufferサイズを計算する関数の実装”で解説したDeriveBufferSize関数は、妥当なAudio Queue Bufferサイズを設定します。
  2. バッファサイズを設定するAudio Queueです。
  3. 記録するファイルの音声データ形式です。“録音音声フォーマットの構成”をご覧下さい。
  4. 各Audio Queue Bufferが保持する音声の秒数です。通常、ここで設定している0.5秒が良い選択です。
  5. 出力で、各Audio Queue Bufferサイズがバイト数で返ります。この値はAudio Queueの独自構造体の中に置かれます。

Audio Queue Bufferセットの準備

それでは、(“録音Audio Queueの生成”で)生成したAudio Queueに、Audio Queue Bufferセットを準備するように命令します。 リスト 2-13はそのデモンストレーションです。

リスト 2-13 Audio Queue Bufferセットの準備

for (int i = 0; i < kNumberBuffers; ++i) {           // 1
    AudioQueueAllocateBuffer (                       // 2
        aqData.mQueue,                               // 3
        aqData.bufferByteSize,                       // 4
        &aqData.mBuffers[i]                          // 5
    );
 
    AudioQueueEnqueueBuffer (                        // 6
        aqData.mQueue,                               // 7
        aqData.mBuffers[i],                          // 8
        0,                                           // 9
        NULL                                         // 10
    );
}

コードの働きを見てみましょう:

  1. Audio Queue Buffer確保とキュー追加のためにイテレートします。
  2. AudioQueueAllocateBuffer関数はAudio QueueにAudio Queue Bufferを確保するよう指示します。
  3. バッファを確保し所持するAudio Queueです。
  4. 新しく確保されるAudio Queue Bufferのバイト数です。“録音Audio Queue Bufferサイズを計算する関数の実装”をご覧下さい。
  5. 新しく確保されたAudio Queue Bufferが出力されます。バッファへのポインタはAudio Queueと共に使う独自構造体の中に置かれます。
  6. AudioQueueEnqueueBuffer関数はバッファキューの最後にAudio Queue Bufferを追加します。
  7. キューに加えるAudio Queue Bufferを持つAudio Queue。
  8. キューに加えるAudio Queue Buffer。
  9. 録音におけるバッファのキュー追加では、本パラメータは使用しません。
  10. 録音におけるバッファのキュー追加では、本パラメータは使用しません。

録音

リスト2-14で示されるように、これまでのコードの全てが録音のとてもシンプルな工程に繋がりました。

リスト 2-14 録音

aqData.mCurrentPacket = 0;                           // 1
aqData.mIsRunning = true;                            // 2
 
AudioQueueStart (                                    // 3
    aqData.mQueue,                                   // 4
    NULL                                             // 5
);
// ユーザーインターフェーススレッドにおいてユーザーが録音を止めるまで待つ
AudioQueueStop (                                     // 6
    aqData.mQueue,                                   // 7
    true                                             // 8
);
 
aqData.mIsRunning = false;                           // 9

コードの働きを見てみましょう:

  1. Audio Fileの先頭から記録するためにパケットインデックスを0に初期化します。
  2. Audio Queueが実行中を表すフラグを独自構造体にセットします。このフラグは録音Audio Queueコールバックで使用されます。
  3. AudioQueueStart関数は、Audio Queue自身のスレッドでAudio Queueを開始します。
  4. 開始するAudio Queue。
  5. NULLを使うと、Audio Queueが直ちに録音を開始する事を示します。
  6. AudioQueueStop関数は録音Audio Queueを停止しリセットします。
  7. 停止するAudio Queue。
  8. trueを使うと、同期的に止めます。停止における同期と非同期の説明は“Audio Queueの状態と制御”をご覧ください。
  9. Audio Queueが非実行中を示すフラグを独自構造体にセットします。

録音後の後始末

録音が終わったら、Audio Queueを破棄しAudio Fileを閉じます。 リスト 2-15はこれらの手順を示します。

リスト 2-15 録音後の後始末

AudioQueueDispose (                                 // 1
    aqData.mQueue,                                  // 2
    true                                            // 3
);
 
AudioFileClose (aqData.mAudioFile);                 // 4

コードの働きを見てみましょう:

  1. AudioQueueDispose関数はAudio Queueと、バッファを含むその全ての資源を破棄します。
  2. 破棄したいAudio Queue。
  3. trueを使うとAudio Queueを同期的に(すなわち、即座に)破棄します
  4. 記録に使ったAudio Fileを閉じます。AudioFileClose関数はAudioFile.hヘッダファイルで宣言されています。
translation/adc/audio/audio_queue_services_programming_guide/0300_recordingaudio.txt · 最終更新: 2015-01-06 11:51 (外部編集)
CC Attribution-Noncommercial-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0