iOS AUv3 : crash in JuceAudioUnitv3::setFullState

Hi,

I noticed that each time I change the number of parameters of my iOS auv3 plugin, when reloading a project saved with the previous number of parameters with any host (Garageband, AUM,…), I’m getting a crash in the call to setFullState :

ObjCMsgSendSuper<AUAudioUnit, void> (au, @selector (setFullState:), state);

(note: in my case the crash happens when 2 instances are loaded in the project, but I think this is only a detail)

The error is:
uncaught exception 'NSInternalInconsistencyException', reason: 'Archive under main: corrupt type: 16'

So, I have a feeling that this might not be a JUCE issue , but just a bug of the Apple AudioToolkitCore framework when it tries to deserialize its own data.

However, is this data really useful ? Looking at the Apple doc here:

it says:

The base class implementation of this property saves the values of all parameters currently in the parameter tree.

So it seems we can just skip this call, none of the other juce plugin formats are saving the individual values of parameters , they just use the AudioProcessor::getStateInformation.

And then if I comment the calls to

ObjCMsgSendSuper<AUAudioUnit, NSDictionary<NSString*, id>*> (au, @selector (fullState));
and
ObjCMsgSendSuper<AUAudioUnit, void> (au, @selector (setFullState:), state);

in juce_AUv3_Wrapper.mm then the plugin is state is still correctly saved and restored , and I’m not getting that crash anymore.

I think we probably need to keep the call, or at least preserve some of its behaviour. As well as storing the parameter values, it also adds the plugin’s ID code, manufacturer code, and version to the state dictionary. I can imagine that some hosts may need this information, so I’m reluctant to remove it completely.

I tried to repro the bug by creating a GarageBand project using the DSPModulePluginDemo, adding a parameter to the plugin, and then reloading the project, but I don’t seem to get any crash in this case. My GarageBand version is 2.3.14, running on iPadOS 16.4 Developer Beta 3. It would be helpful to know the exact host versions and iOS versions you’re running. Are you able to reproduce the same behaviour in any of the JUCE example plugins?

Yes I can reproduce it with the AudioPluginDemo, I just did it in AUM and Garageband, they both crashed.
I started by editing the JuceDemoPluginAudioProcessor to add dummy params:

    JuceDemoPluginAudioProcessor()
        : AudioProcessor (getBusesProperties()),
          state (*this, nullptr, "state",
                 { std::make_unique<AudioParameterFloat> (ParameterID { "gain",  1 }, "Gain",           NormalisableRange<float> (0.0f, 1.0f), 0.9f),
                  std::make_unique<AudioParameterFloat> (ParameterID { "gain2",  1 }, "Gain2",           NormalisableRange<float> (0.0f, 1.0f), 0.9f),
                   std::make_unique<AudioParameterFloat> (ParameterID { "gain3",  1 }, "Gain3",           NormalisableRange<float> (0.0f, 1.0f), 0.9f),
                   std::make_unique<AudioParameterFloat> (ParameterID { "gain4",  1 }, "Gain4",           NormalisableRange<float> (0.0f, 1.0f), 0.9f),
                   std::make_unique<AudioParameterFloat> (ParameterID { "gain5",  1 }, "Gain5",           NormalisableRange<float> (0.0f, 1.0f), 0.9f),
                   std::make_unique<AudioParameterFloat> (ParameterID { "gain6",  1 }, "Gain6",           NormalisableRange<float> (0.0f, 1.0f), 0.9f),
                   std::make_unique<AudioParameterFloat> (ParameterID { "gain7",  1 }, "Gain7",           NormalisableRange<float> (0.0f, 1.0f), 0.9f),
                   std::make_unique<AudioParameterFloat> (ParameterID { "delay", 1 }, "Delay Feedback", NormalisableRange<float> (0.0f, 1.0f), 0.5f) })

Then I load 2 instances if the plugin in AUM (or garageband). I close AUM.

Now I comment all the gain2…gain7 params. Install again, and launch AUM again, and here is the crash:

Exception: Archive under : corrupt type: 102
Archive under : corrupt type: 102
(
	0   CoreFoundation                      0x000000018c649e44 42CCFC7B-FF32-3D25-8F01-CCB2AD843A8B + 40516
	1   libobjc.A.dylib                     0x00000001858538d8 objc_exception_throw + 60
	2   CoreFoundation                      0x000000018c739c28 42CCFC7B-FF32-3D25-8F01-CCB2AD843A8B + 1023016
	3   AudioToolboxCore                    0x0000000197ac41b4 6FB8EAE2-60F1-3DFF-B385-2FD714057E4F + 1282484
	4   AudioToolboxCore                    0x0000000197ab9704 6FB8EAE2-60F1-3DFF-B385-2FD714057E4F + 1238788
	5   AudioPluginDemo                     0x000000010267b320 _ZN4juce16ObjCMsgSendSuperI11AUAudioUnitvJP12NSDictionaryIP8NSStringP11objc_objectEEEET0_S6_P13objc_selectorDpT1_ + 92
	6   AudioPluginDemo                     0x000000010267b1d0 _ZN15JuceAudioUnitv312setFullStateEP12NSDictionaryIP8NSStringP11objc_objectE + 168
	7   AudioPluginDemo                     0x000000010267b0cc _ZZN15JuceAudioUnitv35ClassC1EvENKUlP11objc_objectP13objc_selectorP12NSDictionaryIP8NSStringS2_EE_clES2_S4_S9_ + 44
	8   AudioPluginDemo                     0x000000010267b11c _ZZN15JuceAudioUnitv35ClassC1EvENUlP11objc_objectP13objc_selectorP12NSDictionaryIP8NSStringS2_EE_8__invokeES2_S4_S9_ + 44
..

This is an iPad running iOS 16.3.1.

Thanks, I was able to reproduce the issue and have a workaround on the way.

Out of interest, are you adding/removing parameters to an AUv3 that you’ve already released? If so, you should be aware that doing so may break automation in GarageBand and Logic. This is due to a known limitation in those hosts. There’s no workaround for this on the plugin side (afaik), so I’d recommend keeping parameters unchanged between plugin releases if at all possible.

Great, thank you !

Yes the plugin can be upgraded from a “basic” version to an “advanced” version, which adds a lot of new parameters. I may have to think about it again,thanks for the tip. Those two hosts are such a source of annoyances…

Thanks for the report. The issue should be fixed on develop:

1 Like