2012-04-13 18 views
2

私はモノラルオーディオイベント(さまざまな周波数で短いビープ音)を再生するコードを持っています。 私はAudioOutputUnitを作成し、それを停止し、いつでもオーディオを再生する必要があります。私はそれを始める。私がそれを必要な時間プレイしたら、それをやめます。AudioOutputUnitStart非常に遅い

簡単に聞こえます。

しかし、AudioOutputUnitStartは私のiPhone 4S(iOS 5.1を使用)で戻るには通常180msかかりますが、これはあまりにも多すぎます。ここで

がそれを起動するにはAudioOutputUnit

void createAOU() 
{ 
    m_init = false; 
    // find the default playback output unit 
    AudioComponentDescription defaultOutputDescription; 
    defaultOutputDescription.componentType = kAudioUnitType_Output; 
    defaultOutputDescription.componentSubType = kAudioUnitSubType_RemoteIO; 
    defaultOutputDescription.componentManufacturer = kAudioUnitManufacturer_Apple; 
    defaultOutputDescription.componentFlags = 0; 
    defaultOutputDescription.componentFlagsMask = 0; 

    // Get the default playback output unit 
    AudioComponent defaultOutput = AudioComponentFindNext(NULL, &defaultOutputDescription); 
    if (defaultOutput == NULL) 
     return; 

    OSErr err = AudioComponentInstanceNew(defaultOutput, &m_toneUnit); 
    if (err != noErr) 
     return; 

    // single channel, floating point, linear PCM 
    AudioStreamBasicDescription streamFormat; 
    streamFormat.mSampleRate = m_framerate; 
    streamFormat.mFormatID = kAudioFormatLinearPCM; 
    streamFormat.mFormatFlags = 
    kLinearPCMFormatFlagIsFloat | 
    kAudioFormatFlagsNativeEndian | kLinearPCMFormatFlagIsPacked; 
    streamFormat.mBytesPerPacket = sizeof(float); 
    streamFormat.mFramesPerPacket = 1; 
    streamFormat.mBytesPerFrame = sizeof(float); 
    streamFormat.mChannelsPerFrame = 1; 
    streamFormat.mBitsPerChannel = sizeof(float) * 8; 
    err = AudioUnitSetProperty (m_toneUnit, 
           kAudioUnitProperty_StreamFormat, 
           kAudioUnitScope_Input, 
           0, 
           &streamFormat, 
           sizeof(AudioStreamBasicDescription)); 
    if (err != noErr) 
     return; 

    // Attach callback to default output 
    AURenderCallbackStruct input; 
    input.inputProc = RenderTone; 
    input.inputProcRefCon = this; 
    err = AudioUnitSetProperty(m_toneUnit, 
           kAudioUnitProperty_SetRenderCallback, 
           kAudioUnitScope_Input, 
           0, 
           &input, 
           sizeof(input)); 
    if (err != noErr) 
     return; 

    float aBufferLength = 0.001; // In seconds 
    AudioSessionSetProperty(kAudioSessionProperty_PreferredHardwareIOBufferDuration, 
          sizeof(aBufferLength), &aBufferLength); 

    err = AudioUnitInitialize(m_toneUnit); 
    if (err != noErr) 
     return; 
    reset(); 
    m_init = true; 
} 

の作成/初期化され、私は単純に呼び出します。

OSErr err = AudioOutputUnitStart(m_toneUnit); 

を完了したら:

OSErr err = AudioOutputUnitStop(m_toneUnit); 

を私が試しましたさまざまなもの: kAudioSessionProperty_PreferredHardwareIOBufferDurationプロパティを作る (5msのような)非常に小さな値oをフレームレートを減らして(試してみました48kHzの、44.1kHzの、8kHzの)どんなに私は何をすべきか

...のAudioUnitが開始され 初めて、AudioOutputUnitStartは160-180ms後に返します。私がすぐにそれを停止して始めると、それは約5mしかかかりません。これははるかに受け入れやすいものです。

私のアプリケーションのレイテンシーは重要であり、180msは間違いなく許容できません。

提案がありますか? 私は似たような質問をしている少数の人々を見たことがありますが、答えは決して得られません。

私は今回の事はオーディオユニット起動の待ち時間に対処するためのさまざまな:)

+0

これはすでに考えていますが、ここでrenderCallbackの機能を追加/削除しているのでしょうか?また、これを見た(あなたのバッファは小さいですが):http://stackoverflow.com/questions/5690460/objective-c-audiooutputunitstart-takes-a-long-time-to-start-possible-workaroun –

+0

私は実際にはありませんコールバックを削除することを考えました。コールバックでは、音波が実際に生成されるので、オーディオバッファは小さくて済みます。 – jyavenard

答えて

2

道になります望んでいることは先に必要な時間のオーディオユニットを開始し、それを停止しないことです。代わりに、短いバッファ用のオーディオセッションを設定してから、オーディオユニットのレンダリングコールバックバッファを無音で入力して、目的のサウンドを入力してください。その後、あなたの音の後、停止する代わりに沈黙でバッファーを満たすように戻ってください。

+0

私は懸念していた問題は、すべての時間に実行されている2番目のスレッドがあることを知っていることです。短いオーディオバッファー(レイテンシを減らすため)では、パフォーマンスにかなりの影響を与えます。 – jyavenard

+1

@jyavenard:非常に短いバッファを備えた継続的に動作するRemoteIO Audio Unitは、iPhone 4のCPUサイクルの1%未満を使用します。パフォーマンスの影響は、まったく目立たないでしょう。 – hotpaw2