我继承了一些在Linux嵌入式平台上运行的ALSA代码。现有的实现执行阻止使用snd_pcm_readi()
和snd_pcm_writei()
进行读写。
我的任务是在ARM处理器上运行,但是我发现阻塞的交错读将CPU推送到99%,所以我正在探索非阻塞读写。
我按预期打开设备:
snd_pcm_handle *handle;
const char* hwname = "plughw:0"; // example name
snd_pcm_open(&handle, hwname, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK);
其他ALSA的事情发生了,我可以根据要求提供。
在此值得一提的是:
读小溪是这样的:
int32* buffer; // buffer set up to hold #period_size samples
int actual = snd_pcm_readi(handle, buffer, period_size);
此调用需要大约15 ms才能在阻塞模式下完成。显然,变量actual
在返回时将读取1024。
问题是,在non-blocking模式下,这个函数也需要15毫秒才能完成,actual
也总是在返回时读取1024。
我预计函数会立即返回,actual
是<=1024,很可能会读到"EAGAIN“(-11)。
在读取尝试之间,我计划让线程休眠一段特定的时间,从而为其他进程提供CPU时间。
我是不是误解了ALSA?还是我的代码错过了重要的一步?
发布于 2019-07-04 20:30:09
如果函数返回值为1024,则在调用时至少有1024帧可用。(驱动程序可能需要15毫秒的时间来实际启动设备。)
无论如何,阻塞或非阻塞模式对CPU的使用没有任何影响.要减少CPU的使用,请将default
设备替换为plughw
或hw
,但这样就失去了设备共享或采样速率/格式转换等功能。
发布于 2019-07-12 08:55:09
我通过包装snd_pcm_readi()
解决了问题,如下所示:
/*
** Read interleaved stream in non-blocking mode
*/
template <typename SampleType>
snd_pcm_sframes_t snd_pcm_readi_nb(snd_pcm_t* pcm, SampleType* buffer, snd_pcm_uframes_t size, unsigned samplerate)
{
const snd_pcm_sframes_t avail = ::snd_pcm_avail(pcm);
if (avail < 0) {
return avail;
}
if (avail < size) {
snd_pcm_uframes_t remain = size - avail;
unsigned long msec = (remain * 1000) / samplerate;
static const unsigned long SLEEP_THRESHOLD_MS = 1;
if (msec > SLEEP_THRESHOLD_MS) {
msec -= SLEEP_THRESHOLD_MS;
// exercise for the reader: sleep for msec
}
}
return ::snd_pcm_readi(pcm, buffer, size);
}
这对我很管用。我的音频进程现在‘只’占用19%的CPU时间。如果使用SND_PCM_NONBLOCK
或0
打开PCM接口,这并不重要。
将执行回调分析,以查看是否可以在代码的其他地方保存更多的CPU周期。
https://stackoverflow.com/questions/56886610
复制相似问题