我是ALSA的新手,我设法在SND_PCM_ACCESS_RW_INTERLEAVED模式下播放PCM声音。我的问题是,我找不到一种方法让这种模式对我正在尝试做的事情有用。 (如果有人能告诉我如何,我会很高兴阅读)。我一直在阅读有这种MMAP模式,但要找到简单的例子并不容易。我想知道这是否是我需要的以及如何实现它。
我想要做的就是让我的小游戏(一个简单的太空拍摄)在拍摄或拍摄时立即播放声音。如果敌人在播放另一个声音时发射,声音应该根据需要加起来并且饱和,但是不应该中断声音事件。换句话说,我需要能够编辑即将播放的字节。
在尝试MMAP的无用尝试中(不知道它在实践中是如何工作的;只是遵循模糊的理论指示),我设置了所有内容,就像SND_PCM_ACCESS_RW_INTERLEAVED一样,但是将其更改为SND_PCM_ACCESS_MMAP_INTERLEAVED。然后我调用snd_pcm_avail_update,它似乎工作并返回大量可用的帧。之后,我调用snd_pcm_mmap_begin,传递参数,先前用合理的数字填充“帧”(例如10)。该函数失败并返回错误代码-77。我一直无法找到这意味着什么。区域数组保持不变。
这个错误是什么意思?我在哪里可以获得错误列表?我怎么能克服它?是否有一个好的,简单的例子,说明如何使用MMAP(或其他东西)来执行或多或少像我正在尝试的事情?
感谢您的帮助:)。
答案 0 :(得分:2)
ALSA在出错时返回负值。 77很可能是EBADFD,表示设备处于无效状态(根据/超限或根本不运行)。如果出现欠载,您可能使用的缓冲区太低。
在任何情况下,都无法修改您已提交给alsa驱动程序的音频数据(snd_pcm_mmap_commit / writei / writen)。立即获得音频声音的技巧就是使用非常低的缓冲区大小,< 10毫秒就可以了。为此,您将要使用hw:devices,其他设备类型通常会增加延迟。
在将声音传递给alsa之前,您仍需要手动混合声音。 在这个问题的评论中有一个很好的mmap示例:Alsa api: how to use mmap in c?。
话虽这么说,ALSA是这类应用程序的有效选择,但您不一定需要使用内存映射。读/写访问不会引入额外的延迟,它只是将音频复制更多。