缓冲区欠载逻辑问题,线程教程?
好吧,我尝试了各种标题,但都失败了(所以如果有人想出更好的标题,请随意编辑它:P)
我遇到以下问题:我正在使用 API 来访问硬件,但我不这样做t 编码,要将库添加到该 API,我需要从 API 接口继承,并且 API 可以完成所有操作。
我放入了那个 API,一个音乐生成器库,问题是提到的 API 仅在缓冲区为空时调用音乐库,并要求硬编码的数据量(恰好是 1024*16 个样本......不知道为什么)。
这意味着音乐生成器库无法使用所有 CPU 潜力,在播放音乐时,即使音乐库没有跟上,CPU 使用率仍然很低(例如 3%),因此在音乐的某些部分中,存在太多复杂的东西,缓冲区不足(即:声卡播放缓冲区中的空区域,因为音乐库函数尚未返回)。
调整硬编码的数字,只会使软件在某些机器上工作,而在其他机器上不起作用,这取决于几个因素......
所以我想出了两个解决方案:用一些新的缓冲区逻辑来破解 API,但我不这样做想到了那个领域的任何事情。
或者我实际上想到的逻辑:让音乐库有自己的线程,它将有自己单独的缓冲区,它将一直填充,当 API 调用音乐库获取更多数据时,而不是生成它将简单地将数据从该单独的缓冲区复制到声卡缓冲区,然后恢复生成音乐。
我的问题是,虽然我有几年的编程经验,但我总是避免多线程,我什至不知道从哪里开始......
问题是:有人可以找到另一种解决方案,或者指出我到一个可以解决问题的地方吗?给我有关如何实施我的线程解决方案的信息吗?
编辑:
我不是在读取文件,而是在生成或计算音乐,明白了吗?这不是 .wav 或 .ogg 库。这就是为什么我提到CPU时间,如果我可以使用100%的CPU,我永远不会出现欠载,但我只能在程序意识到缓冲区即将到达末尾和实际结束之间的短时间内使用CPU。缓冲区,这个时间有时小于程序计算音乐所花费的时间。
Ok, I tried all sorts of titles and they all failed (so if someone come up with a better title, feel free to edit it :P)
I have the following problem: I am using a API to access hardware, that I don't coded, to add libraries to that API I need to inherit from the API interface, and the API do everything.
I put in that API, a music generator library, the problem is that the mentioned API only call the music library when the buffer is empty, and ask for a hardcoded amount of data (exactly 1024*16 samples... dunno why).
This mean that the music generator library, cannot use all the CPU potential, while playing music, even if the music library is not keeping up, the CPU use remains low (like 3%), so in parts of the music that there are too complex stuff, the buffer underuns (ie: the soundcard plays the area in the buffer that is empty, because the music library function don't returned yet).
Tweaking the hardcoded number, would only make the software work in some machines, and not work in others, depending of several factors...
So I came up with two solutions: Hack the API with some new buffer logic, but I don't figured anything on that area.
Or the one that I actually figured the logic: Make the music library have its own thread, it will have its own separate buffer that it will fill all the time, when the API calls the music library for more data, instead of generating, it will plainly copy the data from that separate buffer to the soundcard buffer, and then resumes generate music.
My problem is that although I have several years of programming experience, I always avoided multi-threading, I don't know even where to start...
The question is: Can someone find another solution, OR point me into a place that will give me info on how to implement my threaded solution?
EDIT:
I am not READING files, I am GENERATING, or CALCULATING, the music, got it? This is NOT a .wav or .ogg library. This is why I mentioned CPU time, if I could use 100% CPU, I would never get a underrun, but I can only use CPU in the short time between the program realizing that the buffer is reaching the end, and the actual end of the buffer, and this time sometimes is less than the time the program takes to calculate the music.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我相信,具有单独线程的解决方案将为库准备数据,以便在请求时准备好数据,这是减少延迟和解决此问题的最佳方法。一个线程生成音乐数据并将其存储在缓冲区中,API 线程在需要时从该缓冲区获取数据。在这种情况下,无论是读取还是写入,您都需要同步对缓冲区的访问,并确保在 API 太慢的情况下没有太大的缓冲区。为了实现这一点,您需要一个线程、来自线程库的互斥锁和条件原语以及两个标志 - 一个用于指示何时请求停止,另一个用于在 API 无法跟上且缓冲区变得太大时要求线程暂停填充缓冲区。我建议使用 C++ 的 Boost Thread 库,这里有一些有用的文章,其中包含一些可以想到的示例:
I believe that the solution with separate thread that will prepare data for the library so that it is ready when requested is the best way to reduce latency and solve this problem. One thread generates music data and stores it in the buffer, and the APIs thread is getting data from that buffer when it needs it. In this case you need to synchronize access to the buffer whether you are reading or writing and make sure that you don't have too big buffer in those cases when API is too slow. To implement this, you need a thread, mutex and condition primitives from threading library and two flags - one to indicate when stop is requested and another one to ask thread to pause filling the buffer if API cannot keep up and it is getting too big. I'd recommend using Boost Thread library for C++, here are some useful articles with examples that comes to mind:
您不一定需要新线程来解决这个问题。您的操作系统可能提供异步读取操作;例如,在 Windows 上,您可以使用 FILE_FLAG_OVERLAPPED 打开文件,以使对其进行的任何操作异步。
如果您的操作系统确实支持此功能,您可以创建一个大缓冲区来容纳几次调用所需的数据。当应用程序启动时,您填充缓冲区,一旦填充完毕,您可以将缓冲区的第一部分传递给 API。当 API 返回时,您可以读入更多数据以覆盖上次 API 调用消耗的缓冲区部分。由于读取是异步的,因此它会在 API 播放音乐时填充缓冲区。
实现可能比这更复杂,即使用循环缓冲区或等待一些部分被消耗,然后一次读取多个部分,而不是一次读取一个部分。
You don't necessarily need a new thread to solve this problem. Your operating system may provide an asynchronous read operation; for example, on Windows, you would open the file with the FILE_FLAG_OVERLAPPED to make any operations on it asynchronous.
If your operating system does support this functionality, you could make a large buffer that can hold a few calls worth of data. When the application starts, you fill the buffer, then once it's filled you can pass off the first section of the buffer to the API. When the API returns, you can read in more data to overwrite the section of the buffer that your last API call consumed. Because the read is asynchronous, it will fill the buffer while the API is playing music.
The implementation could be more complex than this, i.e. using a circular buffer or waiting until a few of the sections have been consumed, then reading in multiple sections at once, instead of reading in one section at a time.