#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)