Suite Events

A few events have been integrated into portions of the SALSA LipSync Suite where it makes sense to provide a decoupled configuration of the Suite with your custom code.

Event Subscription

The events have been implemented as C# events and require the developer to subscribe and un-subscribe as necessary. Typically, subscription occurs in a wake-up action such as: Awake(), Start(), or (perhaps more preferably) OnEnable().

private void OnEnable()
{
    EventController.AnimationStarting += OnAnimationStarting;
}

Likewise, it is important to unsubscribe to subscribed events to prevent system errors. This is typically performed in the OnDisable() component action.

private void OnDisable()
{
    EventController.AnimationStarting -= OnAnimationStarting;
}

NOTE: There are two template files in the Examples > Scripts folder (SALSA_Template_EventControllerSubscriber, SALSA_Template_SalsaEventSubscriber) that demonstrate how the events can be used. The demo boxhead scene also implements the SALSA events template, writing to the console when SALSA starts/stops SALSAing.
The SALSA event template component simply needs to be dropped on an object and linked to a SALSA component -- this simple template will then write to the console as the SALSA processing state changes. The EventController event template operates similarly -- add the component to any game object. To configure it, simply enter the EventIdentifier string that matches the controller configuration. It will subscribe to the EventController events and filter delegate processing according to the identifier string.

Available Events

There are currently two event sets to subscribe to, one in the Salsa class and the other in the EventController class. Details for each of the events are as follows:

SALSA Events

Several events have been implemented for SALSA and these emit the status of certain SALSA processing conditions:


SALSA Started SALSAing (Talking)

event Salsa.StartedSalsaing

This event will fire when Salsa no longer detects silence from audio analysis (internally calculated or externally provided). This event is immediate upon the first detection of a viseme being triggered. It will only be fired once while Salsa is Salsaing and will not be fired again until non-silences is detected again after Salsa has stopped Salsaing.

NOTE: The sensitivity of the SALSA processing events is controlled via the same mechanism as the Salsa.IsSALSAing property. To adjust the sensitivity of the silence measurement, increase the threshold to give SALSA more time to wait for non-silence and reduce the threshold to increase sensitivity. The lowest usable value for the Silence Threshold is 1, equating to one UpdateDelay cycle.
events salsa sensitivity

The difference between subscribing to the event and monitoring the property Salsa.IsSALSAing is the passive vs active perspective. Subscribing to the event allows the developer to let SALSA inform the developer vs actively polling the property to see if it changes. It is generally recommended to use the event. See the sample template included in the SALSA Suite Unity package (SALSA_Template_SalsaEventSubscriber) for an implementation example. Simply drop this script component on any object and link a SALSA instance to it.


SALSA Stopped SALSAing

event Salsa.StoppedSalsaing

The Salsa.StoppedSalsaing event fires when the appropriate threshold of silence has been reached. The sensitivity of StoppedSalsaing is adjusted using the same mechanism as the Salsa.IsSALSAing property. This event will only fire once and will not be fired again until silence is detected again after Salsa has started SALSAing. Refer to the example script included in the SALSA Suite Unity package as indicated in the Salsa.StartedSalsaing information above.


SALSA Found AudioSource

event Salsa.AudioSourceFound

This event is used by the Advanced Dynamics Silence Analyzer to determine if SALSA is in a ready state with respect to whether or not the AudioSource has been hooked up in the scenario where SALSA is configured to wait for the AudioSource. The developer may also use this event for their own purposes. The event will fire when both of the following conditions are met:
1) SALSA is configured to wait for an AudioSource.
2) SALSA has successfully found an AudioSource.

Example:

using CrazyMinnow.SALSA;
using Unity.Engine;

public MyClass : MonoBehavior
{
    private Salsa salsaInstance; // my SALSA reference

    private void OnEnable()
    {
        salsaInstance = this.gameObject.GetComponent<Salsa>();
        if (salsaInstance == null)
            Debug.LogError("No SALSA instance on this object.");

        Salsa.AudioSourceFound += OnAudioSourceFound;
    }

    private void OnDisable()
    {
        Salsa.AudioSourceFound -= OnAudioSourceFound;
    }

    private void OnAudioSourceFound(object sender, Salsa.SalsaNotificationArgs args)
    {
        if (args.salsaInstance == salsaInstance)
            Debug.Log("This SALSA instance was wired to wait for an AudioSource and just found one.");
    }
}

SALSA Viseme Triggered

event Salsa.VisemeTriggered

The Salsa.VisemeTriggered event fires after audio analysis occurs and trigger parsing has determined the correct, non-silence trigger value to use. Please see the SALSA API documentation for the TriggeredIndex property. The triggered index is available in the event arguments as SalsaNotificationArgs.eventTrigger. See the code snippet below for an example use.

using CrazyMinnow.SALSA;
using UnityEngine;

public class SALSA_Template_SalsaVisemeTriggerEventSubscriber : MonoBehaviour
{
    // Link the required SALSA instance for identification in the event callback.
    [SerializeField] private Salsa salsaInstance;

    private void OnEnable()
    {
        // subscribe to the event
        Salsa.VisemeTriggered += SalsaOnVisemeTriggered;
    }

    private void OnDisable()
    {
        // unsubscribe from the event
        Salsa.VisemeTriggered -= SalsaOnVisemeTriggered;
    }

    private void SalsaOnVisemeTriggered(object sender, Salsa.SalsaNotificationArgs e)
    {
        // compare the event instance with the linked SALSA instance.
        if (e.salsaInstance == salsaInstance)
        {
            // do something...
            Debug.Log("Viseme triggered: " + e.visemeTrigger);
        }
    }
}

EventController Events

The EventController is a new Suite animation controller type, which fires events at the start and finish of each animation timing cycle (ON/OFF). The events correspond to the ON animation 'starting' and 'finishing' and are followed by the OFF animation 'starting' and 'finishing'. There are no events for the HOLD cycle since the HOLD cycle begins immediately as the ON cycle finishes and ends immediately as the OFF cycle begins. The events are designated as follows (please also refer to the following diagram):

animation cycle diagram

Animation in the 'ON' Direction

event EventController.AnimationStarting

When an animation is registered to turn ON with the QueueProcessor, it officially begins the ON cycle and this is where the AnimationStarting event fires. Refer to #1 in the above diagram.

event EventController.AnimationON

Once an animation has reached its max extent and animation ON time, it is considered 'ON' and either is removed from the Queue (if it is a OneWay handler) or begins the wait for the HOLD timing. This is the point where the AnimationON event fires. This event may also be fired if an ON animation is interrupted by an OFF registration. Refer to #2 in the above diagram.

Animation in the 'OFF' Direction

event EventController.AnimationEnding

An animation begins its OFF phase in one of two situations. 1) The HOLD timing expires, or 2) A OneWay handled animation is registered to turn OFF with the QueueProcessor. When either of these two possibilities occur, the AnimationEnding event is fired. Refer to #3 in the above diagram.

event EventController.AnimationOFF

Once an animation completes its transition to the min extent, the AnimationOFF event fires. This event may also be fired if an OFF animation is interrupted with an ON registration. Refer to #4 in the above diagram.

For more information on animation timings, please see Notes On Animation Timings.