iPhone Core Audio Programming 第3回 AUGraphを使ってPlay Thru 2

前回の続き。

まずはRemote IO Unitのバスとスコープについて。
Remote IO UnitはAudio Unitの中でも特殊で、二個のAudio Unitをくっつけたみたいな感じになってます。
In/Outだからこれで正常ですが。
で、その構造は次の図のようになっています。
IO_unit
AppleのDocumentから拝借。

Input scopeとOutput scopeは、次の定数
kAudioUnitScope_Input
kAudioUnitScope_Output
で区別します。
Audio Unit全体にかかわる設定のときにはkAudioUnitScope_Globalを使います。
バスは1と0で区別するので、前回の次のコードを翻訳すると

//マイク入力をオンにする
UInt32 flag = 1;
AudioUnitSetProperty(remoteIOUnit,
                         kAudioOutputUnitProperty_EnableIO,
                         kAudioUnitScope_Input, //Remote InputのInput
                         1, //Remote Input
                         &flag,
                         sizeof(UInt32));

Remote IO Unitのマイク入力のInput BusをEnableにする

となります。図のマイクがつながっている左側の部分が対象、となります。

で、前回の問題はこの入力がモノラルになってるんだけど、出力がステレオだから片方聞こえない
でした。なので、マイク入力以降をモノラルにしちゃいます。

Core Audioで、オーディオデータフォーマットを扱うにはAudioStreamBasicDescription構造体を使います。

struct AudioStreamBasicDescription
{
    Float64 mSampleRate;
    UInt32  mFormatID;
    UInt32  mFormatFlags;
    UInt32  mBytesPerPacket;
    UInt32  mFramesPerPacket;
    UInt32  mBytesPerFrame;
    UInt32  mChannelsPerFrame;
    UInt32  mBitsPerChannel;
    UInt32  mReserved;
};
typedef struct AudioStreamBasicDescription  AudioStreamBasicDescription;

名前が長いので、ASBDと略して使います。

それぞれのメンバの詳細はおいておいて、チャンネル数はmChannelsPerFrameです。
で、iPhone Core AudioではAudio Unit正準形というのがありまして、Audio UnitのデフォルトのASBDです。

mSampleRate = 44100.0;
mFormatID = kAudioFormatLinearPCM;
mFormatFlags = kAudioFormatFlagsAudioUnitCanonical;
mBytesPerPacket = 1 * sizeof (AudioUnitSampleType); // 8
mFramesPerPacket = 1;
mBytesPerFrame = 1 * sizeof (AudioUnitSampleType); // 8
mChannelsPerFrame = 2;
mBitsPerChannel = 8 * sizeof (AudioUnitSampleType); // 32
mReserved = 0;

このASBDのmChannelsPerFrameを1にすればモノラルのAudio Unit正準形になります。
ただし、iPhone OS 3.0と2.2.1以前とでは、厳密にはデフォルトが異なります。この辺はいずれ詳しく扱うとして、ひとまずPlay Thruを完成させます。

結局のところ、図の部分をモノラルにすれば解決します。
ピクチャ 15

モノラルにするには、Audio Unit正準形のモノラルのASBDを作ってAudioUnitSetPropertyでセットします。

AUGraphInitializeの前に以下のコードを追加します。

    //Audio Unit正準形
    AudioStreamBasicDescription audioFormat;
    audioFormat.mSampleRate      = 44100.0;
    audioFormat.mFormatID         = kAudioFormatLinearPCM;
    audioFormat.mFormatFlags      = kAudioFormatFlagsAudioUnitCanonical;
    audioFormat.mBytesPerPacket   = 1 * sizeof (AudioUnitSampleType);
    audioFormat.mFramesPerPacket  = 1;
    audioFormat.mBytesPerFrame    = 1 * sizeof (AudioUnitSampleType);
    audioFormat.mChannelsPerFrame = 1; //モノラル!!
    audioFormat.mBitsPerChannel   = 8 * sizeof (AudioUnitSampleType);
    audioFormat.mReserved         = 0;

    //モノラルに変更する
    AudioUnitSetProperty(remoteIOUnit,
                         kAudioUnitProperty_StreamFormat,
                         kAudioUnitScope_Output, //Remote inputのアウトプットバス
                         1, //Remote input
                         &audioFormat,
                         sizeof(AudioStreamBasicDescription));

    AudioUnitSetProperty(remoteIOUnit,
                         kAudioUnitProperty_StreamFormat,
                         kAudioUnitScope_Input, //Remote outputのインプットバス
                         0, //Remote output
                         &audioFormat,
                         sizeof(AudioStreamBasicDescription));

これでOK。最終的な出力は入力がモノラルなので、勝手にLRに同じソースを出力してくれます。なので、kAudioUnitScope_Output/Bus0は変更しなくてOK(というか変更できません)。

iPhone OS2.2.1でも3.0でも3.1でも完璧に動きます。

この例はiPhoneの内蔵マイクを使う場合ですが、ProTrackみたいなステレオマイクを持つ外部機器を接続した場合、実は前回のコードでまったく問題無くステレオでモニタリングできます。
なので、外部機器を付けたときは前回の設定、通常時は今回の設定に切り替えればOKです。
じゃぁ、マイク入力の入力チャンネル数ってどうやって取得するのか?
Audio Sessionを使います!

ってことで、次回はAudio Sessionをやります。
続きは次回。

#あ、オトカメラ、ステレオ録音対応してなかった。以上のように簡単なので対応します。

2 Comments

  1. KToo9 said:

    すごく理解しやすく、勉強になります。
    このような有益な情報を提供してくださっていることに感謝します。

  2. Norihisa Nagano said:

    ありがとうございます。
    (今後も含め)意味不明のところがあればご指摘ください。

Leave a Reply