Experiencing audio dropouts with OS X core audio playback/output

我们两清 提交于 2019-12-13 02:35:01

问题


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

回答1:


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.



来源:https://stackoverflow.com/questions/36615010/experiencing-audio-dropouts-with-os-x-core-audio-playback-output

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!