Subtitles and Multi Instruments

I’ve been looking into subtitles recently and how to add it to my game while using FMOD

in my FMOD project I have several events that have multi instruments with different versions of a clip it can play.

Is there a way to tell the multi instrument what to play or is there a way to know which clip the multi instrument is going to play so the subtitles can then be set up to write the correct sentence that plays

if this isn’t possible. is the only other solution to control the randomization our selves and use parameter sheets to control what option is picked and played on the FMOD side.

Thanks

You can’t really tell the multi instrument which clip to play directly. You can however see which clip is playing by adding a SOUND_PLAYED callback on your event. That will give you an FMOD.Sound object in the parameters argument, from which you can call Sound.getName to see what the name of the sound is and determine which subtitle line to display. You could also call Sound.getLength to determine how long to display the dialog line for.
We have a few examples of how to assign callbacks to FMOD Events in Unity, I think the Timeline Callbacks example would be most relevant to your use case. Just need to change the callback to handle FMOD.Studio.EVENT_CALLBACK_TYPE.SOUND_PLAYED, and cast the parameterPtr to an FMOD.Sound instead of an FMOD.Studio.TIMELINE_BEAT_PROPERTIES to get started.
Please let me know if you run into any issues getting that setup.

2 Likes

Thank you for the reply I have been able to get this set up and was able to get the sound name printed out using the call backs

I do have another question
Is there a way to export all of the names in multi instruments into a CSV I have Quiet a few Multi instruments with lots of sounds and wanted to know if there was an easy way to export this information out to a CSV for documentation

Thanks

You can achieve this using the FMOD Studio scripting API. I happen to have a script that iterates over event properties and writes them to a CSV file already, so here is an adaptation that writes multi instrument properties to a CSV.

Write CSV
function createFile() {
    var outputPath = studio.project.filePath;
    outputPath = outputPath.substr(0, outputPath.lastIndexOf("/") + 1) + "multisounds.csv";

    var textFile = studio.system.getFile(outputPath);
    if (!textFile.open(studio.system.openMode.WriteOnly)) {
        alert("Failed to open file {0}\n\nCheck the file is not read-only.".format(outputPath));
        console.error("Failed to open file {0}.".format(outputPath));
        return null;
    }

    return textFile;
}

function writeHeader(textFile) {
    textFile.writeText("eventName, startTime, duration, assetName");
    textFile.writeText(",\n");
}

function writeLine(textFile, eventName, startTime, duration, assetName) {
    textFile.writeText(eventName + ", ");
    textFile.writeText(startTime + ", ");
    textFile.writeText(duration + ", ");
    textFile.writeText(assetName);
    textFile.writeText(",\n");
}

function exportAllMultisoundsToCSV() {
    var textFile = createFile();

    writeHeader(textFile);

    // 1. Get all events
    var events = studio.project.model.Event.findInstances()
    events.forEach(function (event) {
        // 2. Get all multi instrument in an event
        event.selectables.forEach(function (selectable) {
            if (selectable.entity && selectable.entity == "MultiSound") {
                // 3. Get all sounds in multi instrument
                selectable.sounds.forEach(function (sound) {
                    // 4. Write to file event name and multi instrument properties
                    var eventName = event.name;
                    var startTime = selectable.start;
                    var duration = selectable.length;
                    var assetName = sound.audioFile.assetPath;

                    writeLine(textFile, eventName, startTime, duration, assetName);
                });
            }
        });
    });

    textFile.close();
}

If you want to add any other properties to the CSV you can use the .dump() function to see available properties of event, selectable etc. Running event.dump() inside the loop for example will give you:

.dump()
(ManagedObject:Event):
id: "{70e98c2f-ab13-4c5e-b0cc-4fe49b6e9b60}",
entity: "Event",
isValid: true,
relationships: (ManagedRelationshipMap:Event),
properties: (ManagedPropertyMap:Event),
isOfType: <function>,
isOfExactType: <function>,
note: undefined,
color: "Default",
name: "New Event",
isDefault: false,
outputFormat: 1,
uiMarkerTracksVisible: true,
uiMaxMarkerTracksVisible: 8,
folder: (ManagedObject:MasterEventFolder),
items: [],
selectables: [(ManagedObject:MultiSound)],
tags: [],
commandSounds: [],
profilerTrackers: [],
profilerGraphs: [],
uiLastParameterSelection: (ManagedObject:Timeline),
mixer: (ManagedObject:EventMixer),
masterTrack: (ManagedObject:MasterTrack),
mixerInput: (ManagedObject:MixerInput),
automatableProperties: (ManagedObject:EventAutomatableProperties),
markerTracks: [(ManagedObject:MarkerTrack)],
groupTracks: [],
returnTracks: [],
timeline: (ManagedObject:Timeline),
parameters: [],
userProperties: [],
references: [],
sandboxEmitters: [],
banks: [],
defaultEvent: null,
clonedEvents: [],
is3D: <function>,
isOneShot: <function>,
isPlaying: <function>,
isPaused: <function>,
isStopping: <function>,
isRecording: <function>,
play: <function>,
togglePause: <function>,
stopImmediate: <function>,
stopNonImmediate: <function>,
returnToStart: <function>,
keyOff: <function>,
toggleRecording: <function>,
getPath: <function>,
get3DAttributes: <function>,
set3DAttributes: <function>,
getCursorPosition: <function>,
setCursorPosition: <function>,
getPlayheadPosition: <function>,
getParameterPresets: <function>,
addGameParameter: <function>,
addGroupTrack: <function>,
addReturnTrack: <function>,
addMarkerTrack: <function>,
addTagToEvent: <function>,
getItem: <function>,
dump: <function>,
document: <function>,

And if you decided you wanted to add the guid for example you could change the writeHeader and writeLine functions to:

function writeHeader(textFile) {
    textFile.writeText("id, eventName, startTime, duration, assetName");
    textFile.writeText(",\n");
}

function writeLine(id, textFile, eventName, startTime, duration, assetName) {
    textFile.writeText(id + ", ");
    textFile.writeText(eventName + ", ");
    textFile.writeText(startTime + ", ");
    textFile.writeText(duration + ", ");
    textFile.writeText(assetName);
    textFile.writeText(",\n");
}

...
writeLine(event.id, textFile, eventName, startTime, duration, assetName);
...

Hopefully that’s enough to get you started.

1 Like

this is great thanks ill see what i can do with this.