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 theEventIdentifier
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.
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 ofStoppedSalsaing
is adjusted using the same mechanism as theSalsa.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 theSalsa.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 theAudioSource
. 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 anAudioSource
.
2) SALSA has successfully found anAudioSource
.
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 theTriggeredIndex
property. The triggered index is available in the event arguments asSalsaNotificationArgs.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 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.