#if ((UNITY_WSA || UNITY_XBOXONE) && !UNITY_EDITOR) && ENABLE_WINMD_SUPPORT //|| CT_DEVELOP
using UnityEngine;
using System;
using System.Threading.Tasks;
using Windows.Media.SpeechSynthesis;
using Windows.Storage;
using Windows.Storage.Streams;
using System.Runtime.InteropServices.WindowsRuntime;
namespace Crosstales.RTVoice
{
/// WSA (UWP) TTS bridge.
public sealed class RTVoiceUWPBridge : IDisposable
{
#region Variables
private static SpeechSynthesizer tts = new SpeechSynthesizer();
#if UNITY_WSA
private static StorageFolder targetFolder = ApplicationData.Current.LocalFolder;
//private static StorageFolder logFolder = ApplicationData.Current.LocalFolder;
//private static StorageFile logFile;
//private System.Collections.Generic.List mediaElements = new System.Collections.Generic.List();
#endif
#endregion
#region Constructor
public RTVoiceUWPBridge()
{
tts = new SpeechSynthesizer();
}
#endregion
#region Properties
///
/// Indicates if the TTS-Engine is currently busy.
///
/// True if the TTS-Engine is currently busy.
public bool isBusy { get; set; }
#if UNITY_WSA
///
/// Returns the target folder of the last Speak call.
/// If there hasn't been a Speak call so far, returns ApplicationData.Current.LocalFolder.
///
/// The target folder of the last Speak call.
public static string TargetFolder
{
get
{
/*
if (targetFolder == null)
{
targetFolder = ApplicationData.Current.LocalFolder;
}
*/
return targetFolder.Path;
}
}
#endif
/// Returns the audio data of the last Speak call.
/// The audio data of the last Speak call.
public byte[] AudioData { get; private set; }
///
/// Returns the available voices.
///
/// Available voices as string-array. Format: DisplayName;Language
public string[] Voices
{
get
{
System.Collections.Generic.List result = new System.Collections.Generic.List();
foreach (VoiceInformation Voice in SpeechSynthesizer.AllVoices)
{
result.Add(Voice.DisplayName + ";" + Voice.Language);
}
return result.ToArray();
}
}
#endregion
#region Public Methods
#if UNITY_WSA
///
/// Use the TTS engine to write the voice clip into a pre-defined Folder.
///
/// Spoken text
/// Target folder
/// File name
/// Desired voice
public async void SynthesizeToFile(string text, string path, string fileName, string voice)
{
isBusy = true;
if (Util.Config.DEBUG)
Debug.Log($"SynthesizeToFile: {text} - {path}");
try
{
targetFolder = await StorageFolder.GetFolderFromPathAsync(path);
SpeechSynthesisStream stream = await synthesizeText(text, voice);
StorageFile outputFile = await targetFolder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);
using (var reader = new DataReader(stream))
{
await reader.LoadAsync((uint)stream.Size);
IBuffer buffer = reader.ReadBuffer((uint)stream.Size);
await FileIO.WriteBufferAsync(outputFile, buffer);
}
}
catch (Exception ex)
{
Debug.LogError("Could not synthesize to file: " + ex);
}
isBusy = false;
}
#endif
///
/// Use the TTS engine to write the voice clip into a pre-defined Folder.
///
/// Spoken text
/// Target folder
/// File name
/// Desired voice
public async void SynthesizeToMemory(string text, string voice)
{
isBusy = true;
if (Util.Config.DEBUG)
Debug.Log($"SynthesizeToMemory: {text}");
try
{
SpeechSynthesisStream stream = await synthesizeText(text, voice);
using (var reader = new DataReader(stream))
{
await reader.LoadAsync((uint)stream.Size);
IBuffer buffer = reader.ReadBuffer((uint)stream.Size);
//AudioData = System.Runtime.InteropServices.WindowsRuntime.WindowsRuntimeBufferExtensions.ToArray(buffer);
AudioData = buffer.ToArray();
}
}
catch (Exception ex)
{
Debug.LogError("Could not synthesize to memory: " + ex);
}
isBusy = false;
}
public void Dispose()
{
tts.Dispose();
}
#endregion
#region Private Methods
private async Task synthesizeText(string inputText, string inputVoice)
{
if (!tts.Voice.DisplayName.Equals(inputVoice))
{
tts.Voice = SpeechSynthesizer.AllVoices[0];
foreach (VoiceInformation Voice in SpeechSynthesizer.AllVoices)
{
if (Voice.DisplayName.Equals(inputVoice))
{
tts.Voice = Voice;
break;
}
}
}
if (inputText.Contains(""))
return await tts.SynthesizeSsmlToStreamAsync(inputText);
return await tts.SynthesizeTextToStreamAsync(inputText);
}
#endregion
}
}
#endif
// © 2016-2024 crosstales LLC (https://www.crosstales.com)