简体   繁体   English

缓冲区欠载逻辑问题,线程教程?

[英]Buffer underrun logic problem, threading tutorial?

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) 好的,我尝试了各种标题,但都失败了(因此,如果有人想出更好的标题,请随时编辑: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. 我有以下问题:我正在使用API​​来访问我未编码的硬件,以便向该API添加库,而我需要从该API接口继承该API,并且该API会执行所有操作。

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). 我放入那个API,一个音乐生成器库,问题是提到的API仅在缓冲区为空时才调用音乐库,并要求硬编码的数据量(恰好是1024 * 16个样本……不知道为什么)。

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). 这意味着音乐生成器库在播放音乐时无法充分利用CPU的潜力,即使音乐库没有跟上,CPU使用率仍然很低(如3%),因此在部分音乐中也是如此复杂的东西,缓冲区不足(即:声卡播放缓冲区中的空白区域,因为音乐库功能尚未返回)。

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. 因此,我提出了两个解决方案:使用一些新的缓冲区逻辑对API进行破解,但在该方面我什么都没想到。

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. 或我实际想出的逻辑:让音乐库具有自己的线程,它将拥有自己的单独缓冲区,该缓冲区将一直填充,当API调用音乐库以获取更多数据而不是生成时,会将数据从该单独的缓冲区简单地复制到声卡缓冲区,然后继续生成音乐。

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. 这不是.wav或.ogg库。 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. 这就是为什么我提到CPU时间的原因,如果我可以使用100%CPU,则永远不会出现欠载情况,但是我只能在程序意识到缓冲区即将到达末尾与实际结束之间的短时间内使用CPU。缓冲区,并且此时间有时小于程序计算音乐所需的时间。

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. 一个线程生成音乐数据并将其存储在缓冲区中,而API线程则在需要时从该缓冲区获取数据。 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. 在这种情况下,无论您是读取还是写入,都需要同步对缓冲区的访问,并确保在API速度太慢的情况下,您没有太大的缓冲区。 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. 要实现这一点,您需要一个来自线程库的线程,互斥体和条件原语,以及两个标志-一个用于指示何时请求停止,另一个用于请求线程在API无法跟上并且API变得太大时暂停填充缓冲区。 I'd recommend using Boost Thread library for C++, here are some useful articles with examples that comes to mind: 我建议对C ++使用Boost Thread库,这是一些有用的文章,并带有示例:

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. 例如,在Windows上,您将使用FILE_FLAG_OVERLAPPED打开该文件,以使对该文件的所有操作都是异步的。

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. 当应用程序启动时,您将填充缓冲区,然后,一旦填充,您就可以将缓冲区的第一部分传递给API。 When the API returns, you can read in more data to overwrite the section of the buffer that your last API call consumed. 当API返回时,您可以读入更多数据以覆盖上一个API调用消耗的缓冲区部分。 Because the read is asynchronous, it will fill the buffer while the API is playing music. 由于读取是异步的,因此它将在API播放音乐时填充缓冲区。

The implementation could be more complex than this, ie 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. 实现可能比这更复杂,即使用循环缓冲区或等待直到消耗完几个部分,然后一次读取多个部分,而不是一次读取一个部分。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM