【问题标题】:Recording from ALSA - understanding memory mapping从 ALSA 录制 - 理解内存映射
【发布时间】:2013-01-23 14:25:33
【问题描述】:

我尝试使用 ALSA 从 USB 音频设备获取输入并将其作为一系列 signed short 值写入磁盘。我最终得到的是似乎是有效数据的块,其中散布着大块零。我猜我的缓冲区设置不正确,并且没有正确使用内存映射。

我正在尝试什么:

  • 采样率:8K(这是设备强制的)
  • 缓冲区大小:2048
  • 周期大小:512
  • 一个频道

设备似乎已正确打开并接受各种参数。经过一些设置后,循环运行为:

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

memcpy 是一个指向 short 数组的指针,并按每次返回的帧数递增。

在此记录几秒钟后,我将其关闭并将后续缓冲区作为每行上的单个短值写入磁盘。我期待的是 1200 到 2300 赫兹之间变化的一两秒 PCM 数据。我得到的是一些有很多零的数据。

我想知道的是:我的缓冲区和周期值是否合理?有人成功使用了 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 并写入磁盘。每行一个值。

【问题讨论】:

    标签: linux audio usb alsa


    【解决方案1】:

    来自documentation:“有必要在此调用之前直接调用 snd_pcm_avail_update() 函数。否则,此函数可能会返回错误的可用帧数。”我认为问题在于 snd_pcm_mmap_begin 误报了可用帧的数量,因此您正在读取尚未写入的区域。

    另外,我并不肯定,但我认为 alsa mmap 函数在有数据之前不会阻塞,尽管这可能会被我在这里没有看到的其他代码所覆盖。它与文件 mmap 不太一样,所以不要开始认为它是。如果您的粉丝开始发疯并且一切都变慢了,那么您的代码很可能会从应用程序切换到内核上下文并在要读取零字节时不断地再次切换。

    正如之前的海报所指出的,无论如何这都是 snd_pcm_readi 的完美用例,所以使用它。

    【讨论】:

      【解决方案2】:

      在 ARM 上有一个带有 USB 音频驱动程序的 known bug,其中内核和应用程序的同一缓冲区的映射可能不是缓存一致的。

      使用 ALSA 内存映射函数才有意义只有代码可以直接处理样本而不将它们复制到另一个缓冲区。 如果您确实复制了它们,那么您所做的snd_pcm_readi 所做的完全相同。 换句话说,就是不要使用内存映射。

      在捕获时,缓冲区大小对延迟没有影响,因此您应该将其设置得尽可能大以避免可能的溢出。

      较小的周期大小可以降低延迟,但您的程序不会执行任何与实时相关的操作,因此您可以使用较大的周期大小来节省一点功率。

      【讨论】:

        猜你喜欢
        • 2017-03-25
        • 2020-01-08
        • 1970-01-01
        • 2017-08-21
        • 1970-01-01
        • 1970-01-01
        • 2017-11-26
        • 1970-01-01
        相关资源
        最近更新 更多