2016-04-14 8 views
1

入出力用に設定されたシンプルな出力オーディオユニットを使用して、コアオーディオ(OS X、10.11.4 Beta、古いMac mini)を使って再生しています私の問題は出力と思われる)。これは、ソケット/インターネットからのブースト・ロックレス・キューへのストリーミング・オーディオ・ソースで、出力AUに供給されます。私は断続的にコアオーディオによって呼び出されないAUレンダリングコールバックの結果であるように見えるオーディオドロップアウトを取得しています。
ここにはgraphがあります。このセクションの前に10秒間の完璧なオーディオがありました。OS Xコアオーディオ再生/出力でオーディオドロップアウトを経験する

ブラック:サンプル・オーディオ、単純な正弦波

ブルー:ロックレス・キューのサイズ(playback_buf:、MSにコールバック(OutputProc)をレンダリング上記チャートをオフポイントのウォールクロック時間が〜120msの

オレンジミリ秒の時間が

すべてはOutputProcにログインしているので、それが呼び出されていない場合は、何も記録されません取得しますが、グラフ化ツールは以下となります。)サンプル中/ 1000がうまく

x軸はグラフにそれに合わせてそれらの間にドットを接続する期間。バッファには常に十分なサンプルがあります。 〜22475ms〜22780msの間にあるようですが、OutputProcは22640で一度しか呼び出されません。その特定のインスタンスでは壁時計の時間が長くなりますが、プリエンプションによるものと思われます。後で22800〜23000の範囲にはまだドロップアウトがありますが、OutputProcは通常よりも長く続きないし、実際の時間ウィンドウ(〜6msここでは... HWサンプルレートは96kHzです)をオーバーランしません。だから、私はこれが何とか先制している他のスレッドだと思っています。私はコアのオーディオスレッドが非常に高いprioを持つことを期待します。私は、いくつかのboost asioソケットの入出力が並行して行われています(例えば、boost :: asio :: io_service io_service)が、コアオーディオに優先順位を常に失うことが予想されます。実際の問題を指すポインタがあれば、それはいつでも歓迎です...しかし、興味のある時間にどのスレッドが実行されているかを知ることができれば進歩を遂げることができますか? Xcodeには、スケジューラの履歴やスレッドの履歴を、おそらくCPUコアごとに示すものがありますか? OutputProcは、それは場合に役立ちます:

OSStatus AudioStream::OutputProc(void *inRefCon, 
           AudioUnitRenderActionFlags *ioActionFlags, 
           const AudioTimeStamp *TimeStamp, 
           UInt32 inBusNumber, 
           UInt32 inNumberFrames, 
           AudioBufferList *ioData) 
{ 
    AudioStream *This = (AudioStream *) inRefCon; 

    playback_cb_dur_log.StartTime(); 

    static bool first_call = true; 
    if (first_call) 
    { 
     std::cout << TIME(timer) << " playback starting\n"; 
     This->playback_state = PLAYBACK_ACTIVE; 
     first_call = false; 
    } 

    int playback_buf_avail = (int) This->playback_buf.read_available(); 
    playback_buf_size_log.AddPoint(playback_buf_avail/1000.); 
    if (playback_buf_avail >= This->playback_buf_thresh) 
    { 
     std::cout << TIME() << " audio, thresh: " << This->playback_buf_thresh << ", buf_size: " << playback_buf_avail << std::endl; 
     // new threshold just one frame of data 
     This->playback_buf_thresh = This->frames_total; 
     for(int i = 0; i < This->num_channels; i++) 
     { 
      float *temp = (float *) ioData->mBuffers[i].mData; 
      This->playback_buf.pop(temp, inNumberFrames); 
      playback_sample_log.AddData(ioData->mBuffers[i].mData, inNumberFrames, This->chan_params.sample_rate); 
     } 
    } 
    else 
    { 
     std::cout << TIME() << " silence, thresh: " << This->playback_buf_thresh << ", buf_size: " << This->playback_buf.read_available() << std::endl; 
     for(int i = 0; i < This->num_channels; i++) 
     { 
      memset(ioData->mBuffers[i].mData, 0, inNumberFrames * sizeof(Float32)); 
      playback_sample_log.AddData(ioData->mBuffers[i].mData, inNumberFrames, This->chan_params.sample_rate); 
     } 
    } 


    playback_cb_dur_log.StopAndCaptureTime(); 

    return noErr; 
} 
+0

CoreAudioのレンダリングコールバックや、OutputProcへの断続的なシステムコールの壁掛け時間が長くなりました。コールバックスレッドは、リアルタイムでタイマーベースです。プロデューサスレッドがタイムリーにデータを提供しない場合、待機しません。無音は取得したものです。問題は他の場所になければならないと思います。この行は何ですか: 'if(playback_buf_avail> = this-> playback_buf_thresh)'と、どのメカニズムが_This_データ構造体を更新しますか? – user3078414

答えて

1

あなたのロギングメカニズムは、リアルタイムのスレッドに干渉されることがあります。ロックを取るか、メモリを管理できる呼び出し(文字列の作成やstdoutファイルIOなど)は、Audio Unitコールバックのドロップアウトやその他の障害を引き起こす可能性があります。

このような場合は、タイムスタンプをロックフリー循環ログFIFOに入れて、別のスレッドでファイルIOを実行してみてください。

+0

これは少なくとも問題の一部です。私はまた、std :: coutステートメントだけでなく、両方のロギングとcoutステートメントを、playback_buf(boost :: lockfree :: spsc_queue)に追加するプロデューサであるソケット受信関数から削除しなければなりませんでした。ありがとう! – Chris

関連する問題