It’s a simple memcopy. If the size matches, and if you are reasonably certain that the memory block given to you in setStateInformation actually contains the data (a basic integrity check is checking the size), then your memory block will contain a bunch of XML, followed by the binary data you appended at the end.
Since you know the exact size of the wavetable payload, you can calculate that it will start at:
data + sizeInBytes - totalSizeOfYourWavetableDataInBytes.
You can just memcopy this portion directly into synthParams.tgActiveWaveform.
Now mind that this data you appended is NOT part of the xml that JUCE created for you. “Remove” this wavetable portion from the memory block, simply by subtracting totalSizeOfYourWavetableDataInBytes from the total size of the data, yielding getXmlFromBinary(data, sizeInBytes - totalSizeOfYourWavetableDataInBytes).
All of this is terribly dangerous if you don’t make absolutely sure you’re not causing any access violations, but for a proof of concept it’s simple enough.
Unless you are the host, you cannot read it back like that.
I am repeating myself, but the host calls getStateInformation to get the current state from your plugin, and it will call setStateInformation to restore the state it read before.
If you call those yourself, you won’t see the data the host had stored.
To the host this blob is just a chunk of binary data. It doesn’t even have to be XML. That’s why getStateInformation supplies a MemoryBlock, where you can write binary data to, and the setStateInformation gives you the content of the memory block as const void* data.
I would strongly advice against conditionally returning anything different for all th ereasons that were given above already. It will be very fragile in terms of behaving on different hosts differently.
None of the Google searched suggestions to get an offset to the read pointer, I can seem to get to work;
// Up here I'm getting parameters in variables one at a time from XML
parameters.replaceState (ValueTree::fromXml (*xmlState));
int length = sizeof (data);
int arraySize = 8 * 2048 * sizeof (float); // Static size as a test for now
memcpy (synthParams.tgActiveArray, data + length - arraySize, arraySize);
This is not what you probably think it is - the size in bytes is provided to setStateInformation in the argument sizeInBytes. Without it, you can’t know how large the block of data given to you is.
“data” is just a pointer, so sizeof(data) will give you the size of this pointer, which generally is 8 bytes on a 64bit architecture.
Another mistake, also pointer related: With &data you’re taking the address of the pointer pointing to the data. The place where the variable “data” is stored, not the place it is pointing to.
You’re also still considering the entire data block to be xml.
You can’t really google ready made solutions for this, because this is your very own individual data layout, and there is no way around understanding precisely what this code actually does. So, you need to calculate and verify your calculations yourself, and probably also get a better understanding of memory layouts and c++ specifics like pointer arithmetic, dereferencing pointers, sizeof, etc.
Just because something is syntactically valid (it compiles) that doesn’t mean that it’s semantically correct, especially with low level stuff like this. as you can see, c++ happily allows you to try and access memory anywhere you like - and throw access violations at runtime. great power / great responsibility
Stepping through the code in a debugger and looking at the values and addresses helps figuring these things out.
If you get this to work it will be very fast, though.
You can’t perform arithmetic on a void pointer directly.
To make this whole thing a little safer and easier in setStateInformation, especially if you’re afraid of working on raw pointers (and everyone always should be!), consider wrapping the data you get in a juce::MemoryBlock. This will copy the entire data though, I’m not sure whether JUCE has a “view” type for non-owned data.
Anyways, then you can simply use copyTo (void *destData, int sourceOffset, size_t numBytes) const noexcept
…with sourceOffset being the start of the data you appended after the xml block (totalSize - constantWavetableDataSize as I wrote earlier).
Thank you VERY much!!! You have helped me a lot since I started my JUCE adventure, and you will be the first to get a free fully functional copy of my synth when it’s released, along with a few others on this awesome forum. The rest of the planet’s inhabitants will be offered a free “Sandbox” version, that are incapable of saving parameters and therefore patches.