New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[WIP] Threaded SLES audio with time stretching #546
Conversation
My main motivation for writing the sles plugin was to reduce the audio latency compared to the SDL plugin. If your new implementation still have less latency than SDL I think we can remove the original sles plugin, otherwise I think we should keep it. I'll try to take a look at your new plugin this weekend. |
Thanks. I thought that it was originally Paul who wrote it for some reason, so I included him. This does add some audio latency so that we can slow down the audio before buffers runs dry. It's not that much though. At least I don't hear unless something bad happens and we end up putting too much in there (which I have had issues with but fixed). |
That's because he's the audio expert here ;-)
Ok I'll test it this weekend and report back. |
BTW Richard is ok for the configurable VI refresh rate option but it has to be a per-game option |
Don't hesitate to send him a pull request if you're interested. |
Cool, yeah, I'll just have to find the time. |
Sure ;-) |
Just a few remarks: queueCallback is running on another thread (at least that's what the opensles doc says) 100 secondary buffers? It sounds enormous to me! Why are you building as c++? |
I believe it's safe to access lock.value from multiple threads because of the volatile keyword use. Writing and reading to that is an atomic operation. I also only check if the value is zero, I don't care if when I access the variable is one or two off. If we really reached 100 secondary buffers, something went wrong. 100 buffers assuming 512 samples a buffer is only 204,800 bytes, nothing now a days :) I'm using C++ because the SoundTouch library is a C++ library. You can't instantiate C++ objects from C files. |
When you try this out, for best experience, make sure sync audio and video are enabled. This will make the game timing be driven off the audio plugin instead of the core. The core frame limiter is very inaccurate. |
The volatile keyword only notify the compiler to disable optimization on a variable, mutex must be locked in order to perform atomic operation. However considering the current design I agree that atomic operation isn't really necessary.
Well it depends which memory is being used when enqueuing buffers ;-)
Arf, is it possible to build SoundTouch as a shared library? |
Yes, I built the SoundTouch librart as a shared library. Maybe I could write a wrapper library to the SoundTouch library that exposes methods that can be accessed using osal_dynlib_getproc. Is it worth the trouble though to keep it as C instead of C++? |
Don't waste your time writing a wrapper, building as C++ is just fine. I'm just not confortable with those static_cast<> |
Oh, lol, since I was building C++ now, I took advantage of some C++ features like |
f0f4513
to
1d7f3f9
Compare
Ok, I fixed the speed limiter in the core. Now it's no longer drifting from audio at 100% speed. I also made an upstream pull request. Desync audio and video should now work correctly. I also notice that frame rate is now a lot smoother when running with the speed limiter. |
0b21b61
to
974c8be
Compare
Number buffers and buffer size settings now actually do something. To start, I would do about 20 buffers and 512 buffer size |
00092f0
to
e68c945
Compare
20 buffers and 512 buffer size seems to result in a latency in audio being too high for my taste. From testing, it seems that 15 buffers at 256 buffer size seems more ideal. I'll probably change the default to that. The bigger the number of buffers, the bigger the chance the audio stretching algorithm has to react to the slowed game speed. If the game is constantly running slow, then low buffer sizes seem fine. It's the quick changes in game speed that make the low buffer sizes trip up. |
02e3027
to
150f574
Compare
I cleaned up the commit history a good amount, it should be much easier to follow. |
68ee745
to
0975408
Compare
Sync game to audio works again
I've been trying implement a "Dual Async Audio" plugin option that does time stretching when a device is unable to run a game quickly enough. This remove crackling audio when a game slows down for whatever reason. Instead of letting the audio buffers run dry, it instead "time stretches" audio until the game catches up again. This is at least the intention.
I'm using the SoundTouch library to achieve this, and from my limited testing so far, it seems to work pretty well.
There are still a couple of WIP:
@littleguy77 @Gillou68310 @paulscode Now here comes a question. Should I make this into a separate audio plugin or should the SLES audio plugin support the original operation and the dual sync audio operation depending on what the user selects?
I'm personally leaning towards making it into a different audio plugin due to the amount of change that was needed to make this work. It would be hard to reintegrate this back into the original SLES audio plugin. The other option would be replace the SLES audio plugin with this plugin and drop original functionality. And if the user wants, they can drop back to the SDL audio plugin.