Raf*_*ega 4 c++ audio openframeworks
我的场景是这样的:用户与GUI元素交互,音频回调函数读取由UI设置的变量,计算样本并将样本存储在缓冲区(或任何数据结构)中,然后由UI读取缓冲区并绘制波形(以每秒60次的绘制循环).
现在,根据我读过的一些内容(Linux音频开发列表中的一个帖子,这个和这个)我需要某种类型的数据结构,可以同时读取和写入而无需锁定,或者,我需要某种类型的跨线程通知系统传递变量.
但是,我见过的一些 例子使用来自C++ std库的vanilla向量,它们从一个线程读取并从另一个线程写入,当我运行程序时,它们运行正常.
如果您的线程正在访问相同的内存(读取或写入),那么您需要使用锁定,或者需要使用无锁数据结构.否则,当多个线程同时访问时,您的数据结构可能会损坏(或显示为已损坏).
您指向的示例似乎使用了提前分配的固定大小的向量.音频线程正在写入此缓冲区并且UI线程正在读取它,并且两者未同步.由于两者可以完全同时运行,因此UI线程无法保证实际读取的数据; 它可能会读取更新N中的一些数据,而某些数据来自更新N + 1.它可能会遗漏一些数据或读取一些数据两次(或更多).这不是构建音频应用程序的强大方法.它对于简单的可视化应用程序来说"足够好",因为可视化的结果不需要是完美的,但它完全不适合于录制或回放应用程序.
音频应用程序通常使用无锁数据结构(而不是使用锁),因为音频播放具有"实时"要求.如果您的音频缓冲区包含100毫秒的声音,那么您需要每秒填充这些缓冲区10次,否则您的音频播放将会断断续续.另一种说法是每次填充缓冲区的最后期限为100毫秒.
有各种各样的事情可以让你错过这个100ms的截止日期; 如果系统太忙,您的进程可能无法调度,或者页面错误可能导致磁盘读取阻塞进程的时间太长,仅举几个例子.如果你试图获得一个锁,但另一个线程持有它超过100毫秒,这将使你错过你的截止日期.这就是为什么使用锁可能对音频应用程序不利; 持有锁太久的另一个线程会让你错过截止日期.
使用无锁数据结构时,没有锁等待,因此其他线程无法停止进度.它使您可以更轻松地完成音频I/O截止日期.
但是在你对无锁算法过于兴奋之前,你应该知道它们更加微妙,并且需要比锁具更多的专业知识来正确使用.基本上,如果您不是该领域的专家,则不应尝试自己编写无锁算法.也许有一个很好的开源库,它有一些无锁算法实现; 我最近没看过.
但要意识到使用无锁算法所需的额外工作或多或少都会浪费,除非你在音频线程中也非常小心,以避免其他可能的延迟原因.特别:
您的音频线程不能malloc()或free()任何内存(大多数malloc/free实现内部获取全局锁)
你必须确保你的音频线程访问的任何内存都没有被分页(例如.mlock())
您的音频线程除声卡外不得执行任何I/O,因为I/O调用可能会阻塞.
除非您非常勤奋并采取所有这些步骤,否则您也可以使用锁定与其他线程共享的数据,但请确保锁定保留的时间非常短.例如,请确保在保持锁定的UI线程中不执行任何malloc()/ free()或阻塞系统调用.
| 归档时间: |
|
| 查看次数: |
695 次 |
| 最近记录: |