|
10-26-2017, 07:56 AM
|
#1
|
Human being with feelings
Join Date: Nov 2015
Location: Germany
Posts: 82
|
Worker threads in audio process
At the moment when parameters change I do new calculations in the audio thread. This includes preparing FIR filters and so on. So far so good, but when the CPU is very busy or the calculation gets to complex and takes too long (e.g. longer than the frame count), the audio glitches and I get drop outs.
The trace looks like this. When no parameter changes there is no problem, but when calculating the FIR (which is already optimized), it takes 15ms which is much too long.
3;16:44:47.052802100;ProcessDoubleReplacing;346;nF rames:512
3;16:44:47.053882200;calcFIR;297;Begin
3;16:44:47.068597800;calcFIR;468;End
3;16:44:47.069520900;ProcessDoubleReplacing;522;nF rames:512 End
3;16:44:47.069662900;ProcessDoubleReplacing;346;nF rames:512
I think I need some kind of asynchronous worker threads here (it's not important before which call of Replacing the calcFIR finishes). I'm succesfully doing some stuff in the GUI with worker threads but I wonder if this is a good idea in the audio thread. Could calls to std::thread lead to problems, glitches and drop outs ? And how to know that it has some new calculation ready ? I assume an atomic variable would do the job.
BTW by rising the audio buffer of the driver to 1024, the glitches disappear, but of course this can't be the solution.
Last edited by Andi!; 10-26-2017 at 08:20 AM.
|
|
|
10-26-2017, 08:50 AM
|
#2
|
Human being with feelings
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 8,062
|
Quote:
Originally Posted by Andi!
Could calls to std::thread lead to problems, glitches and drop outs ?
|
You definitely don't want to be creating std::thread (or any other thread wrappers that just use the underlying operating system implementation) instances in the audio thread. The runtime library or operating system might use a quick thread pool for that, but there are no guarantees at all. (Especially cross platform.)
So, you need to have your thread previously created and then continuously running and waiting for work to be passed into it. Or you could look into the platform specific concurrent/parallel task execution libraries like Apple's Grand Central Dispatch (GCD) or Microsoft's PPL. I would recommend just doing the latter, rolling even the simplest threaded task queue on your own is going to be complicated. Using Apple GCD is a bit annoying in C++ because it's a C API but with some template and other trickery it can be made easy to use in C++.
__________________
I am no longer part of the REAPER community. Please don't contact me with any REAPER-related issues.
Last edited by Xenakios; 10-26-2017 at 08:59 AM.
|
|
|
10-26-2017, 09:11 AM
|
#3
|
Human being with feelings
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,645
|
Or just use CreateThread() on Windows, and pthread on macOS; that is what I do for the worker thread in my version of the WDL convolution engine. But yeah, that does get complicated, because you will also need to think about events/signals, locks, thread priorities, etc.
|
|
|
10-26-2017, 09:14 AM
|
#4
|
Human being with feelings
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 8,062
|
Quote:
Originally Posted by Tale
Or just use CreateThread() on Windows, and pthread on macOS
|
Which is again potentially horrible, if it is done in the audio thread. (std::thread and similar are just relatively light wrappers around those low level calls.)
edit : What I gathered from the original poster was that he intended to do something like :
Code:
void processReplacing(...blah...)
{
if (filterparameterschanged)
{
std::thread coeffsthread(...blahblah...);
coeffsthread.detach();
}
...audio processing...
}
No matter if std::thread or the OS thread creation functions would be used for that, not a good idea.
__________________
I am no longer part of the REAPER community. Please don't contact me with any REAPER-related issues.
Last edited by Xenakios; 10-26-2017 at 09:21 AM.
|
|
|
10-26-2017, 09:33 AM
|
#5
|
Human being with feelings
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,645
|
Yeah, I meant doing what you said i.e. create a thread once, and then signal it when you need it to do some work.
|
|
|
10-26-2017, 09:37 AM
|
#6
|
Human being with feelings
Join Date: Nov 2015
Location: Germany
Posts: 82
|
Thank you! You're right, I shouldn't do that in the audio thread. A continous running (but not busy) std::thread would be great. What about a c11 condition variable? Seems to be the right thing to signal the worker thread that there is something to do. I hope that I don't need a queue. The worker thread could have the atomic state idle, calculating or finished calculation. I would test in the audio thread e.g. every x samples if I have to start a new calculation (parameters changed & state=idle) or I have to pull the results from the finished calculation. When the worker thread is calculating, nothing would happen in the audio thread and the previous calculation is still valid.
|
|
|
10-27-2017, 08:57 AM
|
#7
|
Human being with feelings
Join Date: Nov 2015
Location: Germany
Posts: 82
|
I got an easy worker thread working now. Well, it doesn't really work at the moment (just waits). But it syncs to the audio thread and gets a signal with the mentioned condition variable. I just use platform independent standard c11 stuff like std::thread, mutex, condition_variable, atomic & unique_lock and the trace shows me that I'm on the right way. When the plug-in is deconstructed the thread will be signaled and ended correctly. I have tested it with Reaper,Cubase,Ableton,Logic,AUVal,ProTools & Studio One and it seems to work great on Win & Mac even with multiple instances.
Now I'm thinking about what the safest method is, to access data of the audio thread (some arrays) in the worker thread. Locking the IPlug mutex for a very short time or using shared pointers/atomic data come to mind...
|
|
|
Thread Tools |
|
Display Modes |
Linear Mode
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
All times are GMT -7. The time now is 04:19 AM.
|