The Joy of AUs with Inline Modals


#1

First, to anyone reading this, thank you so much for your time. I am genuinely grateful.

My problems center around the loading and unloading of Audio Unit instances with inline modals in their startup code. In the beginning of development, I did not have this problem. I was loading and unloading using FileBasedDocument. Worked fine until I ran into speed and cloud sync requirements. Thus, I switched to a SQLite backend. All was well, problems fixed, testers were happy, thus I was happy... then I loaded Guitar Rig 5. Thats where the fun begins.

The problem would arise when I would load a saved tone (AudioProcessorGraph) that contained any Audio Unit from Native Instruments. So on loading, I would get this...

~AudioUnitPluginInstance()
{
    const ScopedLock sl (lock);
    #if JUCE_DEBUG
    // this indicates that some kind of recursive call is getting triggered that's
    // deleting this plugin while it's still under construction.
    jassert (AudioUnitFormatHelpers::insideCallback.get() == 0);   // THIS IS WHAT GOT TRIGGERED
    #endif

    ... more stuff below but not relevant yet
}

So I tested some theories, my absurd one was to take my loading function and split the AudioProcessorGraph::clear() into one std::thread x, and the actual loading from SQLite into another std::thread y. Then, call x.join() and y.join() to guarantee everything was done in proper order. Surprisingly, it worked. 

Now, I can load an AudioProcessorGraph that contains Native Instruments Audio Units (NIAU), everything seems good until I load another AudioProcessorGraph and get rid of the one containing a NIAU. I draw the same ~AudioUnitPluginInstance() as above but now I get an EXC_BAD_ACCESS  in this section of the deconstructor instead of tripping the jassert.

if (audioUnit != nullptr)
{
    if (prepared)
       releaseResources();
    
    AudioComponentInstanceDispose (audioUnit);  // this gets the EXC_BAD_ACCESS
    audioUnit = nullptr;
}

Now I will admit, I'm still young with C++. I came here from Javascript and Node.js apps. So there may be a glaring mistake I am making. Here is the actual build function's code.

void LabPresenter::buildGraph (std::string labName)
{   
   LabModel x = database.load(labName);
   
   std::thread clearThread([this](){
      std::cout << "clear called" << std::endl;
      audiograph.clear();
   });

   std::thread buildThread([this, x](){
      std::cout << "assemble the audiograph called" << std::endl;
      assembleTheAudioGraph(x);
   });

   clearThread.join();
   buildThread.join();
   
   sendChangeMessage();
}

As I see it, I have 2 options:

1. Fix this to where I can load and unload AudioProcessorGraphs without the NIAUs blowing things up.

2. Drop support for AU - which I really do not want to do. I still have VST and VST3 working but this is last resort.

 

Any help/insight/damnations/etc. are welcomed. Thank you.


#2

Heh, I think I figured out a way to make lemonade out of my lemons. Good bye AU support. I forgot about the other bugs that I was procastinating on fixing that revolved around AU. I don't have these problems on VST/VST3, with them everything runs perfect. From a business and reliability standpoint, this seems the most sensible stance for me to take. Good riddance to bad rubbish.