Is there a way to copy or change the type of instruments in the FMOD Studio scripting API?

Hi,

I’m trying to write a script that converts every SingleSound instance in an event into a ProgrammerSound that uses the SingleSound’s audioFIle as a placeholder. So far I can select every SingleSound in an event, but I’m a littl a little unsure how to convert, or if it’s possible.

Do I have to create a new ProgrammerInstrument and copy over all the properties of the SingleSound? Is there any kind of property cloning function? I’d to keep all the probability, automation, trigger conditions, etc. The only difference I want is for it to be a ProgrammerSound.

Thanks,
Rhys

Unfortunately, there’s no simple way to convert instrument types, or to copy all relevant properties and automations/modulations/etc. from one instrument to another via the scripting API. Your best bet is to create a script that enumerates all the settings from the existing instrument, the creates a new instrument and applies all the enumerated settings to the new instrument. Using the .dump() function should be helpful in identifying common properties and the best way to handle transferring automations/modulations.

That said, I do think this kind of functionality would be useful, so I’ve added to our internal feature/improvement tracker.

Thanks! That does make sense, and dump() and document() were very helpful. I did end up implementing something like this as a workaround.

That’s really cool, because it’s now almost possible to stream the audio an event over http, by batch converting all the sounds to programmer sounds and loading in sound assets that were fetched separately at runtime.

Right now I’m just using Ctrl+z to undo the changes after I build my project, but is there any reason I can’t just convert everything back to single sounds programmatically?

const properties = [
    'triggerProbability',
    'triggerConditionMode',
    'triggerConditionMode',
    'color',
    'isAsync',
    'isCutoff',
    'start',
    'length',
    'color',
    'isAsync',
    'isCutoff',
    'start',
    'length',
    'delayType',
    'minimumTimeDelay',
    'maximumTimeDelay',
    'quantizationInterval',
    'startOffset',
    'timelockedOffset',
    'voiceStealing',
    'maxVoices',
    'name',
    'volume',
    'pitch',
    'looping',
    'playCount'
];

const relationships = [
    'automators',
    'modulators',
    'snapshotProperties',
    'customBindings',
    'selector',
    'triggerConditions',
    'fadeInCurve',
    'fadeOutCurve',
    'relatedFadeCurves',
    'audioTrack',
    'parameter',
    'playPercentage',
    'owner',
];

studio.project.model.SingleSound.findInstances({
    searchContext: eventContext
}).map(function(sound) { 

    const audioFile = sound.relationships.audioFile.destinations[0];

    const name = audioFile.assetPath.split('/').slice(1).join('/');
    const programmerSound = studio.project.create('ProgrammerSound');
    programmerSound.relationships.placeholder.add(audioFile);

    properties.forEach(function(property) {
        programmerSound[property] = sound[property];
    });

    programmerSound.properties.name.setValue(name);

    relationships.forEach(function(relationship) {
        sound.relationships[relationship].destinations.forEach(function(destination) {
            programmerSound.relationships[relationship].add(destination);
        });
    });       

    if (sound.relationships.audioTrack.destinations.length > 0) {
        sound.relationships.audioTrack.destinations[0].relationships.modules.remove(sound);
    } else {
        sound.relationships.owner.destinations[0].relationships.sounds.remove(sound);
    }

    studio.project.deleteObject(sound);
});

Happy to hear!

There’s no reason you couldn’t do that at all - for example, you could create a script that swaps all single sounds to programmer sounds, builds banks, and then swaps the sounds back to the way they were.