Пример #1
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);
        }
Пример #2
0
        // 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;
        }
Пример #3
0
        // 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);
        }
Пример #4
0
        // 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);
        }
Пример #5
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);
        }
Пример #6
0
        // 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);
        }
Пример #7
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);
        }
Пример #8
0
        // 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]);
            }
        }
Пример #9
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);
        }
Пример #10
0
 public TTSClipData DownloadToDiskCache(string textToSpeak, TTSVoiceSettings voiceSettings,
                                        TTSDiskCacheSettings diskCacheSettings, Action <TTSClipData, string, string> onDownloadComplete = null) =>
 DownloadToDiskCache(textToSpeak, null, voiceSettings, diskCacheSettings, onDownloadComplete);
Пример #11
0
 public TTSClipData DownloadToDiskCache(string textToSpeak, string presetVoiceId,
                                        TTSDiskCacheSettings diskCacheSettings, Action <TTSClipData, string, string> onDownloadComplete = null) =>
 DownloadToDiskCache(textToSpeak, null, GetPresetVoiceSettings(presetVoiceId), diskCacheSettings,
                     onDownloadComplete);
Пример #12
0
 /// <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));
Пример #13
0
        /// <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);
        }
Пример #14
0
 public TTSClipData Load(string textToSpeak, TTSVoiceSettings voiceSettings, TTSDiskCacheSettings diskCacheSettings, Action <TTSClipData, string> onStreamReady = null) => Load(textToSpeak, null, voiceSettings, diskCacheSettings, onStreamReady);
Пример #15
0
 public TTSClipData Load(string textToSpeak, string presetVoiceId, TTSDiskCacheSettings diskCacheSettings, Action <TTSClipData, string> onStreamReady           = null) => Load(textToSpeak, null, GetPresetVoiceSettings(presetVoiceId), diskCacheSettings, onStreamReady);
Пример #16
0
        // 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);
        }