2016-04-14 27 views
1

Giriş ve çıkış için yapılandırılmış basit bir çıkış ses birimi kullanarak çekirdek ses (OS X, 10.11.4 Beta, eski mac mini) kullanarak oynatım yapıyorum (Sorunlarım çıktı olarak görünüyor). Bu, soket/internet beslemesinden bir boost kilitsiz kuyruğa beslenen bir akışlı ses kaynağıdır ve daha sonra çıkış AU'suna beslenir. AU'nun geri çekilmesinin bir sonucu olarak ortaya çıkan ses kesintilerini, aralıklı olarak çekirdek ses tarafından aranmıyor.
İşte bir graph. Bu bölümden önce ~ 10 saniye kusursuz ses vardı.OS X çekirdek ses çalma/çıkışı ile ses çıkışları yaşanıyor

siyah: örnek ses, basit bir sinüs dalgası

mavi: lockless sıranın boyutu (playback_buf: ms geri arama (OutputProc) işlemek yukarıdaki tabloda nokta ile duvar saat süresi ~ 120ms

turuncu ms zaman

Herşey OutputProc kaydedilir, böylece denilen değilse, o zaman hiçbir şey kaydediliyor alır, ancak grafik aracı olacak:) örneklerinde/1000 güzel

x ekseni grafiğinde sığdırmak için noktaları birbirine bağlayın dönemleri. Tamponda her zaman yeterli örnek var. Görünüşe göre ~ 22475ms ~ 22780ms, OutputProc sadece bir kez 22640 olarak adlandırılır. Bu belirli bir örnek üzerinde uzun bir duvar saati zamanı var, ama emilimden ötürü gibi görünüyor. Daha sonra 22800 ila 23000 aralığında hala çıkışlar var ama OutputProc normalden daha uzun sürmez ve gerçek zamanlı pencereyi kesinlikle aşmaz (~ 6ms burada ... HW örnekleme hızı 96kHz'dir). Öyleyse, sanırım bu bir şekilde önceden boşalan başka bir iş parçacığı. Çekirdek ses parçasının çok yüksek bir prioya sahip olmasını beklerdim. Paralel giriş/çıkışın paralel olarak devam etmesine (örneğin, boost :: asio :: io_service io_service) sahibim ama her zaman temel ses seviyesine öncelik vermeyi beklerim. Eğer asıl sorun için herhangi bir işaretçiniz varsa ... bu her zaman bekler ... ama, ilgilendiğiniz zamanlarda hangi iplik (ler) inin çalıştığını öğrenebilir miyim? Xcode'ta, muhtemelen bir işlemci çekirdeği başına bir zamanlayıcı geçmişi veya iş parçacığı geçmişi bildiren bir şey var mı? OutputProc eğer yardımcı olur:

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'nun geri çağırma duvar saati süreleri, Geri Çağırma veya kesintili sistem çağrılarını OutputProc'a dönüştürür. Geri arama iş parçacığı gerçek zamanlı ve zamanlayıcı tabanlı. Üretici iş parçacığı zamanında veri sağlamazsa, beklemez: sessizlik, aldığınız şeydir. Sanırım sorun başka bir yerde olmalı. Bu satır nedir: 'if (playback_buf_avail> = This-> playback_buf_thresh)' ve hangi mekanizma _This_ veri yapısını günceller? – user3078414

cevap

1

Sizin günlük mekanizma gerçek zamanlı iplik müdahale ediyor olabilir. Kilitleme veya hafızayı yönetebilen herhangi bir çağrı, herhangi bir çağrı (böyle bir dizge oluşturma veya stdout dosyası IO), Ses Birimi geri aramalarında düşüşlere ve diğer arızalara neden olabilir.

Böyle bir durumda, zaman damgalarınızı kilitlenmeden döngüsel olarak günlüğe kaydedilen bir FIFO günlüğüne yerleştirmeyi ve başka bir iş parçacığında herhangi bir dosyayı (IO) yapmayı deneyebilirsiniz.

+0

Evet, bu sorunun en azından bir kısmıydı. Ayrıca std :: cout ifadelerinin yanı sıra, kayıttan çalma işlevinin playback_buf'a eklenmesini sağlayan yuva alma işlevinin hem günlük hem de cout ifadelerini kaldırmam gerekiyordu (bu, bir boost :: lockfree :: spsc_queue). Teşekkürler! – Chris