Loading old VST3 sessions?

We’re having problems trying to load old sessions that were saved with non-JUCE versions of the plug-in. While AAX falls back on a default of extracting the old parameter values from the stream, which happens to work for us because our old AAX used that default method of writing the data, our old VST3 sessions don’t work at all. The code calls setState(), which calls readFromMemoryStream(), which fails, apparently because it fails to create anything from the IBStream* data. I can’t debug beyond that, however, as all I see is the interface headers, not any code for the creation of the ISizeableStream object. It then tries to use readFromUnknownStream(), which calls loadStateData (with 108 bytes), but that fails as well, and so the session fails to load any of our plugin data at all.

Is there any way that we can customize the behavior of the VST3 wrapper, preferably without editing the JUCE code (which I’m not permitted to do here)? I had written code that our setStateInformation() function could fall back on if our own parsing of the VST3 session data failed, but our function is never called because of the failure of the above code. I need a way to either allow it to reach our code (and let us detect that it’s old non-JUCE code), or else I need a way to override the wrapper behavior so that we can write our own code to load the old state information.

Anyone know how to do either one of these?

(I have not tested loading of old AU or VST2 session data yet, by the way. I wouldn’t be surprised if the same problems are there, especially since out old AU was built using the auwrapper in the VST3 SDK.)

1 Like

The same holds for Audio Units. My new AU build loads using the old session, but none of the plug-in’s data is loaded (at least in Studio One 4).

Does anyone have any insight into this issue? Has it been addressed in newer versions of JUCE? (We’re using 5.3.2.) This is holding up a release, so it’s vital we get some kind of solution asap. Thanks!

Why are you not permitted to modify the JUCE code?

I’m a little surprised that it fails so drastically… Where exactly is it failing?

Modifying SDK code means having to make sure we do so any time we update the SDK, and leaves open the possibility that a fix we make in one version no longer works or breaks something else in a newer SDK. So I’ve been told to not do that.

I don’t know why those functions fail. There is no exception thrown, and on the Mac I can’t step into the VST3 code beyond the function names I’ve given.

What would be easiest to work with would be if we could derive a class from the wrapper class that allowed us to override the setState() function. Or else, if when that failed in the wrapper, it still passed the data to our setStateInformation() function, anyway, and let us decide what to do with it. As it is, the function simply ends up doing nothing and no data is loaded.

Here is the sequence of calls I see when running on the Mac in Cubase 10:

 -> JuceVST3Component::readFromMemoryStream(IBStream*)
  -> creates FUnknownPtr<ISizeableStream> s (state);
  -> s->getStreamSize(size) == 0, so returns false
 -> falls through to call JuceVST3Component::readFromUnknownStream(state)
  -> for (;;)
   -> status = state-&gt;read(buffer,bytesPerBlock,&amp;bytesRead)
   -> status == 0, bytesRead == 108
   -> allData.write(buffer, 108)
   -> status = state-&gt;read(buffer,bytesPerBlock,&amp;bytesRead)
   -> bytesRead = 0; break;
  -> dataSize == 108
  -> JuceVST3Component::loadStateData(data,108)
   -> loadVST2CompatibleState(data,108)
    -> header == 3
    -> returns false
  -> returns false
 -> falls through to return kResultFalse

This is the data seen in loadStateData. It sees 3 as the first long integer in that data. Could it be that the data has the incorrect endianness? I know our old pre-JUCE software had old code that handled the byte ordering to make Windows and Mac data compatible (including for handling old VST2 data and old FXpansion-wrapper AU data). I suspect that should be 0x3000, and was the version number ( for the previous data, rather than the VST chunk signature that that code appears to be looking for.

00 00 00 03 00 00 00 00 3F 26 CE 0C 3F 22 E8 BA 3F 00 00 00 3F 80 00 00 00 00 00 00 3F 80 00 00 00 00 00 00 3F 80 00 00 00 00 00 00 3F 80 00 00 3F 80 00 00 00 00 00 00 3F 80 00 00 00 00 00 00 3F 80 00 00 3C 7C 0F C1 3F 80 00 00 3E BA 2E 8C 00 00 00 00 3F 00 00 00 3F 80 00 00 3E 92 49 25 3D 4C CC CD 00 00 00 00

If, on failure to load the chunk data, it would still pass it to our setStateInformation() function (or some other fallback code we could implement in our processor class), then we could easily parse it by recognizing that 0x3000 at the start of the data as our old version number.

That function loadStateData() calls loadVST2CompatibleState(), because JUCE_VST3_CAN_REPLACE_VST2 is defined as 1 by default. I tried defining that as 0 in my AppConfig.h file, but then none of this state-loading code seems to get called at all. I was hoping defining that as 0 would allow the other function to be called: setStateInformation(), which is something that I have overridden, and can use to recognize our old data. But if it never gets called, I can’t do anything.

If I modify loadStateData() so that it only calls setStateInformation(), then that function does call my setStateInformation() function, which correctly detects that the data is not the new data, and I can then parse the chunk using my old chunk format. Is there some way to get this to happen, given that defining JUCE_VST3_CAN_REPLACE_VST2 as 0 seems to disable the chunk loading completely (i.e., none of my breakpoints are hit in the related code)?

Unfortunately, modifying loadStateData() so that it only calls setStateInformation() breaks reading new (JUCE-based) VST3 sessions! Can anyone help me determine why the old VST3 chunk data won’t load, and won’t get passed to my setStateInformation() function so I can deal with its differences myself? Or help me find where in the VST3 wrapper I can make modifications that will allow me to deal with the chunk differences myself? I’m running out of time, and can’t find any way to deal with the old VST3 data.

This code works, but I don’t know if it’s the correct thing to do:

			bool ok = false;
			ok = loadVST2CompatibleState ((const char*) data, size);
			if (!ok)
				setStateInformation (data, size);
				ok = true;
			return ok;

Thank you for digging into this and reporting back on the forum.

I’ve made some changes along very similar lines so that if we fail to load a VST2 compatible state then setStateInformation will still be called (thus giving developers a chance to migrate from non-JUCE saved data).

1 Like