Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/backbone.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 将大型多样本音频文件加载到内存中进行播放-如何避免临时冻结_C++_Audio_Memory Management_Sampling - Fatal编程技术网

C++ 将大型多样本音频文件加载到内存中进行播放-如何避免临时冻结

C++ 将大型多样本音频文件加载到内存中进行播放-如何避免临时冻结,c++,audio,memory-management,sampling,C++,Audio,Memory Management,Sampling,我正在编写一个应用程序,需要使用大型音频多样本,通常大小约为50MB。一个文件包含大约80个单独的短录音,我的应用程序可以随时播放这些录音。因此,所有音频数据都会加载到内存中,以便快速访问 然而,当加载其中一个文件时,可能需要几秒钟才能将其放入内存,这意味着我的程序会暂时冻结。避免这种情况发生的好方法是什么?它必须与Windows和OS X兼容。它冻结在以下位置:myMultiSampleClass->open()它必须使用ifstream进行大量的动态内存分配和读取文件 我想到了两个可能的选择

我正在编写一个应用程序,需要使用大型音频多样本,通常大小约为50MB。一个文件包含大约80个单独的短录音,我的应用程序可以随时播放这些录音。因此,所有音频数据都会加载到内存中,以便快速访问

然而,当加载其中一个文件时,可能需要几秒钟才能将其放入内存,这意味着我的程序会暂时冻结。避免这种情况发生的好方法是什么?它必须与Windows和OS X兼容。它冻结在以下位置:
myMultiSampleClass->open()它必须使用ifstream进行大量的动态内存分配和读取文件

我想到了两个可能的选择:

  • 打开文件并将其加载到另一个线程的内存中,这样我的应用程序进程就不会冻结。为了实现这一点,我已经研究了Boost库,但是在准备实现之前,我需要做大量的阅读。我需要做的就是在线程中调用open()函数,然后销毁线程

  • 想出一个方案来确保我在任何时候都不会将整个文件加载到内存中,可以说我只是动态加载。问题是任何样本都可能在任何时候触发。我知道其他一些软件有这种系统,但我不确定它是如何工作的。这在很大程度上取决于个人电脑的规格,它可以在我的电脑上很好地工作,但如果有人硬盘/内存速度慢,可能会得到非常糟糕的结果。我的一个想法是将每个录音的x个样本加载到内存中,然后如果我需要播放,开始播放已经存在的样本,同时将其余的音频加载到内存中


  • 有什么想法或批评吗?提前感谢:-(<

    >P>)你可能想考虑一种方法。这主要涉及使用一个线程将声音数据读入缓冲区,并使用另一个线程将数据从缓冲区流式传输到声卡

    数据读取器是生产者,数据流到声卡是消费者。您需要高水位线和低水位线,这样,如果缓冲区满了,生产者将停止读取,如果缓冲区低了,生产者将再次开始读取

    <强> C++生产者-消费者并发模板库<强> BR>


    编辑:我应该补充一点,这种事情很棘手。如果您正在构建一个示例播放机,系统上的负载会随着播放的按键、一次播放的声音数量、每个声音的持续时间、是否踩下持续踏板以及硬盘速度和缓冲等其他因素的变化而不断变化,以及可用的处理器马力。您最终采用的一些编程优化乍一看并不明显。

    我喜欢将解决方案1作为第一次尝试——简单而切中要害


    如果您在Windows下,您可以执行异步文件操作——告诉操作系统加载文件,并在文件准备就绪时通知您。

    使用异步文件。加载时间最初是“即时的”,I/O的开销将随着时间的推移而分散

    我认为最好的解决方案是在回放期间使用异步i/O(正如John Dibling提到的)将一小块或单个波形数据加载到固定大小的回放缓冲区

    策略是先填充播放缓冲区,然后播放(这将增加少量延迟,但保证连续播放),播放缓冲区时,可以在不同线程上重新填充另一个播放缓冲区(重叠),至少需要有两个播放缓冲区,一个用于播放,一个用于在后台重新填充,然后实时切换它


    稍后,您可以根据客户端PC的性能设置播放缓冲区的大小(这将在内存大小和处理能力之间进行权衡,最快的CPU将需要较小的缓冲区,从而降低延迟)

    听起来不错,但是页面错误通常会发生在最糟糕的时候:当音频解码器需要采样时。产生点击。如果缓冲良好,它可能会工作。一个想法:内存映射文件,有一个后台线程预接触页面?文件系统缓冲/预读应该能够处理任何弹出或点击。@gbrandt:内存映射文件是否已预读?@Snemark:尽管我记得在某个时候读过它(至少对于windows),内存映射文件已被缓冲,我现在到处都找不到那个信息。因此,我可能是不正确的,因为这是一个15岁以上的记忆。高清缓存可能会提前读取,但不能保证它已经读取了您想要的内容。在这种情况下可能不相关-他没有尝试流式传输音频,他有一个多样本文件,每个样本都可以单独播放。@Snemark:然后你可以在多个线程上使用多个缓冲区来播放。在我的应用程序中,任何延迟都是不可接受的,所以这种方法不是一个很好的解决方案。毕竟,我可能会使用解决方案1,尝试了内存映射文件,但效果不太好。我的代码需要完全独立于平台,有没有办法在MacOSX上实现这种重叠加载?