I’ve come across an issue with AUv3 plugins on iOS: When handling MIDI events that trigger file I/O operations, it seems the same MIDI event gets processed multiple times, causing what appears to be a feedback loop.
Has anyone else experienced this behavior or have any insights into why it might be occurring?
After some investigation, I discovered that I was loading the file directly from the audio thread. This meant that a new call to processBlock could occur before the previous one had finished. Moving the file loading to a separate thread resolved the issue.
Interestingly, this led me to notice a peculiar behavior in AUv3 that doesn’t occur with other formats: if the processing of a block isn’t finished when the host starts the next call, the MIDI buffer from the previous call is resent with messages with a negative timestamp!
This is because AUv3 MIDI events are timestamped relative to the current audio block.
But, one dumb question for you: which version of JUCE are you using? JUCE/develop branch or something else? Because I seem to recall this was refactored recently in JUCE, somehow .. still looking for the thread, however ..
I found this excellent analysis in my archives, it might explain why this is designed this way:
Essentially, MIDI events have to be properly time-stamped, and I believe that AUv3’s “negative time” is important in calculating properly accurate timestamps for MIDI events ..
EDIT: JUCE 7.0.12 - yes, same here, but I regularly test on JUCE 8.0.6 and -develop branches. Maybe you have a chance to do the same and see what difference it makes?
I just tried with JUCE 8.0.6 and I get the exact same behaviour, an inifinite “feedback loop” of midi messages with negative timestamp from a single key press.
The timestamps make sense, it basically is just sending over an over the first midi message with the sample offset from the block in which it was received.
However, I’m puzzled by the behavior in AUv3: why isn’t the MIDI buffer cleared between processBlock calls as it is in other formats? Could it be that if processBlock doesn’t finish in time, the previous buffer is retained? Is this an intentional behavior in AUv3?