ISAP/Assets/Plugins/crosstales/RTVoice/Scripts/VoiceProviderExample.cs

436 lines
13 KiB
C#

using UnityEngine;
using System.Collections;
namespace Crosstales.RTVoice
{
/// <summary>
/// Example for a custom voice provider (TTS-system) with all callbacks (only for demonstration - it doesn't do anything).
/// NOTE: please make sure you understand the Wrapper and its variables
/// </summary>
[HelpURL("https://www.crosstales.com/media/data/assets/rtvoice/api/class_crosstales_1_1_r_t_voice_1_1_voice_provider_example.html")]
public class VoiceProviderExample : Provider.BaseCustomVoiceProvider
{
#region Properties
public override string AudioFileExtension
{
get
{
// SKELETON CODE - replace with your own code!
// DEFINE: audio extension of the generated audio files from the provider (e.g. '.wav')
return ".wav";
}
}
public override AudioType AudioFileType
{
get
{
// SKELETON CODE - replace with your own code!
// DEFINE: audio type of the generated audio files from the provider
return AudioType.WAV;
}
}
public override string DefaultVoiceName
{
get
{
// SKELETON CODE - replace with your own code!
// DEFINE: default voice name
return "Marisa";
}
}
public override bool isWorkingInEditor
{
get
{
// SKELETON CODE - replace with your own code!
// DEFINE: Indicates if this provider is working directly inside the Unity Editor (without 'Play'-mode)
return true;
}
}
public override bool isWorkingInPlaymode
{
get
{
// SKELETON CODE - replace with your own code!
// DEFINE: Indicates if this provider is working with 'Play'-mode inside the Unity Editor
return true;
}
}
public override bool isPlatformSupported
{
get
{
// SKELETON CODE - replace with your own code!
// DEFINE: checks if the current platform is supported
return true;
}
}
public override int MaxTextLength
{
get
{
// SKELETON CODE - replace with your own code!
// DEFINE: Maximal length of the speech text (in characters) that could be processed by the provider
return 32000;
}
}
public override bool isSpeakNativeSupported
{
get
{
// SKELETON CODE - replace with your own code!
// DEFINE: Indicates if this provider is supporting SpeakNative
return false;
}
}
public override bool isSpeakSupported
{
get
{
// SKELETON CODE - replace with your own code!
// DEFINE: Indicates if this provider is supporting Speak
return true;
}
}
public override bool isSSMLSupported
{
get
{
// SKELETON CODE - replace with your own code!
// DEFINE: Indicates if this provider is supporting SSML
return true;
}
}
public override bool isOnlineService
{
get
{
// SKELETON CODE - replace with your own code!
// DEFINE: Indicates if this provider is an online service like MaryTTS or AWS Polly
return false;
}
}
public override bool hasCoRoutines
{
get
{
// SKELETON CODE - replace with your own code!
// DEFINE: Indicates if this provider uses co-routines
return true;
}
}
public override bool isIL2CPPSupported
{
get
{
// SKELETON CODE - replace with your own code!
// DEFINE: Indicates if this provider is supporting IL2CPP
return true;
}
}
public override bool hasVoicesInEditor
{
get
{
// SKELETON CODE - replace with your own code!
// DEFINE: Indicates if this provider returns voices in the Editor mode
return true;
}
}
#endregion
#region Implemented methods
public override void Load(bool forceReload = false)
{
Debug.Log("Load", this);
if (cachedVoices?.Count == 0 || forceReload)
{
Debug.Log("Reload all voices", this);
// SKELETON CODE - replace with your own code!
cachedVoices = new System.Collections.Generic.List<Model.Voice>
{
new Model.Voice("Marisa", "RTV custom provider test -> female", Model.Enum.Gender.FEMALE, "adult", "en-US"),
new Model.Voice("Stefan", "RTV custom provider test -> male", Model.Enum.Gender.MALE, "adult", "en-US")
};
}
onVoicesReady();
}
public override IEnumerator Generate(Model.Wrapper wrapper)
{
Debug.Log("Generate: " + wrapper, this);
// SKELETON CODE - replace with your own code!
if (wrapper == null)
{
Debug.LogWarning("'wrapper' is null!", this);
}
else
{
if (string.IsNullOrEmpty(wrapper.Text))
{
Debug.LogWarning("'wrapper.Text' is null or empty!", this);
}
else
{
yield return null; //return to the main process (uid)
silence = false;
// GENERATE: audio file based on the Wrapper configuration (pitch, rate, volume, output file etc.)
//... <code>
onSpeakAudioGenerationStart(wrapper); //NECESSARY
// WAIT: wait until speech is generated
//... <code>
//... load file (with WWW) and add the clip to the AudioSource (see VoiceProviderWindows)
//... <code>
// SIMULATE GENERATE (remove this)
foreach (char character in wrapper.Text)
{
Debug.Log(character, this);
yield return null;
}
onSpeakAudioGenerationComplete(wrapper); //NECESSARY
//OPTIONAL: broadcast possible errors
//onErrorInfo(wrapper, "errorMessage");
}
}
}
public override IEnumerator Speak(Model.Wrapper wrapper)
{
Debug.Log("Speak: " + wrapper, this);
// SKELETON CODE - replace with your own code!
if (wrapper == null)
{
Debug.LogWarning("'wrapper' is null!", this);
}
else
{
if (string.IsNullOrEmpty(wrapper.Text))
{
Debug.LogWarning("'wrapper.Text' is null or empty!", this);
}
else
{
yield return null; //return to the main process (uid)
silence = false;
//GENERATE: audio file based on the Wrapper configuration (pitch, rate, volume, output file etc.)
//... <code>
onSpeakAudioGenerationStart(wrapper); //NECESSARY
// WAIT: wait until speech is generated
//... <code>
//... load file (with WWW) and add the clip to the AudioSource (see VoiceProviderWindows)
//... <code>
onSpeakAudioGenerationComplete(wrapper); //NECESSARY
//OPTIONAL: play audio file
//... <code>
if (wrapper.SpeakImmediately)
{
onSpeakStart(wrapper); //NECESSARY
// WAIT: wait until speech is finished
//... <code>
//SIMULATE SPEECH (remove this)
foreach (char character in wrapper.Text)
{
Debug.Log(character, this);
yield return null;
}
onSpeakComplete(wrapper); //NECESSARY
}
//OPTIONAL: broadcast possible errors
//onErrorInfo(wrapper, "errorMessage");
}
}
}
public override IEnumerator SpeakNative(Model.Wrapper wrapper)
{
Debug.Log("SpeakNative: " + wrapper, this);
// SKELETON CODE - replace with your own code!
if (wrapper == null)
{
Debug.LogWarning("'wrapper' is null!", this);
}
else
{
if (string.IsNullOrEmpty(wrapper.Text))
{
Debug.LogWarning("'wrapper.Text' is null or empty!", this);
}
else
{
yield return null; //return to the main process (uid)
silence = false;
// SPEAK: speech based on the Wrapper configuration (pitch, rate, volume, output file etc.)
//... <code>
onSpeakStart(wrapper); //NECESSARY
// WAIT: wait until speech is finished
//... <code>
//SIMULATE SPEECH (remove this)
foreach (char character in wrapper.Text)
{
//OPTIONAL: enable if you have access to the words, phonemes and visemes
//onSpeakCurrentWord(wrapper, speechTextArray, wordIndex - 1);
onSpeakCurrentPhoneme(wrapper, character.ToString());
onSpeakCurrentViseme(wrapper, character.ToString());
Debug.Log(character, this);
yield return null;
}
onSpeakComplete(wrapper); //NECESSARY
//OPTIONAL: broadcast possible errors
//onErrorInfo(wrapper, "errorMessage");
}
}
}
#endregion
#region Editor-only methods
#if UNITY_EDITOR
public override void GenerateInEditor(Model.Wrapper wrapper)
{
Debug.Log("Generate: " + wrapper, this);
// SKELETON CODE - replace with your own code!
if (wrapper == null)
{
Debug.LogWarning("'wrapper' is null!", this);
}
else
{
if (string.IsNullOrEmpty(wrapper.Text))
{
Debug.LogWarning("'wrapper.Text' is null or empty!", this);
}
else
{
silence = false;
// GENERATE: audio file based on the Wrapper configuration (pitch, rate, volume, output file etc.)
//... <code>
onSpeakAudioGenerationStart(wrapper); //NECESSARY
// WAIT: wait until speech is generated
//... <code>
//... load file (with WWW) and add the clip to the AudioSource (see VoiceProviderWindows)
//... <code>
// SIMULATE GENERATE (remove this)
foreach (char character in wrapper.Text)
{
Debug.Log(character, this);
System.Threading.Thread.Sleep(100);
}
onSpeakAudioGenerationComplete(wrapper); //NECESSARY
//OPTIONAL: broadcast possible errors
//onErrorInfo(wrapper, "errorMessage");
}
}
}
public override void SpeakNativeInEditor(Model.Wrapper wrapper)
{
Debug.Log("SpeakNative: " + wrapper, this);
// SKELETON CODE - replace with your own code!
if (wrapper == null)
{
Debug.LogWarning("'wrapper' is null!", this);
}
else
{
if (string.IsNullOrEmpty(wrapper.Text))
{
Debug.LogWarning("'wrapper.Text' is null or empty!", this);
}
else
{
silence = false;
// SPEAK: speech based on the Wrapper configuration (pitch, rate, volume, output file etc.)
//... <code>
onSpeakStart(wrapper); //NECESSARY
// WAIT: wait until speech is finished
//... <code>
//SIMULATE SPEECH (remove this)
foreach (char character in wrapper.Text)
{
//OPTIONAL: enable if you have access to the words, phonemes and visemes
//onSpeakCurrentWord(wrapper, speechTextArray, wordIndex - 1);
onSpeakCurrentPhoneme(wrapper, character.ToString());
onSpeakCurrentViseme(wrapper, character.ToString());
Debug.Log(character, this);
System.Threading.Thread.Sleep(100);
}
onSpeakComplete(wrapper); //NECESSARY
//OPTIONAL: broadcast possible errors
//onErrorInfo(wrapper, "errorMessage");
}
}
}
#endif
#endregion
}
}
// © 2018-2020 crosstales LLC (https://www.crosstales.com)