Task Speak(CancellationToken?cancelToken) { if (string.IsNullOrWhiteSpace(text)) { return(Task.CompletedTask); } if (language.HasValue && !string.IsNullOrWhiteSpace(language.Value.Language)) { Locale locale = null; if (!string.IsNullOrWhiteSpace(language.Value.Country)) { locale = new Locale(language.Value.Language, language.Value.Country); } else { locale = new Locale(language.Value.Language); } var result = textToSpeech.IsLanguageAvailable(locale); if (result == LanguageAvailableResult.CountryAvailable) { textToSpeech.SetLanguage(locale); } else { Console.WriteLine("Locale: " + locale + " was not valid, setting to default."); SetDefaultLanguage(); } } else { SetDefaultLanguage(); } var tcs = new TaskCompletionSource <object>(); cancelToken?.Register(() => { textToSpeech.Stop(); tcs.TrySetCanceled(); }); textToSpeech.SetPitch(pitch); textToSpeech.SetSpeechRate(speakRate); textToSpeech.SetOnUtteranceProgressListener(new TtsProgressListener(tcs)); #pragma warning disable CS0618 // Type or member is obsolete count++; var map = new Dictionary <string, string> { [Android.Speech.Tts.TextToSpeech.Engine.KeyParamUtteranceId] = count.ToString() }; textToSpeech.Speak(text, QueueMode.Flush, map); #pragma warning restore CS0618 // Type or member is obsolete return(tcs.Task); }
private void Speak() { if (string.IsNullOrWhiteSpace(text)) { return; } if (!queue && textToSpeech.IsSpeaking) { textToSpeech.Stop(); } if (language.HasValue && !string.IsNullOrWhiteSpace(language.Value.Language)) { Locale locale = null; if (!string.IsNullOrWhiteSpace(language.Value.Country)) { locale = new Locale(language.Value.Language, language.Value.Country); } else { locale = new Locale(language.Value.Language); } var result = textToSpeech.IsLanguageAvailable(locale); if (result == LanguageAvailableResult.CountryAvailable) { textToSpeech.SetLanguage(locale); } else { Console.WriteLine("Locale: " + locale + " was not valid, setting to default."); SetDefaultLanguage(); } } else { SetDefaultLanguage(); } textToSpeech.SetPitch(pitch); textToSpeech.SetSpeechRate(speakRate); textToSpeech.Speak(text, queue ? QueueMode.Add : QueueMode.Flush, null); }
public async Task SpeakAsync(string text, int max, SpeechOptions options, CancellationToken cancelToken) { await Initialize(); // Wait for any previous calls to finish up if (tcsUtterances?.Task != null) { await tcsUtterances.Task; } if (cancelToken != null) { cancelToken.Register(() => { try { tts?.Stop(); tcsUtterances?.TrySetResult(true); } catch { } }); } if (options?.Locale?.Language != null) { JavaLocale locale = null; if (!string.IsNullOrWhiteSpace(options?.Locale.Country)) { locale = new JavaLocale(options.Locale.Language, options.Locale.Country); } else { locale = new JavaLocale(options.Locale.Language); } tts.SetLanguage(locale); } else { SetDefaultLanguage(); } if (options?.Pitch.HasValue ?? false) { tts.SetPitch(options.Pitch.Value); } else { tts.SetPitch(TextToSpeech.PitchDefault); } tts.SetSpeechRate(1.0f); var parts = text.SplitSpeak(max); numExpectedUtterances = parts.Count; tcsUtterances = new TaskCompletionSource <bool>(); var guid = Guid.NewGuid().ToString(); for (var i = 0; i < parts.Count && !cancelToken.IsCancellationRequested; i++) { // We require the utterance id to be set if we want the completed listener to fire var map = new Dictionary <string, string> { { AndroidTextToSpeech.Engine.KeyParamUtteranceId, $"{guid}.{i}" } }; if (options != null && options.Volume.HasValue) { map.Add(AndroidTextToSpeech.Engine.KeyParamVolume, options.Volume.Value.ToString(CultureInfo.InvariantCulture)); } // We use an obsolete overload here so it works on older API levels at runtime // Flush on first entry and add (to not flush our own previous) subsequent entries #pragma warning disable CS0618 tts.Speak(parts[i], i == 0 ? QueueMode.Flush : QueueMode.Add, map); #pragma warning restore CS0618 } await tcsUtterances.Task; }
protected override void OnCreate(Bundle bundle) { base.OnCreate(bundle); // Set our view from the "main" layout resource SetContentView(Resource.Layout.Main); // we need to register the onscreen gadgets we're interested in var btnSayIt = FindViewById<Button>(Resource.Id.btnSpeak); var editWhatToSay = FindViewById<EditText>(Resource.Id.editSpeech); var spinLanguages = FindViewById<Spinner>(Resource.Id.spinLanguage); var txtSpeedVal = FindViewById<TextView>(Resource.Id.textSpeed); var txtPitchVal = FindViewById<TextView>(Resource.Id.textPitch); var seekSpeed = FindViewById<SeekBar>(Resource.Id.seekSpeed); var seekPitch = FindViewById<SeekBar>(Resource.Id.seekPitch); // set up the initial pitch and speed values then the onscreen values // the pitch and rate both go from 0f to 1f, however if you have a seek bar with a max of 1, you get a single step // therefore, a simpler option is to have the slider go from 0 to 255 and divide the position of the slider by 255 to get // the float seekSpeed.Progress = seekPitch.Progress = 127; txtSpeedVal.Text = txtPitchVal.Text = "0.5"; // get the context - easiest way is to obtain it from an on screen gadget context = btnSayIt.Context; // set up the TextToSpeech object // third parameter is the speech engine to use textToSpeech = new TextToSpeech(this, this, "com.google.android.tts"); // set up the langauge spinner // set the top option to be default var langAvailable = new List<string>{ "Default" }; // our spinner only wants to contain the languages supported by the tts and ignore the rest var localesAvailable = Java.Util.Locale.GetAvailableLocales().ToList(); foreach (var locale in localesAvailable) { LanguageAvailableResult res = textToSpeech.IsLanguageAvailable(locale); switch (res) { case LanguageAvailableResult.Available: langAvailable.Add(locale.DisplayLanguage); break; case LanguageAvailableResult.CountryAvailable: langAvailable.Add(locale.DisplayLanguage); break; case LanguageAvailableResult.CountryVarAvailable: langAvailable.Add(locale.DisplayLanguage); break; } } langAvailable = langAvailable.OrderBy(t => t).Distinct().ToList(); var adapter = new ArrayAdapter<string>(this, Android.Resource.Layout.SimpleSpinnerDropDownItem, langAvailable); spinLanguages.Adapter = adapter; // set up the speech to use the default langauge // if a language is not available, then the default language is used. lang = Java.Util.Locale.Default; textToSpeech.SetLanguage(lang); // set the speed and pitch textToSpeech.SetPitch(.5f); textToSpeech.SetSpeechRate(.5f); // connect up the events btnSayIt.Click += delegate { // if there is nothing to say, don't say it if (!string.IsNullOrEmpty(editWhatToSay.Text)) textToSpeech.Speak(editWhatToSay.Text, QueueMode.Flush, null); }; // sliders seekPitch.StopTrackingTouch += (object sender, SeekBar.StopTrackingTouchEventArgs e) => { var seek = sender as SeekBar; var progress = seek.Progress / 255f; textToSpeech.SetPitch(progress); txtPitchVal.Text = progress.ToString("F2"); }; seekSpeed.StopTrackingTouch += (object sender, SeekBar.StopTrackingTouchEventArgs e) => { var seek = sender as SeekBar; var progress = seek.Progress / 255f; textToSpeech.SetSpeechRate(progress); txtSpeedVal.Text = progress.ToString("F2"); }; spinLanguages.ItemSelected += (object sender, AdapterView.ItemSelectedEventArgs e) => { lang = Java.Util.Locale.GetAvailableLocales().FirstOrDefault(t => t.DisplayLanguage == langAvailable[(int)e.Id]); // create intent to check the TTS has this language installed var checkTTSIntent = new Intent(); checkTTSIntent.SetAction(TextToSpeech.Engine.ActionCheckTtsData); StartActivityForResult(checkTTSIntent, NeedLang); }; }
async Task Speak(CancellationToken?cancelToken) { if (string.IsNullOrWhiteSpace(text)) { //return Task.CompletedTask; return; } if (language.HasValue && !string.IsNullOrWhiteSpace(language.Value.Language)) { Locale locale = null; if (!string.IsNullOrWhiteSpace(language.Value.Country)) { locale = new Locale(language.Value.Language, language.Value.Country); } else { locale = new Locale(language.Value.Language); } var result = textToSpeech.IsLanguageAvailable(locale); if (result == LanguageAvailableResult.CountryAvailable) { textToSpeech.SetLanguage(locale); } else { Console.WriteLine("Locale: " + locale + " was not valid, setting to default."); SetDefaultLanguage(); } } else { SetDefaultLanguage(); } var tcs = new TaskCompletionSource(); var flag = new AsyncManualResetEvent(); var utteranceID = Guid.NewGuid().ToString(); var doneTask = listener.ListenFor(utteranceID); cancelToken?.Register(() => { textToSpeech.Stop(); tcs?.TrySetCanceled(); listener?.completionSources?[utteranceID]?.TrySetCanceled(); }); var utteranceProgressListenerDictionary = new Dictionary <string, string>(); utteranceProgressListenerDictionary.Add(Android.Speech.Tts.TextToSpeech.Engine.KeyParamUtteranceId, utteranceID); utteranceProgressListenerDictionary.Add(Android.Speech.Tts.TextToSpeech.Engine.KeyParamVolume, volume.ToString()); textToSpeech.SetPitch(pitch); textToSpeech.SetSpeechRate(speakRate); //textToSpeech.SetOnUtteranceProgressListener(new TtsProgressListener(flag)); //var bundle = new Android.OS.Bundle(); //bundle.PutFloat(Android.Speech.Tts.TextToSpeech.Engine.KeyParamVolume, 1.0f); #pragma warning disable CS0618 // Type or member is obsolete //textToSpeech.Speak(text, QueueMode.Flush, bundle, text); textToSpeech.Speak(text, QueueMode.Flush, utteranceProgressListenerDictionary); #pragma warning restore CS0618 // Type or member is obsolete //return tcs.Task; //return Task.WhenAny(tcs.Task, flag.WaitAsync()); //return listener.IsDone(); //int i = 0; //var sw = new System.Diagnostics.Stopwatch(); //sw.Start(); //while (doneTask.Status != TaskStatus.RanToCompletion) //{ // Task.Delay(100).Wait(101); // //await Task.Delay(100, CancellationTokenHelpers.Timeout(105).Token); // Android.Util.Log.Debug("Speech", $"Iteration {i}, {sw.ElapsedMilliseconds} ms - status is {doneTask.Status}."); // i++; //} //return doneTask; await doneTask; }
protected override void OnCreate(Bundle bundle) { base.OnCreate(bundle); SetContentView(Resource.Layout.main); key = true; EditText tb1 = FindViewById<EditText>(Resource.Id.text); SeekBar ss = FindViewById<SeekBar>(Resource.Id.speed); TextView sst = FindViewById<TextView>(Resource.Id.textSpeed); SeekBar sp = FindViewById<SeekBar>(Resource.Id.ton); TextView spt = FindViewById<TextView>(Resource.Id.textton); Button button1 = FindViewById<Button>(Resource.Id.buttonread); ttsListFragment frag = SupportFragmentManager.FindFragmentById(Resource.Id.tts_list_fragment) as ttsListFragment; ttslist = new List<elemTts>(); ss.Progress = sp.Progress = 127; sst.Text = spt.Text = "0,5"; context = button1.Context; tt = new TextToSpeech(this, this); tt.SetPitch(1.25f); tt.SetSpeechRate(1f); sp.StopTrackingTouch += (object sender, SeekBar.StopTrackingTouchEventArgs e) => { var seek = sender as SeekBar; var progress = seek.Progress / 255f; tt.SetPitch(seek.Progress / 170f + 0.5f); spt.Text = progress.ToString("F2"); }; ss.StopTrackingTouch += (object sender, SeekBar.StopTrackingTouchEventArgs e) => { var seek = sender as SeekBar; var progress = seek.Progress / 255f; tt.SetSpeechRate(seek.Progress / 255f + 0.1f); sst.Text = progress.ToString("F2"); }; button1.Click += delegate { try { if (new Regex(@"[А-Яа-я]").Match(tb1.Text).Success) { tb1.FindFocus(); throw new Exception("возможно чтение только символов английского алфавита"); } ttslist.Add(new elemTts(tb1.Text, ss.Progress / 255f + 0.1f, sp.Progress / 170f + 0.5f)); frag.OnResume(); if (ttslist.Count == 1) { Dictionary<string, string> param = new Dictionary<string, string> { { TextToSpeech.Engine.KeyParamUtteranceId, "1" } }; tt.PlaySilence(10, QueueMode.Add, param); } } catch (Exception E) { Toast.MakeText(this, E.Message, ToastLength.Short).Show(); } }; Button button2 = FindViewById<Button>(Resource.Id.buttonload); button2.Click += delegate { StartActivityForResult(new Intent(this,typeof(FilePickerActivity)),tkey); }; }