How to sync ValueTree up with objects

So I’m working on Sampler plugin. I’m trying to figure out how data should flow within it. For my preset data model, I’m using a ValueTree with the following structure:

<groups>
	<group>
		<sample rootNote=48 path="..." />
	</group>
	<group>
		<sample rootNote=48 path="..." />
	</group>
<groups>

When I create a new group and a new sample in the UI, a new “group” and “sample” will get added to the ValueTree. So far so good. Internally, each of the samples will need to have a corresponding SamplerSound object. My question is this, how should I handle correlating or synchronizing the ValueTree with the SamplerSound objects. For example, say a sample gets removed from one of the groups. If I’m listening to the entire/master ValueTree, valueTreeChildRemoved() will get called with a “group” ValueTree as the parentTree and a “sample” ValueTree as the childWhichHasBeenRemoved.

What needs to happen is I need to: a) find the correct SamplerSound object that the “sample” value tree corresponds to; and b) call synth.removeSound() on it. (Actually the problem is more complicated than that because Synthesiser can only remove a sound based on index).

I guess my question is this: do I need to make a mapping table that correlates ValueTrees with indexes? Or is there some better, more JUCE-y way of doing things?

I would use a Uuid, since the all of the indices will have to be updated in the valuetree when you delete or insert an item.

1 Like

Did you work that out @dhilowitz?
I’m working on a similar problem, but I was wondering if simply calling removeSound (assuming you find the correct index) is real-time safe? say if the sound is currently being played, how should one make sure that it can be removed?

No it’s not real time safe and you have to make sure that removeSound is not being called during playback.

My solution:
Use an Atomic<bool> that will be set to true when the ValueTree changes.
Your synth should check that flag on each processBlock run, before or after the synth is rendering audio.
if the flag is set to true, call removeSound and set false.

processBlock(){
...
if (removeSoundFlag.CompareAndSetBool(false, true)
    synth.removeSound();

synth.renderNextBlock();
...
}

Hi @duvrin,

Thanks for the tip! However using this strategy you’ll be indeed calling removeSound from the audio thread right? Aren’t we supposed to only do that from the message thread?

You’re not supposed to do potentially expansive actions from the audio thread. I don’t know if removing one sound falls into this category but if you want to play it safe you can do it another way:
Make 2 Atomic bools: one to indicate that the synth is currently rendering and one to indicate that removeSound is occurring.
Lock and unlock the bools accordingly, and have them both check each other before locking them selves, so they can’t both be true at the same time. So audio will not render during removing sound, and removing sound will not happen during playback.
However, you will need to move removeSound to some timer thread and repeatdly check for it since on the message thread it will be a one-time thing.

Thanks for the suggestion, I’ll look into something like that.