/// <summary> /// Logs for TTSService /// </summary> protected virtual void LogClip(string logMessage, TTSClipData clipData, TTSLogType logType = TTSLogType.Info) { StringBuilder builder = new StringBuilder(); builder.AppendLine(logMessage); if (clipData != null) { builder.AppendLine($"Voice: {(clipData.voiceSettings == null ? "Default" : clipData.voiceSettings.settingsID)}"); builder.AppendLine($"Text: {clipData.textToSpeak}"); builder.AppendLine($"ID: {clipData.clipID}"); TTSDiskCacheLocation cacheLocation = TTSDiskCacheLocation.Stream; if (DiskCacheHandler != null) { TTSDiskCacheSettings settings = clipData.diskCacheSettings; if (settings == null) { settings = DiskCacheHandler.DiskCacheDefaultSettings; } if (settings != null) { cacheLocation = settings.DiskCacheLocation; } } builder.AppendLine($"Cache: {cacheLocation}"); } Log(builder.ToString(), logType); }
// Refresh phrase data public static void RefreshPhraseData(TTSService service, TTSDiskCacheSettings cacheSettings, TTSVoiceSettings voiceSettings, TTSPreloadPhraseData phraseData) { // Get voice settings if (service == null || voiceSettings == null || string.IsNullOrEmpty(phraseData.textToSpeak)) { phraseData.clipID = string.Empty; phraseData.downloaded = false; phraseData.downloadProgress = 0f; return; } if (cacheSettings == null) { cacheSettings = new TTSDiskCacheSettings() { DiskCacheLocation = TTSDiskCacheLocation.Preload }; } // Get phrase data phraseData.clipID = service.GetClipID(phraseData.textToSpeak, voiceSettings); // Check if file exists string path = service.GetDiskCachePath(phraseData.textToSpeak, phraseData.clipID, voiceSettings, cacheSettings); phraseData.downloaded = File.Exists(path); phraseData.downloadProgress = phraseData.downloaded ? 1f : 0f; }
// Refresh private static IEnumerator RefreshPhraseData(TTSService service, TTSDiskCacheSettings cacheSettings, TTSVoiceSettings voiceSettings, TTSPreloadPhraseData phraseData, Action <float> onProgress, Action <string> onComplete) { RefreshPhraseData(service, cacheSettings, voiceSettings, phraseData); yield return(null); onComplete?.Invoke(string.Empty); }
// Preload voice text private static IEnumerator PreloadPhraseData(TTSService service, TTSDiskCacheSettings cacheSettings, TTSVoiceSettings voiceSettings, TTSPreloadPhraseData phraseData, Action <float> onProgress, Action <string> onComplete) { // Begin running bool running = true; // Download string log = string.Empty; service.DownloadToDiskCache(phraseData.textToSpeak, string.Empty, voiceSettings, cacheSettings, delegate(TTSClipData data, string path, string error) { // Set phrase data phraseData.clipID = data.clipID; phraseData.downloaded = string.IsNullOrEmpty(error); // Failed if (!phraseData.downloaded) { log += $"\n-{voiceSettings.settingsID} Preload Failed: {phraseData.textToSpeak}"; } // Next running = false; }); // Wait for running to complete while (running) { //Debug.Log($"Preload Wait: {voiceSettings.settingsID} - {phraseData.textToSpeak}"); yield return(null); } // Invoke onComplete?.Invoke(log); }
/// <summary> /// Perform a download for a TTS audio clip /// </summary> /// <param name="textToSpeak">Text to be spoken in clip</param> /// <param name="clipID">Unique clip id</param> /// <param name="voiceSettings">Custom voice settings</param> /// <param name="diskCacheSettings">Custom disk cache settings</param> /// <param name="onDownloadComplete">Callback when file has finished downloading</param> /// <returns>Generated TTS clip data</returns> public TTSClipData DownloadToDiskCache(string textToSpeak, string clipID, TTSVoiceSettings voiceSettings, TTSDiskCacheSettings diskCacheSettings, Action <TTSClipData, string, string> onDownloadComplete = null) { TTSClipData clipData = CreateClipData(textToSpeak, clipID, voiceSettings, diskCacheSettings); DownloadToDiskCache(clipData, onDownloadComplete); return(clipData); }
// Speak from this audio source public virtual void Speak(string textToSpeak, TTSDiskCacheSettings diskCacheSettings) { // Ensure voice settings exist TTSVoiceSettings voiceSettings = VoiceSettings; if (voiceSettings == null) { Debug.LogError($"TTS Speaker - No voice found with preset id: {presetVoiceID}"); return; } // Log if empty text if (string.IsNullOrEmpty(textToSpeak)) { Debug.LogError("TTS Speaker - No text to speak provided"); return; } // Get clip id string newClipID = TTSService.Instance.GetClipID(textToSpeak, voiceSettings); // Currently loading if (_loadingClip != null) { // Already loading text if (IsClipSame(newClipID, _loadingClip)) { // Refresh clip use time TTSService.Instance.GetRuntimeCachedClip(_loadingClip.clipID); return; } // Abort previous load OnLoadAbort(); } // Currently playing if (IsClipSame(newClipID, _lastClip)) { // Refresh clip use time TTSService.Instance.GetRuntimeCachedClip(_lastClip.clipID); // Play clip OnPlaybackBegin(_lastClip); return; } // Load new clip OnLoadBegin(textToSpeak, newClipID, voiceSettings, diskCacheSettings); }
/// <summary> /// Creates new clip data or returns existing cached clip /// </summary> /// <param name="textToSpeak">Text to speak</param> /// <param name="clipID">Unique clip id</param> /// <param name="voiceSettings">Voice settings</param> /// <param name="diskCacheSettings">Disk Cache settings</param> /// <returns>Clip data structure</returns> protected virtual TTSClipData CreateClipData(string textToSpeak, string clipID, TTSVoiceSettings voiceSettings, TTSDiskCacheSettings diskCacheSettings) { // Use default voice settings if none are set if (voiceSettings == null && VoiceProvider != null) { voiceSettings = VoiceProvider.VoiceDefaultSettings; } // Use default disk cache settings if none are set if (diskCacheSettings == null && DiskCacheHandler != null) { diskCacheSettings = DiskCacheHandler.DiskCacheDefaultSettings; } // Determine clip id if empty if (string.IsNullOrEmpty(clipID)) { clipID = GetClipID(textToSpeak, voiceSettings); } // Get clip from runtime cache if applicable TTSClipData clipData = GetRuntimeCachedClip(clipID); if (clipData != null) { return(clipData); } // Generate new clip data clipData = new TTSClipData() { clipID = clipID, textToSpeak = textToSpeak, voiceSettings = voiceSettings, diskCacheSettings = diskCacheSettings, loadState = TTSClipLoadState.Unloaded, loadProgress = 0f, queryParameters = VoiceProvider?.EncodeVoiceSettings(voiceSettings) }; // Return generated clip return(clipData); }
// Refresh phrase data public static void RefreshVoiceData(TTSService service, TTSPreloadVoiceData voiceData, TTSDiskCacheSettings cacheSettings, ref string log) { // Get voice settings if (service == null) { log += "\n-No TTS service found"; return; } // No voice data if (voiceData == null) { log += "\n-No voice data provided"; return; } // Get voice TTSVoiceSettings voiceSettings = service.GetPresetVoiceSettings(voiceData.presetVoiceID); if (voiceSettings == null) { log += "\n-Missing Voice Setting: " + voiceData.presetVoiceID; return; } // Generate if (cacheSettings == null) { cacheSettings = new TTSDiskCacheSettings() { DiskCacheLocation = TTSDiskCacheLocation.Preload }; } // Iterate phrases for (int p = 0; p < voiceData.phrases.Length; p++) { RefreshPhraseData(service, cacheSettings, voiceSettings, voiceData.phrases[p]); } }
// Begin a load protected virtual void OnLoadBegin(string textToSpeak, string clipID, TTSVoiceSettings voiceSettings, TTSDiskCacheSettings diskCacheSettings) { // Load begin Events?.OnClipLoadBegin?.Invoke(this, textToSpeak); // Perform load request _loadingClip = TTSService.Instance.Load(textToSpeak, clipID, voiceSettings, diskCacheSettings, OnLoadComplete); }
public TTSClipData DownloadToDiskCache(string textToSpeak, TTSVoiceSettings voiceSettings, TTSDiskCacheSettings diskCacheSettings, Action <TTSClipData, string, string> onDownloadComplete = null) => DownloadToDiskCache(textToSpeak, null, voiceSettings, diskCacheSettings, onDownloadComplete);
public TTSClipData DownloadToDiskCache(string textToSpeak, string presetVoiceId, TTSDiskCacheSettings diskCacheSettings, Action <TTSClipData, string, string> onDownloadComplete = null) => DownloadToDiskCache(textToSpeak, null, GetPresetVoiceSettings(presetVoiceId), diskCacheSettings, onDownloadComplete);
/// <summary> /// Get disk cache /// </summary> /// <param name="textToSpeak">Text to be spoken in clip</param> /// <param name="clipID">Unique clip id</param> /// <param name="voiceSettings">Custom voice settings</param> /// <param name="diskCacheSettings">Custom disk cache settings</param> /// <returns></returns> public string GetDiskCachePath(string textToSpeak, string clipID, TTSVoiceSettings voiceSettings, TTSDiskCacheSettings diskCacheSettings) => DiskCacheHandler?.GetDiskCachePath(CreateClipData(textToSpeak, clipID, voiceSettings, diskCacheSettings));
/// <summary> /// Perform a request for a TTS audio clip /// </summary> /// <param name="textToSpeak">Text to be spoken in clip</param> /// <param name="clipID">Unique clip id</param> /// <param name="voiceSettings">Custom voice settings</param> /// <param name="diskCacheSettings">Custom cache settings</param> /// <returns>Generated TTS clip data</returns> public virtual TTSClipData Load(string textToSpeak, string clipID, TTSVoiceSettings voiceSettings, TTSDiskCacheSettings diskCacheSettings, Action <TTSClipData, string> onStreamReady) { // Add delegates if needed AddDelegates(); // Get clip data TTSClipData clipData = CreateClipData(textToSpeak, clipID, voiceSettings, diskCacheSettings); if (clipData == null) { Log("No clip provided", TTSLogType.Error); onStreamReady?.Invoke(clipData, "No clip provided"); return(null); } // From Runtime Cache if (clipData.loadState != TTSClipLoadState.Unloaded) { // Add callback if (onStreamReady != null) { // Call once ready if (clipData.loadState == TTSClipLoadState.Preparing) { clipData.onPlaybackReady += (e) => onStreamReady(clipData, e); } // Call after return else { CoroutineUtility.StartCoroutine(CallAfterAMoment(() => onStreamReady(clipData, clipData.loadState == TTSClipLoadState.Loaded ? string.Empty : "Error"))); } } // Return clip return(clipData); } // Add to runtime cache if possible if (RuntimeCacheHandler != null) { RuntimeCacheHandler.AddClip(clipData); } // Load begin else { OnLoadBegin(clipData); } // Add on ready delegate clipData.onPlaybackReady += (error) => onStreamReady(clipData, error); // Wait a moment and load CoroutineUtility.StartCoroutine(CallAfterAMoment(() => { // Check for invalid text string invalidError = WebHandler.IsTextValid(clipData.textToSpeak); if (!string.IsNullOrEmpty(invalidError)) { OnWebStreamError(clipData, invalidError); return; } // If should cache to disk, attempt to do so if (ShouldCacheToDisk(clipData)) { // Download was canceled before starting if (clipData.loadState != TTSClipLoadState.Preparing) { string downloadPath = DiskCacheHandler.GetDiskCachePath(clipData); OnWebDownloadBegin(clipData, downloadPath); OnWebDownloadCancel(clipData, downloadPath); OnWebStreamBegin(clipData); OnWebStreamCancel(clipData); return; } // Download DownloadToDiskCache(clipData, (clipData2, downloadPath, error) => { // Download was canceled before starting if (string.Equals(error, CANCEL_WARNING)) { OnWebStreamBegin(clipData); OnWebStreamCancel(clipData); return; } // Success if (string.IsNullOrEmpty(error)) { DiskCacheHandler?.StreamFromDiskCache(clipData); } // Failed else { WebHandler?.RequestStreamFromWeb(clipData); } }); } // Simply stream from the web else { // Stream was canceled before starting if (clipData.loadState != TTSClipLoadState.Preparing) { OnWebStreamBegin(clipData); OnWebStreamCancel(clipData); return; } // Stream WebHandler?.RequestStreamFromWeb(clipData); } })); // Return data return(clipData); }
public TTSClipData Load(string textToSpeak, TTSVoiceSettings voiceSettings, TTSDiskCacheSettings diskCacheSettings, Action <TTSClipData, string> onStreamReady = null) => Load(textToSpeak, null, voiceSettings, diskCacheSettings, onStreamReady);
public TTSClipData Load(string textToSpeak, string presetVoiceId, TTSDiskCacheSettings diskCacheSettings, Action <TTSClipData, string> onStreamReady = null) => Load(textToSpeak, null, GetPresetVoiceSettings(presetVoiceId), diskCacheSettings, onStreamReady);
// Perform iterate private static IEnumerator PerformIteratePhrases(TTSService service, TTSPreloadData preloadData, TTSPreloadIterateDelegate onIterate, Action <float> onProgress, Action <string> onComplete) { // Get cache settings TTSDiskCacheSettings cacheSettings = new TTSDiskCacheSettings() { DiskCacheLocation = TTSDiskCacheLocation.Preload }; // Get total phrases int phraseTotal = 0; foreach (var voice in preloadData.voices) { if (voice.phrases == null) { continue; } foreach (var phrase in voice.phrases) { phraseTotal++; } } // Begin onProgress?.Invoke(0f); // Iterate int phraseCount = 0; float phraseInc = 1f / (float)phraseTotal; string log = string.Empty; for (int v = 0; v < preloadData.voices.Length; v++) { // Get voice data TTSPreloadVoiceData voiceData = preloadData.voices[v]; // Get voice TTSVoiceSettings voiceSettings = service.GetPresetVoiceSettings(voiceData.presetVoiceID); if (voiceSettings == null) { log += "\n-Missing Voice Setting: " + voiceData.presetVoiceID; phraseCount += voiceData.phrases.Length; continue; } // Iterate phrases for (int p = 0; p < voiceData.phrases.Length; p++) { // Iterate progress float progress = (float)phraseCount / (float)phraseTotal; onProgress?.Invoke(progress); phraseCount++; // Iterate yield return(onIterate(service, cacheSettings, voiceSettings, voiceData.phrases[p], (p2) => onProgress?.Invoke(progress + p2 * phraseInc), (l) => log += l)); } } // Complete onProgress?.Invoke(1f); onComplete?.Invoke(log); }