从ALSA录音 - 了解内存映射(Recording from ALSA - understandi

2019-08-16 19:45发布

林尝试使用ALSA从USB音频设备获取用户输入并写入到磁盘的一系列signed short值。 什么我结束了有什么似乎是用零的大块穿插有效的数据块。 我猜,我有我的缓冲区设置不正确,我不恰当地使用内存映射。

我试图:

  • 采样率:8K(这是由该装置被迫)
  • 缓冲区大小:2048
  • 期大小:512
  • 一个通道

该设备似乎被正确打开,并接受各种PARAMS。 一些设置后循环形式运行:

snd_pcm_avail_update   
snd_pcm_mmap_begin   
   memcpy data from mmap buffer to array of short   
snd_pcm_mmap_commit   

所述的memcpy是指向的短阵列,并且通过返回的每个通帧的数量递增。

在此之后记录几秒钟我关闭它,写随后的缓冲到磁盘上每行一个短值。 我很期待是第二个或两个PCM数据1200和2300赫兹之间变化。 什么我得到一些数据,有很多零。

我想知道的是:是我的缓冲期和值合理? 有没有人成功地使用从ALSA映射输出的内存?

编辑:一些代码

const snd_pcm_channel_area_t *areas;  
snd_pcm_uframes_t offset, frames, size;   
short* pCID = (short*)malloc( 50000 * sizeof( short ));  
short* ppCID = pCID;
while( size > 0 )  
{  
   frames = size;  
   snd_pcm_mmap_begin (device, &areas, &offset, &frames);     
   short* pd = (short*)areas[0].addr;   
   memcpy( ppCID, (pd + (offset*sizeof(short))), frames * sizeof( short ));  
   ppCID += frames;  
   snd_pcm_mmap_commit(device, offset, frames);  

   size -= frames;
}

(为了清楚起见移除检查错误)
当一切都说过和做过通过PCID我环路和写入磁盘。 每行一个值。

Answer 1:

有一个已知的bug与ARM的USB音频驱动程序,在内核和缓存相同的应用程序的地图可能不是高速缓存相干。

使用ALSA存储器映射功能,使得仅当代码可以直接handlle样品,而不将它们复制到另一个缓冲感。 如果你复制他们,你正在做的完全一样的 snd_pcm_readi已经这样做。 换句话说,就是不使用内存映射。

采集时,缓冲区大小对延迟没有任何影响,所以你应该让尽可能大,以避免可能出现的超支。

较小尺寸的时期给你更低的延迟,但你的程序没有做任何实时相关的,所以你可以使用较大尺寸期间节省电力的一点点。



Answer 2:

从文档 :“有必要直接调用此之前,调用snd_pcm_avail_update()函数,否则这个函数可以返回可用帧的错误计数。” 我假设的问题是,snd_pcm_mmap_begin被误报可用的帧数,所以你是从尚未被写入到一个区域内读取。

另外,我还不能肯定,但我不认为ALSA MMAP功能将阻塞,直到有数据,但可以由我不是在这里看到其他代码覆盖。 这并不完全是一回事文件mmap的,所以不要开始思考,它是。 如果你的粉丝开始要疯了,一切都变得缓慢,机会是你的代码是从纺纱应用程序切换到内核上下文,然后再返回继续当有零个字节被读取。

由于以前的海报已经指出的那样,这是一个完美的使用情况snd_pcm_readi无论如何,所以使用它。



文章来源: Recording from ALSA - understanding memory mapping