using SpeechLib; using System; using System.Collections.Generic; using System.Threading; namespace spitalkDLL { public class SapiTalk { private SpVoice sapi = null; private Dictionary SpeakerList = new Dictionary(); private int Speed = 0; private int Volume = 100; private int AvatorIdx = 0; public SapiTalk() { int idx = 0; try { sapi = new SpVoice(); SpObjectTokenCategory sapiCat = new SpObjectTokenCategory(); Dictionary TokerPool = new Dictionary(); // See https://qiita.com/7shi/items/7781516d6746e29c03b4 sapiCat.SetId(@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Speech_OneCore\Voices", false); foreach (SpObjectToken token in sapiCat.EnumerateTokens()) { if (!TokerPool.ContainsKey(token.GetAttribute("name"))) { TokerPool.Add(token.GetAttribute("name"), token); } } foreach (SpObjectToken token in sapi.GetVoices("", "")) { if (!TokerPool.ContainsKey(token.GetAttribute("name"))) { TokerPool.Add(token.GetAttribute("name"), token); } } foreach (var item in TokerPool) { SpeakerList.Add(idx, item.Value); idx++; } } catch (Exception e) { Console.WriteLine("{0},{1},{2}", e.Message, e.InnerException == null ? "" : e.InnerException.Message, e.StackTrace); } } public Dictionary Talkers() { Dictionary ans = new Dictionary(); for (int i = 0; i < SpeakerList.Count; i++) { ans.Add(i, SpeakerList[i].GetDescription()); } return ans; } public void SetTalker(int talker) { AvatorIdx = talker; } public void SetVolume(int volume) { Volume = volume; } public void SetRate(int speed) { Speed = speed; } public void Talk(string text, bool asyncFlag = false) { try { SpObjectToken backupSapi = null; Thread t = new Thread(() => { backupSapi = sapi.Voice; sapi.Voice = SpeakerList[AvatorIdx]; sapi.Rate = Speed; sapi.Volume = Volume; sapi.Speak(text); sapi.Voice = backupSapi; }); t.SetApartmentState(ApartmentState.STA); t.Start(); if (!asyncFlag) t.Join(); } catch (Exception e) { throw new Exception(string.Format("発声処理で落ちたっす。{0}", e.Message)); } } public void Save(string filePath, string text) { try { SpObjectToken backupSapi = null; SpFileStream ss = new SpFileStream(); ss.Open(filePath, SpeechStreamFileMode.SSFMCreateForWrite); sapi.AudioOutputStream = ss; Thread t = new Thread(() => { backupSapi = sapi.Voice; sapi.Voice = SpeakerList[AvatorIdx]; sapi.Rate = Speed; sapi.Volume = Volume; sapi.Speak(text); sapi.Voice = backupSapi; }); t.SetApartmentState(ApartmentState.STA); t.Start(); t.Join(); ss.Close(); } catch (Exception e) { throw new Exception(string.Format("保存処理で落ちたっす。{0}", e.Message)); } } } }