遇到OS X的核心音频播放/输出音频丢失 [英] Experiencing audio dropouts with OS X core audio playback/output

查看:195
本文介绍了遇到OS X的核心音频播放/输出音频丢失的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用使用一个简单的音频输出单元配置为输入和输出(尽管我所有的问题似乎与输出)的核心音频(OS X,10.11.4测试版,年长的Mac mini)播放。这是插座/互联网喂养流式音频源成升压无锁队列,然后送入输出AU。我理解的似乎非盟的结果呈现回调不被核心音频称为间歇性音频丢失。结果
这里是一个图表。有完美的音频到10秒这一部分之前。

黑色:样本音乐,简单的正弦波

蓝色:渲染毫秒回调(OutputProc),点关闭上述图表的挂钟时间为120毫秒〜

橙:样品无锁队列(playback_buf)的尺寸/ 1000,以适应它在图形很好

x轴:时间(ms)

一切都被记录在OutputProc,所以如果这不叫,再没有什么被记录,但图形工具将在这些时期的点连接起来。总是有在缓冲足够的样本。似乎从〜22475ms至〜22780ms,OutputProc仅在22640.称为一次它具有在该特定实例的长挂钟时间,但似乎是由于$ P $对抢占。后来在22800至23000范围仍存在辍学,但OutputProc并不比正常再持续,肯定不能超限实时窗口(这里〜6ms的... HW采样率为96kHz的是)。所以,我想这是一些其他的线程是pre-先发制人莫名其妙。我预计核心音频线有非常高PRIO虽然。我确实有并行一些提振ASIO插座输入/输出回事(如提高:: ASIO :: io_service对象io_service对象),但我希望这永远失去优先的核心音频。如果您有任何指针的实际问题......这总是欢迎...但是,我可以取得进步,如果我可以只找出线程(S)期间利息的时间执行?有什么在X code,它告诉我一个调度的历史或线程的历史,可能每个CPU核心?
如果它可以帮助OutputProc:

  OSStatus语音串流:: OutputProc(无效* inRefCon,
                                 AudioUnitRenderActionFlags * ioActionFlags,
                                 常量AudioTimeStamp *时间,
                                 UInt32的inBusNumber,
                                 UInt32的inNumberFrames,
                                 AudioBufferList * ioData)
{
    语音串流*此=(语音串流*)inRefCon;    playback_cb_dur_log.StartTime();    静态布尔first_call = TRUE;
    如果(first_call)
    {
        性病::法院LT&;<时间(定时器)所述;&下; 播放开始\\ n;
        这 - > playback_state = PLAYBACK_ACTIVE;
        first_call = FALSE;
    }    INT playback_buf_avail =(int)的这 - > playback_buf.read_available();
    playback_buf_size_log.AddPoint(playback_buf_avail / 1000);
    如果(playback_buf_avail> =&这个 - GT; playback_buf_thresh)
    {
        性病::法院LT&;< TIME()<< 音频,脱粒:<<这 - > playback_buf_thresh<< buf_size:&所述;&下; playback_buf_avail<<的std :: ENDL;
        //新的阈值只是一个数据帧
        这 - > playback_buf_thresh =这个 - > frames_total;
        的for(int i = 0; I<这 - > NUM_CHANNELS;我++)
        {
            浮动* TEMP =(浮点*)ioData-> mBuffers [I] .mData;
            这 - > playback_buf.pop(温度,inNumberFrames);
            playback_sample_log.AddData(ioData-> mBuffers [I] .mData,inNumberFrames,这 - > chan_params.sample_rate);
        }
    }
    其他
    {
        性病::法院LT&;< TIME()<< 沉默,脱粒:<<这 - > playback_buf_thresh<< buf_size:&所述;&下;这 - > playback_buf.read_available()&所述;&下;的std :: ENDL;
        的for(int i = 0; I<这 - > NUM_CHANNELS;我++)
        {
            memset的(ioData-> mBuffers [I] .mData,0,inNumberFrames *的sizeof(浮点32));
            playback_sample_log.AddData(ioData-> mBuffers [I] .mData,inNumberFrames,这 - > chan_params.sample_rate);
        }
    }
    playback_cb_dur_log.StopAndCaptureTime();    返回诺尔;
}


解决方案

您记录机制可能与实时线程干扰。任何事情,任何调用,这可能需要一个锁定,或管理内存(这样的字符串创建或标准输出文件IO)可能会导致音频单元回调辍学等故障。

如果是这样的话,你可以尝试在馅无锁循环记录FIFO的时间戳,以及做任何文件IO在另一个线程。

I'm doing playback using core audio (OS X, 10.11.4 Beta, older mac mini) using a simple output audio unit configured for input and output (though all of my problems seem to be with output). This is a streaming audio source from socket/internet feeding into a boost lockless queue, which then feeds into the output AU. I'm getting audio dropouts that appear to be a result of the AU render callback not being called by core audio intermittently.
Here is a graph. There were ~10 seconds of flawless audio before this section.

black: sample audio, simple sine wave

blue: wall clock duration of render callback (OutputProc) in ms, point off the chart above is ~120ms

orange: size of lockless queue (playback_buf) in samples/1000 to fit it in graph nicely

x-axis: time in ms

Everything is logged in OutputProc, so if that isn't called, then nothing gets logged, but the graphing tool will connect the dots across those periods. There is always enough samples in the buffer. It seems that from ~22475ms to ~22780ms, OutputProc is only called once at 22640. It does have a long wall clock time on that particular instance, but seems to be due to pre-emption. Later in the 22800 to 23000 range there are still dropouts but the OutputProc doesn't last any longer than normal and certainly doesn't overrun the real time window (~6ms here...HW sample rate is 96kHz). So, I'm thinking this is some other thread that is pre-empting somehow. I would expect core audio thread to have very high prio though. I do have some boost asio socket input/output going on in parallel (e.g. boost::asio::io_service io_service) but I would expect that to always lose priority to core audio. If you have any pointers to the actual problem...that is always welcome...but, I can make progress if I can just find out what thread(s) are executing during those times of interest? Is there something in Xcode that tells me a scheduler history or thread history, possibly per CPU core? The OutputProc if it helps:

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;
}

解决方案

Your logging mechanism might be interfering with the real-time thread. Anything, any call, which can take a lock, or manage memory (such a string creation or stdout file IO) can cause dropouts and other failures in Audio Unit callbacks.

If that's the case, you might try stuffing your time stamps in a lock-free circular logging FIFO, and doing any file IO in another thread.

这篇关于遇到OS X的核心音频播放/输出音频丢失的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆