using UnityEngine;
namespace Crosstales.RTVoice.Model
{
/// Wrapper for "Speak"-function calls.
[System.Serializable]
public class Wrapper
{
#region Variables
[Tooltip("Text for the speech."), TextArea(1, 5), SerializeField] private string text = string.Empty;
[Tooltip("AudioSource for the speech."), SerializeField] private AudioSource source;
[Tooltip("Voice for the speech."), SerializeField] private Voice voice;
[Tooltip("Speak immediately after the audio generation. Only works if 'Source' is not null."), SerializeField]
private bool speakImmediately = true;
[Tooltip("Speech rate of the speaker in percent (1 = 100%, default: 1, optional)."), Range(0.01f, 3f), SerializeField]
private float rate = 1f;
[Tooltip("Speech pitch of the speaker in percent (1 = 100%, default: 1, optional)."), Range(0f, 2f), SerializeField]
private float pitch = 1f;
[Tooltip("Volume of the speaker in percent (1 = 100%, default: 1, optional)."), Range(0f, 1f), SerializeField]
private float volume = 1f;
[Tooltip("Output file (without extension) for the generated audio."), SerializeField] private string outputFile;
[Tooltip("Force SSML on supported platforms."), SerializeField] private bool forceSSML = true;
[Tooltip("Is the current wrapper just a part of a speech (only used in iOS)."), SerializeField] private bool _isPartial;
private string uid;
private string cachedString;
private readonly System.DateTime created = System.DateTime.Now;
#endregion
#region Properties
/// Text for the speech.
public string Text
{
get
{
if (cachedString == null)
{
string result = cachedString = Util.Helper.CleanText(text, Speaker.Instance.AutoClearTags /*&& !(Speaker.isMaryMode /* || Util.Helper.isWindowsPlatform )*/);
if (result.Length > Speaker.Instance.MaxTextLength)
{
Debug.LogWarning("Text is too long! It will be shortened to " + Speaker.Instance.MaxTextLength + " characters: " + this);
cachedString = result.Substring(0, Speaker.Instance.MaxTextLength);
}
}
return cachedString;
}
set
{
cachedString = null;
text = value;
}
}
/// AudioSource for the speech.
public AudioSource Source
{
get => source;
set => source = value;
}
/// Voice for the speech.
public Voice Voice
{
get => voice;
set => voice = value;
}
/// Speak immediately after the audio generation. Only works if 'Source' is not null.
public bool SpeakImmediately
{
get => speakImmediately;
set => speakImmediately = value;
}
/// Rate of the speech (range: 0.01-3).
public float Rate
{
get => rate;
set => rate = Mathf.Clamp(value, 0.01f, 3f);
}
/// Pitch of the speech (range: 0-2).
public float Pitch
{
get => pitch;
set => pitch = Mathf.Clamp(value, 0f, 2f);
}
/// Volume of the speech (range: 0-1).
public float Volume
{
get => volume;
set => volume = Mathf.Clamp(value, 0f, 1f);
}
/// Output file (without extension) for the generated audio.
public string OutputFile
{
get => outputFile;
set => outputFile = value;
}
/// Force SSML on supported platforms.
public bool ForceSSML
{
get => forceSSML;
set => forceSSML = value;
}
/// Is the current wrapper just a part of a speech (only used in iOS).
public bool isPartial
{
get => _isPartial;
set => _isPartial = value;
}
/// UID of the speech.
public string Uid
{
get => uid;
private set => uid = value;
}
/// Returns the creation time of the Wrapper.
/// Creation time of the Wrapper.
public System.DateTime Created => created;
/// Returns the speech time in seconds (0: no audio file was generated).
/// Speech time in seconds.
public float SpeechTime
{
get
{
if (!Util.Helper.isEditorMode && source != null && source.clip != null)
{
return source.clip.length;
}
return 0f;
}
}
#endregion
#region Constructors
/// Default.
public Wrapper()
{
uid = System.Guid.NewGuid().ToString();
}
/// Instantiate the class.
/// Text for the speech.
/// Voice for the speech (default: null, optional).
/// Rate of the speech (values: 0-3, default: 1, optional).
/// Pitch of the speech (values: 0-2, default: 1, optional).
/// Volume of the speech (values: 0-1, default: 1, optional).
/// Force SSML on supported platforms (default: true, optional).
public Wrapper(string text, Voice voice = null, float rate = 1f, float pitch = 1f, float volume = 1f, bool forceSSML = true)
{
uid = System.Guid.NewGuid().ToString();
Text = text;
this.voice = voice;
Rate = rate;
Pitch = pitch;
Volume = volume;
this.forceSSML = forceSSML;
}
/// Instantiate the class.
/// Text for the speech.
/// Voice for the speech (default: null, optional).
/// Rate of the speech (values: 0-3, default: 1, optional).
/// Pitch of the speech (values: 0-2, default: 1, optional).
/// Volume of the speech (values: 0-1, default: 1, optional).
/// AudioSource for the speech (default: null, optional).
/// Speak immediately after the audio generation. Only works if 'Source' is not null (default: true, optional).
/// Output file (without extension) for the generated audio (default: empty, optional).
/// Force SSML on supported platforms (default: true, optional).
public Wrapper(string text, Voice voice = null, float rate = 1f, float pitch = 1f, float volume = 1f, AudioSource source = null, bool speakImmediately = true, string outputFile = "", bool forceSSML = true)
{
uid = System.Guid.NewGuid().ToString();
Text = text;
this.source = source;
this.voice = voice;
this.speakImmediately = speakImmediately;
Rate = rate;
Pitch = pitch;
Volume = volume;
this.outputFile = outputFile;
this.forceSSML = forceSSML;
}
/// Instantiate the class.
/// UID of the speech.
/// Text for the speech.
/// Voice for the speech (default: null, optional).
/// Rate of the speech (values: 0-3, default: 1, optional).
/// Pitch of the speech (values: 0-2, default: 1, optional).
/// Volume of the speech (values: 0-1, default: 1, optional).
/// AudioSource for the speech (default: null, optional).
/// Speak immediately after the audio generation. Only works if 'Source' is not null (default: true, optional).
/// Output file (without extension) for the generated audio (default: empty, optional).
/// Force SSML on supported platforms (default: true, optional).
public Wrapper(string uid, string text, Voice voice = null, float rate = 1f, float pitch = 1f, float volume = 1f, AudioSource source = null, bool speakImmediately = true, string outputFile = "", bool forceSSML = true) : this(text, voice, rate, pitch, volume, source, speakImmediately, outputFile, forceSSML)
{
this.uid = uid;
}
#endregion
#region Overridden methods
public override string ToString()
{
System.Text.StringBuilder result = new System.Text.StringBuilder();
result.Append(GetType().Name);
result.Append(Util.Constants.TEXT_TOSTRING_START);
result.Append("Uid='");
result.Append(uid);
result.Append(Util.Constants.TEXT_TOSTRING_DELIMITER);
result.Append("Text='");
result.Append(text);
result.Append(Util.Constants.TEXT_TOSTRING_DELIMITER);
result.Append("Source='");
result.Append(source);
result.Append(Util.Constants.TEXT_TOSTRING_DELIMITER);
result.Append("Voice='");
result.Append(voice);
result.Append(Util.Constants.TEXT_TOSTRING_DELIMITER);
result.Append("SpeakImmediately='");
result.Append(speakImmediately);
result.Append(Util.Constants.TEXT_TOSTRING_DELIMITER);
result.Append("Rate='");
result.Append(rate);
result.Append(Util.Constants.TEXT_TOSTRING_DELIMITER);
result.Append("Pitch='");
result.Append(pitch);
result.Append(Util.Constants.TEXT_TOSTRING_DELIMITER);
result.Append("Volume='");
result.Append(volume);
result.Append(Util.Constants.TEXT_TOSTRING_DELIMITER);
result.Append("OutputFile='");
result.Append(outputFile);
result.Append(Util.Constants.TEXT_TOSTRING_DELIMITER);
result.Append("ForceSSML='");
result.Append(forceSSML);
result.Append(Util.Constants.TEXT_TOSTRING_DELIMITER);
result.Append("isPartial='");
result.Append(isPartial);
result.Append(Util.Constants.TEXT_TOSTRING_DELIMITER);
result.Append("Created='");
result.Append(Created);
result.Append(Util.Constants.TEXT_TOSTRING_DELIMITER_END);
result.Append(Util.Constants.TEXT_TOSTRING_END);
return result.ToString();
}
public override bool Equals(object obj)
{
if (obj == null || GetType() != obj.GetType())
return false;
Wrapper o = (Wrapper)obj;
bool result = Text == o.Text &&
voice == o.voice &&
System.Math.Abs(Rate - o.Rate) < Util.Constants.FLOAT_TOLERANCE &&
System.Math.Abs(Pitch - o.Pitch) < Util.Constants.FLOAT_TOLERANCE;
return result;
}
public override int GetHashCode()
{
int hash = 0;
if (Text != null)
hash += Text.GetHashCode();
if (voice != null)
hash += voice.GetHashCode();
hash += (int)(Rate * 100) * 17;
hash += (int)(Pitch * 100) * 17;
return hash;
}
#endregion
}
}
// © 2015-2020 crosstales LLC (https://www.crosstales.com)