Exemple #1
0
        // 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);
        }
Exemple #2
0
        // Play begin
        protected virtual void OnPlaybackBegin(TTSClipData clipData)
        {
            // If already speaking, stop doing so
            OnPlaybackCancel();

            // Remove previous clip
            if (clipData != _lastClip && _lastClip != null)
            {
                _lastClip = null;
            }

            // Apply clip
            _lastClip = clipData;

            // If clip missing
            if (_lastClip == null || _lastClip.clip == null)
            {
                Debug.LogError("TTS Speaker - Clip destroyed prior to playback");
                return;
            }

            // Started speaking
            _speaking = true;
            Events?.OnStartSpeaking?.Invoke(this, _lastClip.textToSpeak);

            // Play clip & wait
            _source.PlayOneShot(_lastClip.clip);
            _player = StartCoroutine(OnPlaybackWait());
        }
Exemple #3
0
        /// <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);
        }
Exemple #4
0
        // Load complete
        protected virtual void OnLoadComplete(TTSClipData clipData, string error)
        {
            // Incorrect clip, ignore
            if (clipData != _loadingClip)
            {
                return;
            }

            // Loading complete
            _loadingClip = null;

            // Load failed
            if (clipData.clip == null)
            {
                Debug.LogError($"TTS Speaker - Load Clip - Failed\n{error}");
                Events?.OnClipLoadFailed?.Invoke(this, clipData.textToSpeak);
                return;
            }

            // Load success
            Events?.OnClipLoadSuccess?.Invoke(this, clipData.textToSpeak);

            // Play clip
            OnPlaybackBegin(clipData);
        }
Exemple #5
0
        /// <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);
        }
Exemple #6
0
        /// <summary>
        /// Add clip to cache and ensure it is most recently referenced
        /// </summary>
        /// <param name="clipData"></param>
        public void AddClip(TTSClipData clipData)
        {
            // Do not add null
            if (clipData == null)
            {
                return;
            }
            // Remove from order
            bool wasAdded  = true;
            int  clipIndex = _clipOrder.IndexOf(clipData.clipID);

            if (clipIndex != -1)
            {
                wasAdded = false;
                _clipOrder.RemoveAt(clipIndex);
            }

            // Add clip
            _clips[clipData.clipID] = clipData;
            // Add to end of order
            _clipOrder.Add(clipData.clipID);

            // Evict least recently used clips
            while (IsCacheFull() && _clipOrder.Count > 0)
            {
                RemoveClip(_clipOrder[0]);
            }

            // Call add delegate
            if (wasAdded && _clips.Keys.Count > 0)
            {
                OnClipAdded?.Invoke(clipData);
            }
        }
Exemple #7
0
        /// <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);
        }
Exemple #8
0
        // 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);
        }
Exemple #9
0
 // Cancel load
 protected virtual void OnLoadAbort()
 {
     // Abort any loading
     if (_loadingClip != null)
     {
         Events?.OnClipLoadAbort?.Invoke(this, _loadingClip.textToSpeak);
         _loadingClip = null;
     }
 }
Exemple #10
0
        // Load begin
        private void OnLoadBegin(TTSClipData clipData)
        {
            // Now preparing
            SetClipLoadState(clipData, TTSClipLoadState.Preparing);

            // Begin load
            LogClip($"Load Clip", clipData);
            Events?.OnClipCreated?.Invoke(clipData);
        }
Exemple #11
0
        // On web download complete
        private void OnWebDownloadCancel(TTSClipData clipData, string downloadPath)
        {
            // Invoke clip callback & clear
            clipData.onDownloadComplete?.Invoke(CANCEL_WARNING);
            clipData.onDownloadComplete = null;

            // Log
            LogClip($"Download Clip - Canceled\nPath: {downloadPath}", clipData);
            Events?.Download?.OnDownloadCancel?.Invoke(clipData, downloadPath);
        }
Exemple #12
0
        // On web download complete
        private void OnWebDownloadError(TTSClipData clipData, string downloadPath, string error)
        {
            // Invoke clip callback & clear
            clipData.onDownloadComplete?.Invoke(error);
            clipData.onDownloadComplete = null;

            // Log
            LogClip($"Download Clip - Failed\nPath: {downloadPath}", clipData, TTSLogType.Error);
            Events?.Download?.OnDownloadError?.Invoke(clipData, downloadPath, error);
        }
Exemple #13
0
        // On web download complete
        private void OnWebDownloadSuccess(TTSClipData clipData, string downloadPath)
        {
            // Invoke clip callback & clear
            clipData.onDownloadComplete?.Invoke(string.Empty);
            clipData.onDownloadComplete = null;

            // Log
            LogClip($"Download Clip - Success\nPath: {downloadPath}", clipData);
            Events?.Download?.OnDownloadSuccess?.Invoke(clipData, downloadPath);
        }
Exemple #14
0
 /// <summary>
 /// Force a runtime cache unload
 /// </summary>
 public void Unload(TTSClipData clipData)
 {
     if (RuntimeCacheHandler != null)
     {
         RuntimeCacheHandler.RemoveClip(clipData.clipID);
     }
     else
     {
         OnUnloadBegin(clipData);
     }
 }
 // Clip data
 private void OnClipGUI(TTSClipData clip)
 {
     // Generation Settings
     WitEditorUI.LayoutKeyLabel("Text", clip.textToSpeak);
     WitEditorUI.LayoutKeyObjectLabels("Voice Settings", clip.voiceSettings);
     WitEditorUI.LayoutKeyObjectLabels("Cache Settings", clip.diskCacheSettings);
     // Clip Settings
     EditorGUILayout.TextField("Clip ID", clip.clipID);
     EditorGUILayout.ObjectField("Clip", clip.clip, typeof(AudioClip), true);
     // Load Settings
     WitEditorUI.LayoutKeyLabel("Load State", clip.loadState.ToString());
     WitEditorUI.LayoutKeyLabel("Load Progress", (clip.loadProgress * 100f).ToString() + "%");
 }
Exemple #16
0
 // Compare clip with new text
 protected virtual bool IsClipSame(string clipID, TTSClipData clipData)
 {
     // Not same
     if (clipData == null)
     {
         return(false);
     }
     // Not same text
     if (!string.Equals(clipID, clipData.clipID, StringComparison.CurrentCultureIgnoreCase))
     {
         return(false);
     }
     // Success
     return(true);
 }
Exemple #17
0
        private void OnStreamCancel(TTSClipData clipData, bool fromDisk)
        {
            // Handled as an error
            SetClipLoadState(clipData, TTSClipLoadState.Error);

            // Invoke
            clipData.onPlaybackReady?.Invoke(CANCEL_WARNING);
            clipData.onPlaybackReady = null;

            // Callback delegate
            LogClip($"{(fromDisk ? "Disk" : "Web")} Stream Canceled", clipData);
            Events?.Stream?.OnStreamCancel?.Invoke(clipData);

            // Unload clip
            Unload(clipData);
        }
Exemple #18
0
 // Clip unloaded externally
 protected virtual void OnClipUnload(TTSClipData clipData)
 {
     // Handle abort for loading
     if (clipData == _loadingClip)
     {
         OnLoadAbort();
     }
     // Cancel playback & remove clip
     else if (clipData == _lastClip)
     {
         // Cancel playback
         OnPlaybackCancel();
         // Remove reference
         _lastClip = null;
     }
 }
Exemple #19
0
        private void OnStreamReady(TTSClipData clipData, bool fromDisk)
        {
            // Refresh cache for file size
            RuntimeCacheHandler?.AddClip(clipData);

            // Now loaded
            SetClipLoadState(clipData, TTSClipLoadState.Loaded);

            // Invoke playback is ready
            clipData.onPlaybackReady?.Invoke(string.Empty);
            clipData.onPlaybackReady = null;

            // Callback delegate
            LogClip($"{(fromDisk ? "Disk" : "Web")} Stream Ready", clipData);
            Events?.Stream?.OnStreamReady?.Invoke(clipData);
        }
Exemple #20
0
        private void OnStreamError(TTSClipData clipData, string error, bool fromDisk)
        {
            // Error
            SetClipLoadState(clipData, TTSClipLoadState.Error);

            // Invoke playback is ready
            clipData.onPlaybackReady?.Invoke(error);
            clipData.onPlaybackReady = null;

            // Stream error
            LogClip($"{(fromDisk ? "Disk" : "Web")} Stream Error\nError: {error}", clipData, TTSLogType.Error);
            Events?.Stream?.OnStreamError?.Invoke(clipData, error);

            // Unload clip
            Unload(clipData);
        }
Exemple #21
0
        // Returns an error if request is not valid
        private string IsRequestValid(TTSClipData clipData, WitConfiguration configuration)
        {
            // Invalid tts
            string valid = IsValid();

            if (!string.IsNullOrEmpty(valid))
            {
                return(valid);
            }
            // Invalid clip
            if (clipData == null)
            {
                return("No clip data provided");
            }
            // Success
            return(string.Empty);
        }
Exemple #22
0
        /// <summary>
        /// Unload all audio clips from the runtime cache
        /// </summary>
        public void UnloadAll()
        {
            // Failed
            TTSClipData[] clips = RuntimeCacheHandler?.GetClips();
            if (clips == null)
            {
                return;
            }

            // Copy array
            TTSClipData[] copy = new TTSClipData[clips.Length];
            clips.CopyTo(copy, 0);

            // Unload all clips
            foreach (var clip in copy)
            {
                Unload(clip);
            }
        }
Exemple #23
0
        /// <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);
        }
Exemple #24
0
        /// <summary>
        /// Remove clip from cache immediately
        /// </summary>
        /// <param name="clipID"></param>
        public void RemoveClip(string clipID)
        {
            // Id not found
            if (!_clips.ContainsKey(clipID))
            {
                return;
            }

            // Remove from dictionary
            TTSClipData clipData = _clips[clipID];

            _clips.Remove(clipID);

            // Remove from order list
            int clipIndex = _clipOrder.IndexOf(clipID);

            _clipOrder.RemoveAt(clipIndex);

            // Call remove delegate
            OnClipRemoved?.Invoke(clipData);
        }
Exemple #25
0
        /// <summary>
        /// Method for cancelling a running load request
        /// </summary>
        /// <param name="clipData">Clip request data</param>
        public bool CancelWebDownload(TTSClipData clipData, string downloadPath)
        {
            // Ignore if not performing
            if (!_webDownloads.ContainsKey(clipData.clipID))
            {
                return(false);
            }

            // Get request
            WitUnityRequest request = _webDownloads[clipData.clipID];

            _webDownloads.Remove(clipData.clipID);

            // Destroy immediately
            request?.Unload();

            // Download cancelled
            WebDownloadEvents?.OnDownloadCancel?.Invoke(clipData, downloadPath);

            // Success
            return(true);
        }
Exemple #26
0
        /// <summary>
        /// Cancel web stream
        /// </summary>
        /// <param name="clipID">Unique clip id</param>
        public bool CancelWebStream(TTSClipData clipData)
        {
            // Ignore without
            if (!_webStreams.ContainsKey(clipData.clipID))
            {
                return(false);
            }

            // Get request
            WitUnityRequest request = _webStreams[clipData.clipID];

            _webStreams.Remove(clipData.clipID);

            // Destroy immediately
            request?.Unload();

            // Call delegate
            WebStreamEvents?.OnStreamCancel?.Invoke(clipData);

            // Success
            return(true);
        }
Exemple #27
0
        /// <summary>
        /// Method for performing a web load request
        /// </summary>
        /// <param name="clipData">Clip request data</param>
        /// <param name="onStreamSetupComplete">Stream setup complete: returns clip and error if applicable</param>
        public void RequestStreamFromWeb(TTSClipData clipData)
        {
            // Stream begin
            WebStreamEvents?.OnStreamBegin?.Invoke(clipData);

            // Check if valid
            string validError = IsRequestValid(clipData, RequestSettings.configuration);

            if (!string.IsNullOrEmpty(validError))
            {
                WebStreamEvents?.OnStreamError?.Invoke(clipData, validError);
                return;
            }
            // Ignore if already performing
            if (_webStreams.ContainsKey(clipData.clipID))
            {
                CancelWebStream(clipData);
            }

            // Request tts
            _webStreams[clipData.clipID] = WitUnityRequest.RequestTTSStream(RequestSettings.configuration,
                                                                            clipData.textToSpeak, clipData.queryParameters,
                                                                            (progress) => clipData.loadProgress = progress,
                                                                            (clip, error) =>
            {
                _webStreams.Remove(clipData.clipID);
                clipData.clip = clip;
                if (string.IsNullOrEmpty(error))
                {
                    WebStreamEvents?.OnStreamReady?.Invoke(clipData);
                }
                else
                {
                    WebStreamEvents?.OnStreamError?.Invoke(clipData, error);
                }
            });
        }
Exemple #28
0
        /// <summary>
        /// Method for performing a web load request
        /// </summary>
        /// <param name="clipData">Clip request data</param>
        /// <param name="downloadPath">Path to save clip</param>
        public void RequestDownloadFromWeb(TTSClipData clipData, string downloadPath)
        {
            // Begin
            WebDownloadEvents?.OnDownloadBegin?.Invoke(clipData, downloadPath);

            // Ensure valid
            string validError = IsRequestValid(clipData, RequestSettings.configuration);

            if (!string.IsNullOrEmpty(validError))
            {
                WebDownloadEvents?.OnDownloadError?.Invoke(clipData, downloadPath, validError);
                return;
            }
            // Abort if already performing
            if (_webDownloads.ContainsKey(clipData.clipID))
            {
                CancelWebDownload(clipData, downloadPath);
            }

            // Request tts
            _webDownloads[clipData.clipID] = WitUnityRequest.RequestTTSDownload(downloadPath,
                                                                                RequestSettings.configuration, clipData.textToSpeak, clipData.queryParameters,
                                                                                (progress) => clipData.loadProgress = progress,
                                                                                (error) =>
            {
                _webDownloads.Remove(clipData.clipID);
                if (string.IsNullOrEmpty(error))
                {
                    WebDownloadEvents?.OnDownloadSuccess?.Invoke(clipData, downloadPath);
                }
                else
                {
                    WebDownloadEvents?.OnDownloadError?.Invoke(clipData, downloadPath, error);
                }
            });
        }
Exemple #29
0
 /// <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);
Exemple #30
0
 // On web download begin
 private void OnWebDownloadBegin(TTSClipData clipData, string downloadPath)
 {
     LogClip($"Download Clip - Begin\nPath: {downloadPath}", clipData);
     Events?.Download?.OnDownloadBegin?.Invoke(clipData, downloadPath);
 }