// Performs download to disk cache protected virtual void DownloadToDiskCache(TTSClipData clipData, Action <TTSClipData, string, string> onDownloadComplete) { // Add delegates if needed AddDelegates(); // Check if cached to disk & log string downloadPath = DiskCacheHandler.GetDiskCachePath(clipData); bool found = DiskCacheHandler.IsCachedToDisk(clipData); LogClip($"Disk Cache {(found ? "Found" : "Missing")}\nPath: {downloadPath}", clipData); // Found if (found) { onDownloadComplete?.Invoke(clipData, downloadPath, string.Empty); return; } // Fail if not preloaded if (Application.isPlaying && clipData.diskCacheSettings.DiskCacheLocation == TTSDiskCacheLocation.Preload) { onDownloadComplete?.Invoke(clipData, downloadPath, "File is not Preloaded"); return; } // Return error clipData.onDownloadComplete += (error) => onDownloadComplete(clipData, downloadPath, error); // Download to cache & then stream WebHandler.RequestDownloadFromWeb(clipData, downloadPath); }
/// <summary> /// Perform clip unload /// </summary> /// <param name="clipID"></param> private void OnUnloadBegin(TTSClipData clipData) { // Abort if currently preparing if (clipData.loadState == TTSClipLoadState.Preparing) { // Cancel web stream WebHandler?.CancelWebStream(clipData); // Cancel web download to cache WebHandler?.CancelWebDownload(clipData, GetDiskCachePath(clipData.textToSpeak, clipData.clipID, clipData.voiceSettings, clipData.diskCacheSettings)); // Cancel disk cache stream DiskCacheHandler?.CancelDiskCacheStream(clipData); } // Destroy clip else if (clipData.clip != null) { MonoBehaviour.DestroyImmediate(clipData.clip); } // Clip is now unloaded SetClipLoadState(clipData, TTSClipLoadState.Unloaded); // Unload LogClip($"Unload Clip", clipData); Events?.OnClipUnloaded?.Invoke(clipData); }
/// <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> /// Whether a specific clip should be cached /// </summary> /// <param name="clipData">Clip data</param> /// <returns>True if should be cached</returns> public bool ShouldCacheToDisk(TTSClipData clipData) => DiskCacheHandler != null && DiskCacheHandler.ShouldCacheToDisk(clipData);
/// <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); }