Need advice for debugging plugin
- KVRist
- 405 posts since 14 Jul, 2005 from Germany
Hi Martin,
not sure if you can need it. Christian Budde's "VST-Plugin Unit Test":
http://www.savioursofsoul.de/Christian/programs/tools/
not sure if you can need it. Christian Budde's "VST-Plugin Unit Test":
http://www.savioursofsoul.de/Christian/programs/tools/
It`s not a bug... it`s a feature!
-
- KVRian
- Topic Starter
- 960 posts since 27 Jun, 2009 from Germany
RexXx wrote:Hi Martin,
not sure if you can need it. Christian Budde's "VST-Plugin Unit Test":
http://www.savioursofsoul.de/Christian/programs/tools/
Yes, I got that one. Only tried it briefly, and it was freezing somewhere during the tests. I will run it through all the tests one by one later.
Thanks,
Martin
-
- KVRAF
- 1940 posts since 16 Aug, 2004 from Vienna, Austria
-
- KVRian
- Topic Starter
- 960 posts since 27 Jun, 2009 from Germany
No, nothing reported there. I will start digging into the different routines now...arakula wrote: You might want to look into the PlugIn's Info window. If it produced a crash, and VSTHost is able to notice it, it stops the PlugIn from processing. The fact is reported in the Info window.
Martin
- KVRAF
- 2187 posts since 25 Jan, 2007 from the back room, away from his wife's sight (or so he thinks)
And another +1 from me.arakula wrote:+1mystran wrote:(I'm still using MSVC2008 because 2010 IDE is just horrid)
2008 was _great_. 2010 is ...
Cakewalk by Bandlab / FL Studio
Squire Stratocaster / Chapman ML3 Modern V2 / Fender Precision Bass
Formerly known as arke, VladimirDimitrievich, bslf, and ctmg. Yep, those bans were deserved.
Squire Stratocaster / Chapman ML3 Modern V2 / Fender Precision Bass
Formerly known as arke, VladimirDimitrievich, bslf, and ctmg. Yep, those bans were deserved.
-
- KVRian
- Topic Starter
- 960 posts since 27 Jun, 2009 from Germany
OK. I got some more details on this one:martin_l wrote:RexXx wrote:Hi Martin,
not sure if you can need it. Christian Budde's "VST-Plugin Unit Test":
http://www.savioursofsoul.de/Christian/programs/tools/
Yes, I got that one. Only tried it briefly, and it was freezing somewhere during the tests. I will run it through all the tests one by one later.
Thanks,
Martin
It freezes for the following reason:
In the test for Parameter Sweeps and SetProgramme, the Unit test is sending one event after the other one and calls processEvents() without ever calling process() or processReplacing().
So far, in processEvents I added events to an internal event queue, which then was processed during the processReplacing() call. This never happened in the unit test, and at some point it must have crashed (did not get that far with the debugger...)
Here is the question:
Is my approach safe, or should I always process all events in the processEvents() routine, and not assume that processReplacing() will _normally_ be called afterwards?
Cheers,
Martin
-
AdmiralQuality AdmiralQuality https://www.kvraudio.com/forum/memberlist.php?mode=viewprofile&u=83902
- Banned
- 6657 posts since 10 Oct, 2005 from Toronto, Canada
Those events all come with deltaFrames timestamps, so they're only valid being interpreted within the next block of samples passed to processReplacing().martin_l wrote:OK. I got some more details on this one:martin_l wrote:RexXx wrote:Hi Martin,
not sure if you can need it. Christian Budde's "VST-Plugin Unit Test":
http://www.savioursofsoul.de/Christian/programs/tools/
Yes, I got that one. Only tried it briefly, and it was freezing somewhere during the tests. I will run it through all the tests one by one later.
Thanks,
Martin
It freezes for the following reason:
In the test for Parameter Sweeps and SetProgramme, the Unit test is sending one event after the other one and calls processEvents() without ever calling process() or processReplacing().
So far, in processEvents I added events to an internal event queue, which then was processed during the processReplacing() call. This never happened in the unit test, and at some point it must have crashed (did not get that far with the debugger...)
Here is the question:
Is my approach safe, or should I always process all events in the processEvents() routine, and not assume that processReplacing() will _normally_ be called afterwards?
Cheers,
Martin
As to whether your approach is safe, hard to say without seeing what you're doing in processEvents. You should copy events to your own queue (don't expect the event pointers to remain valid after processEvents returns!) and of course you interpret these events in processReplacing, on the particular sample offset their deltaFrames value indicates, and remove them from your queue once they've been processed.
You also shouldn't assume processEvents will only be called once between each call to processReplacing. So it shouldn't blow up if your own copy of the events hasn't been emptied in processReplacing yet. It should just add more events to your queue.
I've built-in automatic protection to keep my event queue from growing too large, though this never happens.
-
- KVRian
- Topic Starter
- 960 posts since 27 Jun, 2009 from Germany
Yes, in processEvents() I go through the list of events, read them out and thenAdmiralQuality wrote: Those events all come with deltaFrames timestamps, so they're only valid being interpreted within the next block of samples passed to processReplacing().
As to whether your approach is safe, hard to say without seeing what you're doing in processEvents. You should copy events to your own queue (don't expect the event pointers to remain valid after processEvents returns!) and of course you interpret these events in processReplacing, on the particular sample offset their deltaFrames value indicates, and remove them from your queue once they've been processed.
add my own events to the corresponding queues of my MidiHandler, my SysexHandler and the VoiceAllocator. All of them have a their own queue.
These queues are then processed during the processReplacing() call.
The queues themselves are implemented as a STL list of "myEvent"'s, and also include locking when pushing and popping elements, so that there should be no conflicts when processEvents and processReplacing are running simultaneously.AdmiralQuality wrote: You also shouldn't assume processEvents will only be called once between each call to processReplacing. So it shouldn't blow up if your own copy of the events hasn't been emptied in processReplacing yet. It should just add more events to your queue.
I've built-in automatic protection to keep my event queue from growing too large, though this never happens.
Actually, it is the processEvents call which will wait until the queue is unlocked. If processReplacing finds the queue locked, it will simply ignore the event in the current frame, and try again in the next one.
So far, I did not limit the queue, as I was assuming, that there should not be an overflow problem.
Cheers,
Martin
-
AdmiralQuality AdmiralQuality https://www.kvraudio.com/forum/memberlist.php?mode=viewprofile&u=83902
- Banned
- 6657 posts since 10 Oct, 2005 from Toronto, Canada
Any host that would call processEvents while processReplacing is running is truly evil. I doubt you'll find that ever happens, though it doesn't hurt to guard against it.martin_l wrote: The queues themselves are implemented as a STL list of "myEvent"'s, and also include locking when pushing and popping elements, so that there should be no conflicts when processEvents and processReplacing are running simultaneously.
You shouldn't ignore the events in the current frame as their deltaFrames "timestamps" are only valid for that frame. (As to what happens if a deltaFrames value is longer than the next frame length, I'm not sure. A well behaved host shouldn't do this, but of course it's possible.)
Actually, it is the processEvents call which will wait until the queue is unlocked. If processReplacing finds the queue locked, it will simply ignore the event in the current frame, and try again in the next one.
Sorting events by their deltaFrames value is also not guaranteed, though again well behaved hosts will pass you the events already in sorted order. You will also find negative deltaFrames values from events that are performed live as opposed to played back from recording. MIDI events are always at least one frame late when played live.
Definitely put break points at any of these special conditions so you'll see if/when they happen. I doubt any of this is the problem though.
One thing I'd recommend is cutting out chunks of code to isolate where the problem is. Say, bypass event handling entirely, and bypass your synth process, and just make your processReplacing function output a sine wave or something simple like that. Then, piece by piece, re-enable your various components and see when the trouble starts.
-
- KVRist
- 95 posts since 25 Jul, 2007 from Finland
Yeah, the shortcut seems to work, thanks for the tip. But the feature is not in any menu by default, and according to Microsoft docs it's not supported at all.mystran wrote: I think that's just the C# version.
IIRC even in 2010 (I'm still using MSVC2008 because 2010 IDE is just horrid), in C++ version you press ctrl-alt-P and that's it.
-
- KVRian
- Topic Starter
- 960 posts since 27 Jun, 2009 from Germany
Yes, I did not expect that. But, I use the same event queue for automation parameter changes, which can occur at the same time. The queues perform timeordering when appending (inserting) a new event. This is my attempt to make sure that automation data and MIDI events, addressing the same parameter (e.g. through MIDI Learn) do not conflict.AdmiralQuality wrote: Any host that would call processEvents while processReplacing is running is truly evil. I doubt you'll find that ever happens, though it doesn't hurt to guard against it.
I hope that this event does not really occur. But in this case, I reset the timestamp to zero.AdmiralQuality wrote:
You shouldn't ignore the events in the current frame as their deltaFrames "timestamps" are only valid for that frame. (As to what happens if a deltaFrames value is longer than the next frame length, I'm not sure. A well behaved host shouldn't do this, but of course it's possible.)
Yes, that's the next step: switching off portions of the code, one by one, until it behaves well. But that will have to wait, as I will be away from my development computer for the next week.AdmiralQuality wrote: Sorting events by their deltaFrames value is also not guaranteed, though again well behaved hosts will pass you the events already in sorted order. You will also find negative deltaFrames values from events that are performed live as opposed to played back from recording. MIDI events are always at least one frame late when played live.
Definitely put break points at any of these special conditions so you'll see if/when they happen. I doubt any of this is the problem though.
One thing I'd recommend is cutting out chunks of code to isolate where the problem is. Say, bypass event handling entirely, and bypass your synth process, and just make your processReplacing function output a sine wave or something simple like that. Then, piece by piece, re-enable your various components and see when the trouble starts.
Cheers,
Martin
-
AdmiralQuality AdmiralQuality https://www.kvraudio.com/forum/memberlist.php?mode=viewprofile&u=83902
- Banned
- 6657 posts since 10 Oct, 2005 from Toronto, Canada
Yes, but automation in VST 2.4 isn't sample accurate. So setParameter gets called for all parameters that need it (ideally) between processReplacing calls. All we know is it's supposed to happen some time in that next buffer of samples, but not exactly where. (Many plug-ins also apply smoothing to parameter changes, so a single change of parameter may actually take place over many samples.)martin_l wrote:Yes, I did not expect that. But, I use the same event queue for automation parameter changes, which can occur at the same time.AdmiralQuality wrote: Any host that would call processEvents while processReplacing is running is truly evil. I doubt you'll find that ever happens, though it doesn't hurt to guard against it.
You will find setParameter getting called during processReplacing in many hosts (this remains shocking to me) but obviously any of those changes must apply to the next buffer, as there's no way for the host to know how far through the buffer the currently running processReplacing is.
That should be a fairly rare case as well. Really, it's the users' fault if they're sending MIDI and automation messages to the same control at the same time. If the control jumps around like crazy, that's exactly what they've asked it to do. But the MIDI will usually "win" because it will usually have a deltaFrames value. Where automation has no timestamp at all, other than do it as soon as possible.
The queues perform timeordering when appending (inserting) a new event. This is my attempt to make sure that automation data and MIDI events, addressing the same parameter (e.g. through MIDI Learn) do not conflict.
The really smart way to handle this would be to decrement the deltaFrames value for every queue element at every sample. When the count reaches zero, the event fires. Then the events could easily overlap into the next buffer.I hope that this event does not really occur. But in this case, I reset the timestamp to zero.AdmiralQuality wrote:
You shouldn't ignore the events in the current frame as their deltaFrames "timestamps" are only valid for that frame. (As to what happens if a deltaFrames value is longer than the next frame length, I'm not sure. A well behaved host shouldn't do this, but of course it's possible.)
This might sound crazy, but there are some crazy hosts out there. I'm not sure offhand if it ever happens, but I wouldn't be surprised as there are hosts that do other wacko (you might even say "fruity") things like changing the sampleFrames size in successive calls to processReplacing.
Oh no! (I'm one of the people who can't wait to see this released. I think you did an amazing job on the SE-based one.)Yes, that's the next step: switching off portions of the code, one by one, until it behaves well. But that will have to wait, as I will be away from my development computer for the next week.AdmiralQuality wrote: Sorting events by their deltaFrames value is also not guaranteed, though again well behaved hosts will pass you the events already in sorted order. You will also find negative deltaFrames values from events that are performed live as opposed to played back from recording. MIDI events are always at least one frame late when played live.
Definitely put break points at any of these special conditions so you'll see if/when they happen. I doubt any of this is the problem though.
One thing I'd recommend is cutting out chunks of code to isolate where the problem is. Say, bypass event handling entirely, and bypass your synth process, and just make your processReplacing function output a sine wave or something simple like that. Then, piece by piece, re-enable your various components and see when the trouble starts.
Cheers,
Martin
-
- KVRAF
- 2460 posts since 3 Oct, 2002 from SF CA USA NA Earth
Variable block size is, like, the least wacko behavior in any host. That's why it's a parameter to process/processReplacing() instead of a parameter to resume().AdmiralQuality wrote:there are hosts that do other wacko (you might even say "fruity") things like changing the sampleFrames size in successive calls to processReplacing.
-
AdmiralQuality AdmiralQuality https://www.kvraudio.com/forum/memberlist.php?mode=viewprofile&u=83902
- Banned
- 6657 posts since 10 Oct, 2005 from Toronto, Canada
Right. But if they're daring to change block size, are they also checking the deltaFrames of the pending events to make sure that they don't overshoot the next block? (Not that that's technically illegal, but I bet you'll cause a bunch of instruments to break if you do that in a host.)Borogove wrote:Variable block size is, like, the least wacko behavior in any host. That's why it's a parameter to process/processReplacing() instead of a parameter to resume().AdmiralQuality wrote:there are hosts that do other wacko (you might even say "fruity") things like changing the sampleFrames size in successive calls to processReplacing.
Also, block size often has audible artifacts in many plug-ins. (In particular, the update rate for automation.) So to change it on the fly is, in my opinion, not a great idea.
IMHO, sampleFrames should either be the size of the hardware buffer, which makes sense for a whole bunch of reasons. Or 1, which makes sense for a bunch of other reasons. But that's just me...
-
- KVRAF
- 2460 posts since 3 Oct, 2002 from SF CA USA NA Earth
Unless, of course, they're matching the block size to the actual varying number of samples between recorded automation events.AdmiralQuality wrote:Right. But if they're daring to change block size, are they also checking the deltaFrames of the pending events to make sure that they don't overshoot the next block? (Not that that's technically illegal, but I bet you'll cause a bunch of instruments to break if you do that in a host.)Borogove wrote:Variable block size is, like, the least wacko behavior in any host. That's why it's a parameter to process/processReplacing() instead of a parameter to resume().AdmiralQuality wrote:there are hosts that do other wacko (you might even say "fruity") things like changing the sampleFrames size in successive calls to processReplacing.
Also, block size often has audible artifacts in many plug-ins. (In particular, the update rate for automation.) So to change it on the fly is, in my opinion, not a great idea.


