How to reset plugin buffers in hosts that suspend ProcessReplacing()?
-
Jimbrowski-one Jimbrowski-one https://www.kvraudio.com/forum/memberlist.php?mode=viewprofile&u=157544
- KVRist
- 80 posts since 13 Aug, 2007 from Montréal, QC
What I did in one of my (likely never to be released) plugins, was to listen for in coming MIDI events for "all-notes-off" (0x7b) and "all-sounds-off" (0x78). You might also want to consider resetting things if you ever receive a setProgram with a program index that is the same as your current program index... or depending on what your users would expect, maybe any setProgram received, merits a reset.
-
- KVRian
- Topic Starter
- 617 posts since 30 Aug, 2012
Yeah, but that would take all the fun out of it! I didn't know that, will try. Thanks!
In the meantime, how about something like this (haven't tried it yet):
ProcessDoubleReplacing(double** inputs, double** outputs, int nFrames)
{
curPos = GetSamplePos();
if (curPos < lastPos) Reset(); //playback resumed behind stop point
if (curPos > lastPos) Reset(); //playback resumed forward of stop point
lastPos = curPos;
//---------------------------------------------------------------------------------------------------
for (int s = 0; s < nFrames; ++s, ++in1, ++in2, ++out1, ++out2)
{
lastPos += 1;
Last edited by Fender19 on Wed Jan 09, 2019 11:06 pm, edited 1 time in total.
-
- KVRian
- 1265 posts since 9 Sep, 2005 from Oulu, Finland
Kind of doubtful Wavelab, which seems to be the actual problem host in this case, would be sending such messages to audio effect plugins...(Of course, everything is possible...)Jimbrowski-one wrote: ↑Wed Jan 09, 2019 10:57 pm What I did in one of my (likely never to be released) plugins, was to listen for in coming MIDI events for "all-notes-off" (0x7b) and "all-sounds-off" (0x78).
- KVRist
- 347 posts since 20 Apr, 2005 from Moscow, Russian Federation
The disadvantage of the sample position workaround is that it will break a looped playback.
-
- KVRian
- Topic Starter
- 617 posts since 30 Aug, 2012
I have something that appears to work. Not fully tested, or "sample accurate", but it seems to be working in Wavelab:
ProcessDoubleReplacing(double** inputs, double** outputs, int nFrames)
{
curPos = GetSamplePos();
if (curPos < lastPos) Reset();//playback resumed behind block stop point
if (curPos > (lastPos + 2 * nFrames)) Reset(); //playback resumed forward of block stop point
lastPos = curPos;
Now, how to make this more accurate and robust? I'm not sure about the "2 * nFrames" since frame size can vary block-to-block. I used "2 *" nFrames to make sure there was some buffer space.
Anyhow, it's a step in the right direction (I think)!
ProcessDoubleReplacing(double** inputs, double** outputs, int nFrames)
{
curPos = GetSamplePos();
if (curPos < lastPos) Reset();//playback resumed behind block stop point
if (curPos > (lastPos + 2 * nFrames)) Reset(); //playback resumed forward of block stop point
lastPos = curPos;
Now, how to make this more accurate and robust? I'm not sure about the "2 * nFrames" since frame size can vary block-to-block. I used "2 *" nFrames to make sure there was some buffer space.
Anyhow, it's a step in the right direction (I think)!
Last edited by Fender19 on Thu Jan 10, 2019 12:34 am, edited 3 times in total.
-
- KVRian
- Topic Starter
- 617 posts since 30 Aug, 2012
-
- KVRian
- Topic Starter
- 617 posts since 30 Aug, 2012
NOPE - I was wrong. This does not work in Wavelab. Reason: GetSamplePos() returns the TOTAL number of samples played, not WHERE it is in the track! Makes no sense! The sample count reported keeps going up no matter where I place the cursor.Fender19 wrote: ↑Wed Jan 09, 2019 11:58 pm I have something that appears to work. Not fully tested, or "sample accurate", but it seems to be working in Wavelab:
ProcessDoubleReplacing(double** inputs, double** outputs, int nFrames)
{
curPos = GetSamplePos();
if (curPos < lastPos) Reset();//playback resumed behind block stop point
if (curPos > (lastPos + 2 * nFrames)) Reset(); //playback resumed forward of block stop point
lastPos = curPos;
Now, how to make this more accurate and robust? I'm not sure about the "2 * nFrames" since frame size can vary block-to-block. I used "2 *" nFrames to make sure there was some buffer space.
Anyhow, it's a step in the right direction (I think)!
Ahhhhhhhh Back to the drawing board...
- KVRist
- 347 posts since 20 Apr, 2005 from Moscow, Russian Federation
How difficult could it be to modify IPlug sources themselves? I've taken a quick look into its sources (not sure if that was the same version you use) - well, a bit tricky (just too much code to get trough in a few minutes) - but not undoable... If this is really about unhandled `suspend/resume` messages the fix could be very simple.
-
- KVRian
- 1265 posts since 9 Sep, 2005 from Oulu, Finland
As far as I can see, it is not about that. The IPlug code is doing pretty much the same what the Steinberg C++ VST2 wrapper code is doing. Note that the VST2 C API itself does not have any suspend or resume calls or opcodes. The Steinberg C++ class calls its suspend() and resume() methods when the host calls the effMainsChanged opcode. IPlug actually calls its Reset() method in response to some other opcodes too.
- KVRist
- 347 posts since 20 Apr, 2005 from Moscow, Russian Federation
I Know. I used `suspend`/`resume` notation only to not confuse this with yet more different API details.
Does it? Ah, never mind, I see it now: https://github.com/olilarkin/wdl-ol/blo ... T.cpp#L440 (I'm not sure how this version matches yours though). Then it's definitely not what I suspected earlier.The IPlug code is doing pretty much the same
Either way that's why primarily I suggested to try to monitor all WaveLab calls during stop/start - to find the exact reason/root of the problem (I still can't believe WL does not trigger any useful events at start/stop). W/o knowing exact reason the whole thing goes more like "trying to cure symptoms instead of the illness itself".
Honestly the problem surprises me a lot as it seems to be quite critical (it should affect too many effect types and be easy noticable) for none using IPlug to not face it before. On the other hand we know for sure that most of effects do not suffer from this - and I don't really believe anybody had actually to write any tricky workarounds/kludges for this. Very strange. So something somewhere in IPlug<->VST code is still the first suspect.
Last edited by Max M. on Thu Jan 10, 2019 3:55 am, edited 1 time in total.
-
- KVRian
- Topic Starter
- 617 posts since 30 Aug, 2012
Exactly my thought, "OTHER developers must have come across this - what are THEY doing?" That's why I asked here.Max M. wrote: ↑Thu Jan 10, 2019 2:51 am Honestly the problem surprises me a lot as it seems to be quite critical (it should affect too many effect types and be easy noticable) for none using IPlug to not face it before. On the other hand we know for sure that most of effects do not suffer from this - and I don't really believe anybody had actually to write any tricky workarounds/kludges for this. Very strange. So something somewhere in IPlug<->VST code is still the first suspect.
I've also asked over on the WDL-OL forum (home of IPlug) and have basically received the same answer - crickets! I was hoping someone had a simple, "oh, you do this" answer.
My last thought was that maybe the "Tails" parameter has something to do with this but I've played with it a bit and that doesn't seem to be the key either.
-
- KVRian
- 1265 posts since 9 Sep, 2005 from Oulu, Finland
You seem to be concerned about the behavior of Wavelab in particular. Maybe Wavelab just isn't a popular host for plugin developers to test with?
-
- KVRian
- 1265 posts since 9 Sep, 2005 from Oulu, Finland
IPlug and JUCE are missing handlers for effStartProcess and effStopProcess (from VST2.x), those sound promising but do they actually have anything to do with this?
- KVRAF
- 7868 posts since 12 Feb, 2006 from Helsinki, Finland
Well, checking WDL-OL master branch on Github, it seems IPlug calls Reset() on suspend (but not resume) for VST2, whenever bypass state changes (in either direction) for AU, but only in setupProcessing for VST3. Maybe there is some logic behind all this, but it seems somewhat inconsistent.Max M. wrote: ↑Thu Jan 10, 2019 1:34 am How difficult could it be to modify IPlug sources themselves? I've taken a quick look into its sources (not sure if that was the same version you use) - well, a bit tricky (just too much code to get trough in a few minutes) - but not undoable... If this is really about unhandled `suspend/resume` messages the fix could be very simple.
If you don't want to mess with the IPlug sources, you could try putting the reset-code in OnActivate() and see if that makes a difference. That one seems to be called in for both suspend and resume for VST2 and whenever bypass state changes for AU or VST3.
- KVRist
- 347 posts since 20 Apr, 2005 from Moscow, Russian Federation
Maybe Wavelab just isn't a popular host for plugin developers to test with?
Still there should be a lot of complains from WL users, like... hmm... "I hear ghost echos/reverb-tails every time I re-start my song". No idea how many widely IPlug based delays/reverbs are out there, but an overall result of the IPlug_based_plugins * type_of_effects_affected * n_of_wl_users equation cannot be that small to have no trace :) (Or can it?)
Still there should be a lot of complains from WL users, like... hmm... "I hear ghost echos/reverb-tails every time I re-start my song". No idea how many widely IPlug based delays/reverbs are out there, but an overall result of the IPlug_based_plugins * type_of_effects_affected * n_of_wl_users equation cannot be that small to have no trace :) (Or can it?)