【发布时间】:2016-04-14 06:09:18
【问题描述】:
我正在使用为输入和输出配置的简单输出音频单元使用核心音频(OS X、10.11.4 Beta、旧版 mac mini)进行播放(尽管我的所有问题似乎都与输出有关)。这是来自套接字/互联网的流式音频源,馈送到升压无锁队列,然后馈送到输出 AU。我收到的音频丢失似乎是由于核心音频没有间歇性调用 AU 渲染回调的结果。
这是graph。在此部分之前有大约 10 秒的完美音频。
黑色:采样音频,简单正弦波
蓝色:渲染回调 (OutputProc) 的挂钟持续时间,以毫秒为单位,上图指出是 ~120ms
橙色:无锁队列 (playback_buf) 的大小(以 samples/1000 为单位)以很好地适应图形
x 轴:以毫秒为单位的时间
所有内容都记录在 OutputProc 中,因此如果不调用它,则不会记录任何内容,但绘图工具会将这些时间段内的点连接起来。缓冲区中总是有足够的样本。似乎从 ~22475ms 到 ~22780ms,OutputProc 仅在 22640 被调用一次。在该特定实例上它确实有很长的挂钟时间,但似乎是由于抢占。后来在 22800 到 23000 范围内仍然存在丢失,但 OutputProc 的持续时间不会比正常时间长,并且肯定不会超出实时窗口(此处约为 6 毫秒……硬件采样率为 96kHz)。所以,我认为这是其他一些以某种方式先发制人的线程。我希望核心音频线程具有非常高的优先级。我确实有一些并行的 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;
}
【问题讨论】:
-
我从来没有遇到过 CoreAudio 渲染回调或对 OutputProc 的间歇性系统调用的挂钟持续时间。回调线程是实时的和基于定时器的。如果生产者线程没有及时提供数据,它不会等待:沉默就是你得到的。我想问题一定出在其他地方。这行是什么:
if (playback_buf_avail >= This->playback_buf_thresh)以及哪个机制更新了 This 数据结构?
标签: c++ multithreading macos boost core-audio