// Speak public async Task Say(VoiceRequest request, CancellationToken token) { // Stop speech StopSpeech(); // Stop blink if (request.DisableBlink && !token.IsCancellationRequested) { StopBlink(); } // Prefetch Web/TTS voice if (UsePrefetch) { PrefetchVoices(request.Voices, token); } // Speak sequentially foreach (var v in request.Voices) { if (token.IsCancellationRequested) { return; } if (v.Source == VoiceSource.Local) { if (voices.ContainsKey(v.Name)) { // Wait for PreGap await Task.Delay((int)(v.PreGap * 1000), token); // Play audio History?.Add(v); AudioSource.PlayOneShot(voices[v.Name]); } else { Debug.LogWarning($"Voice not found: {v.Name}"); } } else { // Download voice from web or TTS service var downloadStartTime = Time.time; AudioClip clip = null; if (v.Source == VoiceSource.Web) { if (VoiceDownloadFunc != null) { clip = await VoiceDownloadFunc(v, token); } else { Debug.LogError("Voice download function not found"); } } else if (v.Source == VoiceSource.TTS) { var ttsFunc = GetTTSFunction(v.GetTTSFunctionName()); if (ttsFunc != null) { clip = await ttsFunc(v, token); } else { Debug.LogError($"TTS function not found: {v.GetTTSFunctionName()}"); } } if (clip != null) { // Wait for PreGap remains after download var preGap = v.PreGap - (Time.time - downloadStartTime); if (preGap > 0) { if (!token.IsCancellationRequested) { try { await Task.Delay((int)(preGap * 1000), token); } catch (TaskCanceledException) { // TaskCanceledException raises Debug.Log("Task canceled in waiting PreGap"); } } } // Play audio History?.Add(v); AudioSource.PlayOneShot(clip); } } // Wait while voice playing while (AudioSource.isPlaying && !token.IsCancellationRequested) { await Task.Delay(1); } if (!token.IsCancellationRequested) { try { // Wait for PostGap await Task.Delay((int)(v.PostGap * 1000), token); } catch (TaskCanceledException) { Debug.Log("Task canceled in waiting PostGap"); } } } // Reset viseme LipSyncContext?.ResetContext(); // Restart blink if (request.DisableBlink && !token.IsCancellationRequested) { _ = StartBlinkAsync(); } }
// Speak public async Task Say(VoiceRequest request, CancellationToken token) { // Stop speech StopSpeech(); // Stop blink if (request.DisableBlink && !token.IsCancellationRequested) { StopBlink(); } // Speak sequentially foreach (var v in request.Voices) { if (token.IsCancellationRequested) { return; } if (v.Source == VoiceSource.Local) { if (voices.ContainsKey(v.Name)) { // Wait for PreGap await Task.Delay((int)(v.PreGap * 1000), token); // Play audio AudioSource.PlayOneShot(voices[v.Name]); } else { Debug.LogWarning($"Voice not found: {v.Name}"); } } else { // Download voice from web or TTS service var downloadStartTime = Time.time; AudioClip clip = null; if (v.Source == VoiceSource.Web) { clip = await(VoiceDownloadFunc ?? GetAudioClipFromWeb)(v, WebAudioType); } else if (v.Source == VoiceSource.TTS) { clip = await(SpeechToTextFunc ?? GetAudioClipFromTTS)(v, TTSAudioType); } if (clip != null) { // Wait for PreGap remains after download var preGap = v.PreGap - (Time.time - downloadStartTime); if (preGap > 0) { await Task.Delay((int)(preGap * 1000), token); } // Play audio AudioSource.PlayOneShot(clip); } } // Wait while voice playing while (AudioSource.isPlaying && !token.IsCancellationRequested) { await Task.Delay(1); } // Wait for PostGap await Task.Delay((int)(v.PostGap * 1000), token); } // Restart blink if (request.DisableBlink && !token.IsCancellationRequested) { StartBlink(); } }