|
03-05-2016, 01:11 AM
|
#1
|
Human being with feelings
Join Date: Sep 2009
Posts: 623
|
Low Latency Convolution
Do you guys know if ReaVerb uses the same FFT and convolution engine that is included in WDL? I've found that when I have ReaVerb set to LL and ZL, I can get nice zero latency reverb without any glitches.
However, I'm working on a reverb plugin based off of the convoEngine example, and I can't use long impulses without getting glitches in my plugin at zero latency. I'm looking through the convoengine code, and I'm not seeing any settings that I could be missing to make it more efficient. It's not hitting my cpu hard (~1%), but I still get pops/clicks in my plugin, but with the same impulse, I don't get pops/clicks in ReaVerb.
I've found that I get better performance running convoengine in floats rather than doubles.
Just curious to know if there are any tricks I'm missing to get the same performance as ReaVerb, or if they used something different altogether to get their code so efficient.
|
|
|
03-05-2016, 02:00 AM
|
#2
|
Human being with feelings
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,645
|
AFAIK ReaVerb's ZL uses WDL_ConvolutionEngine_Div, without ZL it uses WDL_ConvolutionEngine. However, ReaVerb's LL creates a worker thread, which would probably fix your glitches, but the worker thread code is not part of the original ConvoEngine. However, a while ago I have added WDL_ConvolutionEngine_Thread to the ConvoEngine in my WDL.
BTW, my ConvoEngine also includes some SSE/SSE3 optimisations.
|
|
|
03-05-2016, 11:05 AM
|
#3
|
Human being with feelings
Join Date: Sep 2009
Posts: 623
|
aaah. yes. Now I'm getting sweet sweet smooth convolution at zero latency. Are there any situations where using the threaded version might have negative side effects?
|
|
|
03-05-2016, 11:36 AM
|
#4
|
Human being with feelings
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,645
|
Well, there is a tiny bit of overhead (CPU use, memory, code size). But the CPU overhead will likely be negligible when compared to all the other stuff going on (FFTs, complex multiplies, FIFO queues etc.). The extra memory is because of the extra queues, how much memory depends on how much input you feed it before advancing the output queue.
|
|
|
03-18-2016, 12:36 AM
|
#5
|
Human being with feelings
Join Date: Sep 2009
Posts: 623
|
Just FYI, I don't know if you know this, but I noticed that if I set latency_allowed to anything other than 0, after 16348 samples, there is a break in the impulse for however many samples I have set to the latency_allowed.
So, for example, if I set latency_allowed to 512, 16348 samples into the impulse, it mutes for 512 samples and then continues on as normal for the rest of the impulse.
I haven't had a chance to look through the code yet to see what might be causing it, but I thought I'd let you know. If you need a better description, let me know.
|
|
|
03-18-2016, 01:46 AM
|
#6
|
Human being with feelings
Join Date: Sep 2009
Posts: 623
|
Found it.
in WDL_ConvolutionEngine_Thread::SetImpulse(), int offs ends up being the initial block size + the offset, but it should just be the blocksize.
So just making offs = impulsechunksize seems to fix it for me.
|
|
|
03-18-2016, 04:17 AM
|
#7
|
Human being with feelings
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,645
|
Quote:
Originally Posted by bozmillar
Just FYI, I don't know if you know this, but I noticed that if I set latency_allowed to anything other than 0, after 16348 samples, there is a break in the impulse for however many samples I have set to the latency_allowed.
|
Yeah, you are right, oops. I don't actually use latency_allowed anywhere myself, which is why I hadn't noticed this. BTW, this happens not necessarily after 16384 samples, but rather after maxfft_size.
Quote:
Originally Posted by bozmillar
Found it.
in WDL_ConvolutionEngine_Thread::SetImpulse(), int offs ends up being the initial block size + the offset, but it should just be the blocksize.
So just making offs = impulsechunksize seems to fix it for me.
|
Fix confirmed, thanks! Then we don't really need offs anymore at all i.e.:
Code:
diff --git a/WDL/convoengine.cpp b/WDL/convoengine.cpp
index 840614b..2dbeb5a 100644
--- a/WDL/convoengine.cpp
+++ b/WDL/convoengine.cpp
@@ -1155,11 +1155,11 @@ int WDL_ConvolutionEngine_Thread::SetImpulse(WDL_ImpulseBuffer *impulse, int max
int impulsechunksize = maxfft_size;
if (impulsechunksize >= samplesleft || !m_thread_enable) impulsechunksize=samplesleft;
- int offs = m_zl_engine.SetImpulse(impulse, maxfft_size, known_blocksize, impulsechunksize, impulse_offset, latency_allowed) + impulsechunksize;
+ m_zl_engine.SetImpulse(impulse, maxfft_size, known_blocksize, impulsechunksize, impulse_offset, latency_allowed);
samplesleft -= impulsechunksize;
m_thread_engine.SetImpulse(impulse, maxfft_size*2, impulse_offset + impulsechunksize, samplesleft);
- m_thread_engine.m_zl_delaypos = samplesleft > 0 ? offs : -1;
+ m_thread_engine.m_zl_delaypos = samplesleft > 0 ? impulsechunksize : -1;
m_thread_engine.m_zl_dumpage=0;
return GetLatency();
|
|
|
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 10:41 PM.
|