예제 #1
0
        private void getVoicesInEditor()
        {
            cachedVoices.Clear();
            string args = "--voices" + (string.IsNullOrEmpty(Util.Config.TTS_LINUX_DATA) ? string.Empty : " --path=\"" + Util.Config.TTS_LINUX_DATA + '"');

#if ENABLE_IL2CPP && (UNITY_STANDALONE_WIN || UNITY_EDITOR_WIN)
            Common.Util.CTProcess process = new Common.Util.CTProcess();
#else
            System.Diagnostics.Process process = new System.Diagnostics.Process();
#endif
            process.StartInfo.FileName  = Util.Config.TTS_LINUX;
            process.StartInfo.Arguments = args;
            process.OutputDataReceived += process_OutputDataReceived;

            try
            {
                System.Threading.Thread worker = new System.Threading.Thread(() => startProcess(ref process, Util.Constants.DEFAULT_TTS_KILL_TIME, true));
                worker.Start();

                do
                {
                    System.Threading.Thread.Sleep(50);
                } while (worker.IsAlive || !process.HasExited);

                if (Util.Constants.DEV_DEBUG)
                {
                    Debug.Log("Finished after: " + (process.ExitTime - process.StartTime).Seconds);
                }

                if (process.ExitCode == 0)
                {
                    //do nothing
                }
                else
                {
                    using (System.IO.StreamReader sr = process.StandardError)
                    {
                        string errorMessage = "Could not get any voices: " + process.ExitCode + System.Environment.NewLine + sr.ReadToEnd();
                        Debug.LogError(errorMessage);
                    }
                }
            }
            catch (System.Exception ex)
            {
                string errorMessage = "Could not get any voices!" + System.Environment.NewLine + ex;
                Debug.LogError(errorMessage);
            }

            process.Dispose();

            cachedVoices = voices.OrderBy(s => s.Name).ToList();

            if (Util.Constants.DEV_DEBUG)
            {
                Debug.Log("Voices read: " + cachedVoices.CTDump());
            }

            onVoicesReady();
        }
        private IEnumerator getVoices()
        {
            voices.Clear();

            string args = "--voices" + (string.IsNullOrEmpty(Util.Config.TTS_LINUX_DATA)
            ? string.Empty
            : " --path=\"" + Util.Config.TTS_LINUX_DATA + '"');

#if ENABLE_IL2CPP
            Common.Util.CTProcess process = new Common.Util.CTProcess();
#else
            System.Diagnostics.Process process = new System.Diagnostics.Process();
#endif
            process.StartInfo.FileName  = Util.Config.TTS_LINUX;
            process.StartInfo.Arguments = args;
            process.OutputDataReceived += process_OutputDataReceived;

            System.Threading.Thread worker = new System.Threading.Thread(() => startProcess(ref process, Util.Constants.DEFAULT_TTS_KILL_TIME, true));
            worker.Start();

            do
            {
                yield return(null);
            } while (worker.IsAlive || !process.HasExited);

            if (process.ExitCode == 0)
            {
                //do nothing
            }
            else
            {
                using (System.IO.StreamReader sr = process.StandardError)
                {
                    string errorMessage = "Could not get any voices: " + process.ExitCode + System.Environment.NewLine +
                                          sr.ReadToEnd();
                    Debug.LogError(errorMessage);
                    onErrorInfo(null, errorMessage);
                }
            }

            process.Dispose();

            cachedVoices = voices.OrderBy(s => s.Name).ToList();

            if (Util.Constants.DEV_DEBUG)
            {
                Debug.Log("Voices read: " + cachedVoices.CTDump());
            }

            onVoicesReady();
        }
예제 #3
0
        public override void SpeakNativeInEditor(Model.Wrapper wrapper)
        {
            if (wrapper == null)
            {
                Debug.LogWarning("'wrapper' is null!");
            }
            else
            {
                if (string.IsNullOrEmpty(wrapper.Text))
                {
                    Debug.LogWarning("'wrapper.Text' is null or empty!");
                }
                else
                {
                    if (System.IO.File.Exists(applicationName))
                    {
                        string voiceName        = getVoiceName(wrapper);
                        int    calculatedRate   = calculateRate(wrapper.Rate);
                        int    calculatedVolume = calculateVolume(wrapper.Volume);

                        string args = "--speak " +
                                      "-text \"" + prepareText(wrapper) + "\" " +
                                      "-rate " + calculatedRate.ToString() + " " +
                                      "-volume " + calculatedVolume.ToString() + " \"" +
                                      "-voice " + voiceName.Replace('"', '\'') + '"';

                        if (Util.Config.DEBUG)
                        {
                            Debug.Log("Process arguments: " + args);
                        }
#if ENABLE_IL2CPP
                        Common.Util.CTProcess process = new Common.Util.CTProcess();
#else
                        System.Diagnostics.Process process = new System.Diagnostics.Process();
#endif
                        process.StartInfo.FileName  = applicationName;
                        process.StartInfo.Arguments = args;
#if ENABLE_IL2CPP
                        System.Threading.Thread worker = new System.Threading.Thread(() => startProcess(ref process, 0, false, false, false, false))
                        {
                            Name = wrapper.Uid.ToString()
                        };
#else
                        System.Threading.Thread worker = new System.Threading.Thread(() => startProcess(ref process))
                        {
                            Name = wrapper.Uid.ToString()
                        };
#endif
                        worker.Start();

                        silence = false;
                        onSpeakStart(wrapper);

                        do
                        {
                            System.Threading.Thread.Sleep(50);

                            if (silence && !process.HasExited)
                            {
                                process.Kill();
                            }
                        } while (worker.IsAlive || !process.HasExited);
#if ENABLE_IL2CPP
                        if (process.ExitCode == 0 || process.ExitCode == 123456) //123456 = Killed
#else
                        if (process.ExitCode == 0 || process.ExitCode == -1)     //-1 = Killed
#endif
                        {
                            if (Util.Config.DEBUG)
                            {
                                Debug.Log("Text spoken: " + wrapper.Text);
                            }

                            onSpeakComplete(wrapper);
                        }
                        else
                        {
                            using (System.IO.StreamReader sr = process.StandardError)
                            {
                                Debug.LogError("Could not speak the text: " + process.ExitCode + System.Environment.NewLine + sr.ReadToEnd());
                            }
                        }

                        process.Dispose();
                    }
                    else
                    {
                        string errorMessage = "Could not find the TTS-wrapper: '" + applicationName + "'";
                        Debug.LogError(errorMessage);
                        onErrorInfo(wrapper, errorMessage);
                    }
                }
            }
        }
예제 #4
0
 private void readSpeakNativeStream(ref Common.Util.CTProcess process, ref string[] speechTextArray, out int wordIndex, out string phoneme, out string viseme, out bool start, bool redirectOutputData = true, bool redirectErrorData = true)
예제 #5
0
        private IEnumerator getVoices()
        {
            if (System.IO.File.Exists(applicationName))
            {
                System.Collections.Generic.List <Model.Voice> voices = new System.Collections.Generic.List <Model.Voice>();

#if ENABLE_IL2CPP
                Common.Util.CTProcess process = new Common.Util.CTProcess();
#else
                System.Diagnostics.Process process = new System.Diagnostics.Process();
#endif
                process.StartInfo.FileName  = applicationName;
                process.StartInfo.Arguments = "--voices";

                System.Threading.Thread worker = new System.Threading.Thread(() => startProcess(ref process, Util.Constants.DEFAULT_TTS_KILL_TIME));
                worker.Start();

                do
                {
                    yield return(null);
                } while (worker.IsAlive || !process.HasExited);

                if (process.ExitCode == 0)
                {
                    using (System.IO.StreamReader streamReader = process.StandardOutput)
                    {
                        string reply;
                        while (!streamReader.EndOfStream)
                        {
                            reply = streamReader.ReadLine();

                            if (Util.Config.DEBUG)
                            {
                                Debug.Log("reply: " + reply);
                            }

                            if (!string.IsNullOrEmpty(reply))
                            {
                                if (reply.StartsWith(idVoice))
                                {
                                    string[] splittedString = reply.Split(splitChar, System.StringSplitOptions.RemoveEmptyEntries);

                                    if (splittedString.Length == 6)
                                    {
                                        voices.Add(new Model.Voice(splittedString[1], splittedString[2], Util.Helper.StringToGender(splittedString[3]), splittedString[4], splittedString[5]));
                                    }
                                    else
                                    {
                                        Debug.LogWarning("Voice is invalid: " + reply);
                                    }
                                }
                            }
                        }
                    }
                }
                else
                {
                    using (System.IO.StreamReader sr = process.StandardError)
                    {
                        string errorMessage = "Could not get any voices: " + process.ExitCode + System.Environment.NewLine + sr.ReadToEnd();
                        Debug.LogError(errorMessage);
                        onErrorInfo(null, errorMessage);
                    }
                }

                process.Dispose();

                cachedVoices = voices.OrderBy(s => s.Name).ToList();

                if (Util.Constants.DEV_DEBUG)
                {
                    Debug.Log("Voices read: " + cachedVoices.CTDump());
                }
            }
            else
            {
                string errorMessage = "Could not find the TTS-wrapper: '" + applicationName + "'";
                Debug.LogError(errorMessage);
                onErrorInfo(null, errorMessage);
            }

            onVoicesReady();
        }
예제 #6
0
        public override IEnumerator Generate(Model.Wrapper wrapper)
        {
            if (wrapper == null)
            {
                Debug.LogWarning("'wrapper' is null!");
            }
            else
            {
                if (string.IsNullOrEmpty(wrapper.Text))
                {
                    Debug.LogWarning("'wrapper.Text' is null or empty: " + wrapper);
                }
                else
                {
                    yield return(null); //return to the main process (uid)

                    if (System.IO.File.Exists(applicationName))
                    {
                        string voiceName        = getVoiceName(wrapper);
                        int    calculatedRate   = calculateRate(wrapper.Rate);
                        int    calculatedVolume = calculateVolume(wrapper.Volume);

                        string outputFile = getOutputFile(wrapper.Uid);

                        string args = "--speakToFile " +
                                      "-text \"" + prepareText(wrapper) + "\" " +
                                      "-file \"" + outputFile.Replace('"', '\'') + "\" " +
                                      "-rate " + calculatedRate.ToString() + " " +
                                      "-volume " + calculatedVolume.ToString() + " \"" +
                                      "-voice " + voiceName.Replace('"', '\'') + '"';

                        if (Util.Config.DEBUG)
                        {
                            Debug.Log("Process arguments: " + args);
                        }
#if ENABLE_IL2CPP
                        Common.Util.CTProcess process = new Common.Util.CTProcess();
#else
                        System.Diagnostics.Process process = new System.Diagnostics.Process();
#endif
                        process.StartInfo.FileName  = applicationName;
                        process.StartInfo.Arguments = args;

#if ENABLE_IL2CPP
                        System.Threading.Thread worker = new System.Threading.Thread(() => startProcess(ref process, 0, false, false, false, false))
                        {
                            Name = wrapper.Uid.ToString()
                        };
#else
                        System.Threading.Thread worker = new System.Threading.Thread(() => startProcess(ref process))
                        {
                            Name = wrapper.Uid.ToString()
                        };
#endif
                        worker.Start();

                        silence = false;
                        onSpeakAudioGenerationStart(wrapper);

                        do
                        {
                            yield return(null);
                        } while (worker.IsAlive || !process.HasExited);

                        if (process.ExitCode == 0)
                        {
                            processAudioFile(wrapper, outputFile);
                        }
                        else
                        {
                            using (System.IO.StreamReader sr = process.StandardError)
                            {
                                string errorMessage = "Could not generate the text: " + wrapper + System.Environment.NewLine + "Exit code: " + process.ExitCode + System.Environment.NewLine + sr.ReadToEnd();
                                Debug.LogError(errorMessage);
                                onErrorInfo(wrapper, errorMessage);
                            }
                        }

                        process.Dispose();
                    }
                    else
                    {
                        string errorMessage = "Could not find the TTS-wrapper: '" + applicationName + "'";
                        Debug.LogError(errorMessage);
                        onErrorInfo(wrapper, errorMessage);
                    }
                }
            }
        }
예제 #7
0
        public override IEnumerator SpeakNative(Model.Wrapper wrapper)
        {
            if (wrapper == null)
            {
                Debug.LogWarning("'wrapper' is null!");
            }
            else
            {
                if (string.IsNullOrEmpty(wrapper.Text))
                {
                    Debug.LogWarning("'wrapper.Text' is null or empty!");
                }
                else
                {
                    yield return(null); //return to the main process (uid)

                    if (System.IO.File.Exists(applicationName))
                    {
                        string voiceName        = getVoiceName(wrapper);
                        int    calculatedRate   = calculateRate(wrapper.Rate);
                        int    calculatedVolume = calculateVolume(wrapper.Volume);

                        string args = "--speak " +
                                      "-text \"" + prepareText(wrapper) + "\" " +
                                      "-rate " + calculatedRate.ToString() + " " +
                                      "-volume " + calculatedVolume.ToString() + " \"" +
                                      "-voice " + voiceName.Replace('"', '\'') + '"';

                        if (Util.Config.DEBUG)
                        {
                            Debug.Log("Process arguments: " + args);
                        }
#if ENABLE_IL2CPP
                        Common.Util.CTProcess process = new Common.Util.CTProcess();
#else
                        System.Diagnostics.Process process = new System.Diagnostics.Process();
#endif
                        //speakProcess.StartInfo.FileName = System.IO.Path.GetFileName(application);
                        //speakProcess.StartInfo.WorkingDirectory = System.IO.Path.GetDirectoryName(application);
                        process.StartInfo.FileName  = applicationName;
                        process.StartInfo.Arguments = args;

                        string[] speechTextArray  = Util.Helper.CleanText(wrapper.Text, false).Split(splitCharWords, System.StringSplitOptions.RemoveEmptyEntries);
                        int      wordIndex        = 0;
                        int      wordIndexCompare = 0;
                        string   phoneme          = string.Empty;
                        string   viseme           = string.Empty;
                        bool     start            = false;
#if ENABLE_IL2CPP
                        System.Threading.Thread worker = new System.Threading.Thread(() => readSpeakNativeStream(ref process, ref speechTextArray, out wordIndex, out phoneme, out viseme, out start, useVisemesAndPhonemesIL2CPP, useVisemesAndPhonemesIL2CPP))
                        {
                            Name = wrapper.Uid.ToString()
                        };
#else
                        System.Threading.Thread worker = new System.Threading.Thread(() => readSpeakNativeStream(ref process, ref speechTextArray, out wordIndex, out phoneme, out viseme, out start))
                        {
                            Name = wrapper.Uid.ToString()
                        };
#endif
                        worker.Start();

                        silence = false;
#if ENABLE_IL2CPP
                        processCreators.Add(wrapper.Uid, process);
#else
                        processes.Add(wrapper.Uid, process);
#endif
                        do
                        {
                            yield return(null);

                            if (wordIndex != wordIndexCompare)
                            {
                                onSpeakCurrentWord(wrapper, speechTextArray, wordIndex - 1);

                                wordIndexCompare = wordIndex;
                            }

                            if (!string.IsNullOrEmpty(phoneme))
                            {
                                onSpeakCurrentPhoneme(wrapper, phoneme);

                                phoneme = string.Empty;
                            }

                            if (!string.IsNullOrEmpty(viseme))
                            {
                                onSpeakCurrentViseme(wrapper, viseme);

                                viseme = string.Empty;
                            }

                            if (start)
                            {
                                onSpeakStart(wrapper);

                                start = false;
                            }
                        } while (worker.IsAlive || !process.HasExited);

                        // clear output
                        onSpeakCurrentPhoneme(wrapper, string.Empty);
                        onSpeakCurrentViseme(wrapper, string.Empty);
#if ENABLE_IL2CPP
                        if (process.ExitCode == 0 || process.ExitCode == 123456) //123456 = Killed
#else
                        if (process.ExitCode == 0 || process.ExitCode == -1)     //-1 = Killed
#endif
                        {
                            if (Util.Config.DEBUG)
                            {
                                Debug.Log("Text spoken: " + wrapper.Text);
                            }

                            onSpeakComplete(wrapper);
                        }
                        else
                        {
                            using (System.IO.StreamReader sr = process.StandardError)
                            {
                                string errorMessage = "Could not speak the text: " + wrapper + System.Environment.NewLine + "Exit code: " + process.ExitCode + System.Environment.NewLine + sr.ReadToEnd();
                                Debug.LogError(errorMessage);
                                onErrorInfo(wrapper, errorMessage);
                            }
                        }
#if ENABLE_IL2CPP
                        processCreators.Remove(wrapper.Uid);
#else
                        processes.Remove(wrapper.Uid);
#endif
                        process.Dispose();
                    }
                    else
                    {
                        string errorMessage = "Could not find the TTS-wrapper: '" + applicationName + "'";
                        Debug.LogError(errorMessage);
                        onErrorInfo(wrapper, errorMessage);
                    }
                }
            }
        }
 protected void startProcess(ref Common.Util.CTProcess process, int timeout = 0, bool eventOutputData = false, bool eventErrorData = false, bool redirectOutputData = true, bool redirectErrorData = true)
예제 #9
0
        public override void SpeakNativeInEditor(Model.Wrapper wrapper)
        {
            if (wrapper == null)
            {
                Debug.LogWarning("'wrapper' is null!");
            }
            else
            {
                if (string.IsNullOrEmpty(wrapper.Text))
                {
                    Debug.LogWarning("'wrapper.Text' is null or empty: " + wrapper);
                }
                else
                {
                    string voiceName        = getVoiceName(wrapper);
                    int    calculatedRate   = calculateRate(wrapper.Rate);
                    int    calculatedVolume = calculateVolume(wrapper.Volume);
                    int    calculatedPitch  = calculatePitch(wrapper.Pitch);

                    string args = (string.IsNullOrEmpty(voiceName) ? string.Empty : ("-v \"" + voiceName.Replace('"', '\'') + '"')) +
                                  (calculatedRate != defaultRate ? (" -s " + calculatedRate + " ") : string.Empty) +
                                  (calculatedVolume != defaultVolume ? (" -a " + calculatedVolume + " ") : string.Empty) +
                                  (calculatedPitch != defaultPitch ? (" -p " + calculatedPitch + " ") : string.Empty) +
                                  " -m \"" +
                                  wrapper.Text.Replace('"', '\'') + '"' +
                                  (string.IsNullOrEmpty(Util.Config.TTS_LINUX_DATA) ? string.Empty : " --path=\"" + Util.Config.TTS_LINUX_DATA + '"');

                    if (Util.Config.DEBUG)
                    {
                        Debug.Log("Process arguments: " + args);
                    }

#if ENABLE_IL2CPP && (UNITY_STANDALONE_WIN || UNITY_EDITOR_WIN)
                    Common.Util.CTProcess process = new Common.Util.CTProcess();
#else
                    System.Diagnostics.Process process = new System.Diagnostics.Process();
#endif
                    process.StartInfo.FileName  = Util.Config.TTS_LINUX;
                    process.StartInfo.Arguments = args;
#if ENABLE_IL2CPP && (UNITY_STANDALONE_WIN || UNITY_EDITOR_WIN)
                    System.Threading.Thread worker = new System.Threading.Thread(() => startProcess(ref process, 0, false, false, false, false))
                    {
                        Name = wrapper.Uid.ToString()
                    };
#else
                    System.Threading.Thread worker = new System.Threading.Thread(() => startProcess(ref process))
                    {
                        Name = wrapper.Uid.ToString()
                    };
#endif
                    worker.Start();

                    silence = false;
                    onSpeakStart(wrapper);

                    do
                    {
                        System.Threading.Thread.Sleep(50);

                        if (silence && !process.HasExited)
                        {
                            process.Kill();
                        }
                    } while (worker.IsAlive || !process.HasExited);

#if ENABLE_IL2CPP && (UNITY_STANDALONE_WIN || UNITY_EDITOR_WIN)
                    if (process.ExitCode == 0 || process.ExitCode == 123456) //123456 = Killed
#else
                    if (process.ExitCode == 0 || process.ExitCode == -1)     //-1 = Killed
#endif
                    {
                        if (Util.Config.DEBUG)
                        {
                            Debug.Log("Text spoken: " + wrapper.Text);
                        }

                        onSpeakComplete(wrapper);
                    }
                    else
                    {
                        using (System.IO.StreamReader sr = process.StandardError)
                        {
                            string errorMessage = "Could not speak the text: " + wrapper + System.Environment.NewLine + "Exit code: " + process.ExitCode + System.Environment.NewLine + sr.ReadToEnd();
                            Debug.LogError(errorMessage);
                            onErrorInfo(wrapper, errorMessage);
                        }
                    }

                    process.Dispose();
                }
            }
        }
예제 #10
0
        public override IEnumerator Generate(Model.Wrapper wrapper)
        {
            if (wrapper == null)
            {
                Debug.LogWarning("'wrapper' is null!");
            }
            else
            {
                if (string.IsNullOrEmpty(wrapper.Text))
                {
                    Debug.LogWarning("'wrapper.Text' is null or empty: " + wrapper);
                }
                else
                {
                    yield return(null); //return to the main process (uid)

                    string voiceName        = getVoiceName(wrapper);
                    int    calculatedRate   = calculateRate(wrapper.Rate);
                    int    calculatedVolume = calculateVolume(wrapper.Volume);
                    int    calculatedPitch  = calculatePitch(wrapper.Pitch);
                    string outputFile       = getOutputFile(wrapper.Uid);

                    string args = (string.IsNullOrEmpty(voiceName) ? string.Empty : ("-v \"" + voiceName.Replace('"', '\'') + '"')) +
                                  (calculatedRate != defaultRate ? (" -s " + calculatedRate + " ") : string.Empty) +
                                  (calculatedVolume != defaultVolume ? (" -a " + calculatedVolume + " ") : string.Empty) +
                                  (calculatedPitch != defaultPitch ? (" -p " + calculatedPitch + " ") : string.Empty) +
                                  " -w \"" + outputFile.Replace('"', '\'') + '"' +
                                  " -m \"" +
                                  wrapper.Text.Replace('"', '\'') + '"' +
                                  (string.IsNullOrEmpty(Util.Config.TTS_LINUX_DATA) ? string.Empty : " --path=\"" + Util.Config.TTS_LINUX_DATA + '"');

                    if (Util.Config.DEBUG)
                    {
                        Debug.Log("Process arguments: " + args);
                    }
#if ENABLE_IL2CPP && (UNITY_STANDALONE_WIN || UNITY_EDITOR_WIN)
                    Common.Util.CTProcess process = new Common.Util.CTProcess();
#else
                    System.Diagnostics.Process process = new System.Diagnostics.Process();
#endif
                    process.StartInfo.FileName  = Util.Config.TTS_LINUX;
                    process.StartInfo.Arguments = args;

#if ENABLE_IL2CPP && (UNITY_STANDALONE_WIN || UNITY_EDITOR_WIN)
                    System.Threading.Thread worker = new System.Threading.Thread(() => startProcess(ref process, 0, false, false, false, false))
                    {
                        Name = wrapper.Uid.ToString()
                    };
#else
                    System.Threading.Thread worker = new System.Threading.Thread(() => startProcess(ref process))
                    {
                        Name = wrapper.Uid.ToString()
                    };
#endif
                    worker.Start();

                    silence = false;
                    onSpeakAudioGenerationStart(wrapper);

                    do
                    {
                        yield return(null);
                    } while (worker.IsAlive || !process.HasExited);

                    if (process.ExitCode == 0)
                    {
                        processAudioFile(wrapper, outputFile);
                    }
                    else
                    {
                        using (System.IO.StreamReader sr = process.StandardError)
                        {
                            string errorMessage = "Could not generate the text: " + wrapper + System.Environment.NewLine + "Exit code: " + process.ExitCode + System.Environment.NewLine + sr.ReadToEnd();
                            Debug.LogError(errorMessage);
                            onErrorInfo(wrapper, errorMessage);
                        }
                    }

                    process.Dispose();
                }
            }
        }
        public override IEnumerator SpeakNative(Model.Wrapper wrapper)
        {
            if (wrapper == null)
            {
                Debug.LogWarning("'wrapper' is null!");
            }
            else
            {
                if (string.IsNullOrEmpty(wrapper.Text))
                {
                    Debug.LogWarning("'wrapper.Text' is null or empty: " + wrapper);
                }
                else
                {
                    yield return(null); //return to the main process (uid)

                    string voiceName        = getVoiceName(wrapper);
                    int    calculatedRate   = calculateRate(wrapper.Rate);
                    int    calculatedVolume = calculateVolume(wrapper.Volume);
                    int    calculatedPitch  = calculatePitch(wrapper.Pitch);

                    string args = (string.IsNullOrEmpty(voiceName)
                                ? string.Empty
                                : "-v \"" + voiceName.Replace('"', '\'') + '"') +
                                  (calculatedRate != defaultRate ? " -s " + calculatedRate + " " : string.Empty) +
                                  (calculatedVolume != defaultVolume ? " -a " + calculatedVolume + " " : string.Empty) +
                                  (calculatedPitch != defaultPitch ? " -p " + calculatedPitch + " " : string.Empty) +
                                  " -z " +
                                  " -m \"" +
                                  wrapper.Text.Replace('"', '\'') + '"' +
                                  (string.IsNullOrEmpty(Util.Config.TTS_LINUX_DATA)
                                ? string.Empty
                                : " --path=\"" + Util.Config.TTS_LINUX_DATA + '"');

                    if (Util.Config.DEBUG)
                    {
                        Debug.Log("Process arguments: " + args);
                    }
#if ENABLE_IL2CPP
                    Common.Util.CTProcess process = new Common.Util.CTProcess();
#else
                    System.Diagnostics.Process process = new System.Diagnostics.Process();
#endif
                    process.StartInfo.FileName  = Util.Config.TTS_LINUX;
                    process.StartInfo.Arguments = args;

                    System.Threading.Thread worker = new System.Threading.Thread(() => startProcess(ref process, 0, false, false, false, false))
                    {
                        Name = wrapper.Uid
                    };
                    worker.Start();

                    silence = false;
#if ENABLE_IL2CPP
                    processCreators.Add(wrapper.Uid, process);
#else
                    processes.Add(wrapper.Uid, process);
#endif
                    onSpeakStart(wrapper);

                    do
                    {
                        yield return(null);
                    } while (worker.IsAlive || !process.HasExited);

#if ENABLE_IL2CPP
                    if (process.ExitCode == 0 || process.ExitCode == 123456) //123456 = Killed
#else
                    if (process.ExitCode == 0 || process.ExitCode == -1)     //-1 = Killed
#endif
                    {
                        if (Util.Config.DEBUG)
                        {
                            Debug.Log("Text spoken: " + wrapper.Text);
                        }

                        onSpeakComplete(wrapper);
                    }
                    else
                    {
                        using (System.IO.StreamReader sr = process.StandardError)
                        {
                            string errorMessage = "Could not speak the text: " + wrapper + System.Environment.NewLine +
                                                  "Exit code: " + process.ExitCode + System.Environment.NewLine +
                                                  sr.ReadToEnd();
                            Debug.LogError(errorMessage);
                            onErrorInfo(wrapper, errorMessage);
                        }
                    }
#if ENABLE_IL2CPP
                    processCreators.Remove(wrapper.Uid);
#else
                    processes.Remove(wrapper.Uid);
#endif
                    process.Dispose();
                }
            }
        }
        private void getVoicesInEditor()
        {
#if ENABLE_IL2CPP
            Common.Util.CTProcess process = new Common.Util.CTProcess();
#else
            System.Diagnostics.Process process = new System.Diagnostics.Process();
#endif
            process.StartInfo.FileName  = Util.Config.TTS_MACOS;
            process.StartInfo.Arguments = "-v '?'";

            try
            {
                System.Threading.Thread worker = new System.Threading.Thread(() => startProcess(ref process, Util.Constants.DEFAULT_TTS_KILL_TIME));
                worker.Start();

                do
                {
                    System.Threading.Thread.Sleep(50);
                } while (worker.IsAlive || !process.HasExited);

                if (Util.Constants.DEV_DEBUG)
                {
                    Debug.Log("Finished after: " + (process.ExitTime - process.StartTime).Seconds);
                }

                if (process.ExitCode == 0)
                {
                    System.Collections.Generic.List <Model.Voice> voices =
                        new System.Collections.Generic.List <Model.Voice>(100);

                    using (System.IO.StreamReader streamReader = process.StandardOutput)
                    {
                        while (!streamReader.EndOfStream)
                        {
                            var reply = streamReader.ReadLine();

                            if (!string.IsNullOrEmpty(reply))
                            {
                                System.Text.RegularExpressions.Match match = sayRegex.Match(reply);

                                if (match.Success)
                                {
                                    var name = match.Groups[1].ToString();
                                    voices.Add(new Model.Voice(match.Groups[1].ToString(), match.Groups[3].ToString(),
                                                               Util.Helper.AppleVoiceNameToGender(name), "unknown",
                                                               match.Groups[2].ToString().Replace('_', '-')));
                                }
                            }
                        }
                    }

                    cachedVoices = voices.OrderBy(s => s.Name).ToList();

                    if (Util.Constants.DEV_DEBUG)
                    {
                        Debug.Log("Voices read: " + cachedVoices.CTDump());
                    }
                }
                else
                {
                    using (System.IO.StreamReader sr = process.StandardError)
                    {
                        string errorMessage = "Could not get any voices: " + process.ExitCode +
                                              System.Environment.NewLine + sr.ReadToEnd();
                        Debug.LogError(errorMessage);
                    }
                }
            }
            catch (System.Exception ex)
            {
                string errorMessage = "Could not get any voices!" + System.Environment.NewLine + ex;
                Debug.LogError(errorMessage);
            }

            process.Dispose();
            onVoicesReady();
        }
        public override void SpeakNativeInEditor(Model.Wrapper wrapper)
        {
            if (wrapper == null)
            {
                Debug.LogWarning("'wrapper' is null!");
            }
            else
            {
                if (string.IsNullOrEmpty(wrapper.Text))
                {
                    Debug.LogWarning("'wrapper.Text' is null or empty: " + wrapper);
                }
                else
                {
                    string voiceName      = getVoiceName(wrapper);
                    int    calculatedRate = calculateRate(wrapper.Rate);
#if ENABLE_IL2CPP
                    Common.Util.CTProcess process = new Common.Util.CTProcess();
#else
                    System.Diagnostics.Process process = new System.Diagnostics.Process();
#endif
                    string args = (string.IsNullOrEmpty(voiceName)
                                ? string.Empty
                                : " -v \"" + voiceName.Replace('"', '\'') + '"') +
                                  (calculatedRate != defaultRate ? " -r " + calculatedRate : string.Empty) + " \"" +
                                  wrapper.Text.Replace('"', '\'') + '"';

                    if (Util.Config.DEBUG)
                    {
                        Debug.Log("Process arguments: " + args);
                    }

                    process.StartInfo.FileName  = Util.Config.TTS_MACOS;
                    process.StartInfo.Arguments = args;

                    System.Threading.Thread worker = new System.Threading.Thread(() => startProcess(ref process, 0, false, false, false, false))
                    {
                        Name = wrapper.Uid
                    };
                    worker.Start();

                    silence = false;
                    onSpeakStart(wrapper);

                    do
                    {
                        System.Threading.Thread.Sleep(50);

                        if (silence && !process.HasExited)
                        {
                            process.Kill();
                        }
                    } while (worker.IsAlive || !process.HasExited);

#if ENABLE_IL2CPP
                    if (process.ExitCode == 0 || process.ExitCode == 123456) //123456 = Killed
#else
                    if (process.ExitCode == 0 || process.ExitCode == -1 || process.ExitCode == 137
                        ) //0 = normal ended, -1/137 = killed
#endif
                    {
                        if (Util.Config.DEBUG)
                        {
                            Debug.Log("Text spoken: " + wrapper.Text);
                        }

                        onSpeakComplete(wrapper);
                    }
                    else
                    {
                        using (System.IO.StreamReader sr = process.StandardError)
                        {
                            string errorMessage = "Could not speak the text: " + wrapper + System.Environment.NewLine +
                                                  "Exit code: " + process.ExitCode + System.Environment.NewLine +
                                                  sr.ReadToEnd();
                            Debug.LogError(errorMessage);
                            onErrorInfo(wrapper, errorMessage);
                        }
                    }

                    process.Dispose();
                }
            }
        }
        public override void GenerateInEditor(Model.Wrapper wrapper)
        {
            if (wrapper == null)
            {
                Debug.LogWarning("'wrapper' is null!");
            }
            else
            {
                if (string.IsNullOrEmpty(wrapper.Text))
                {
                    Debug.LogWarning("'wrapper.Text' is null or empty: " + wrapper);
                }
                else
                {
                    string voiceName      = getVoiceName(wrapper);
                    int    calculatedRate = calculateRate(wrapper.Rate);
                    string outputFile     = getOutputFile(wrapper.Uid);
#if ENABLE_IL2CPP
                    Common.Util.CTProcess process = new Common.Util.CTProcess();
#else
                    System.Diagnostics.Process process = new System.Diagnostics.Process();
#endif
                    string args = (string.IsNullOrEmpty(voiceName)
                                ? string.Empty
                                : " -v \"" + voiceName.Replace('"', '\'') + '"') +
                                  (calculatedRate != defaultRate ? " -r " + calculatedRate : string.Empty) + " -o \"" +
                                  outputFile.Replace('"', '\'') + '"' +
                                  " --file-format=AIFFLE" + " \"" +
                                  wrapper.Text.Replace('"', '\'') + '"';

                    if (Util.Config.DEBUG)
                    {
                        Debug.Log("Process arguments: " + args);
                    }

                    process.StartInfo.FileName  = Util.Config.TTS_MACOS;
                    process.StartInfo.Arguments = args;

                    System.Threading.Thread worker = new System.Threading.Thread(() => startProcess(ref process, 0, false, false, false, false))
                    {
                        Name = wrapper.Uid
                    };
                    worker.Start();

                    silence = false;
                    onSpeakAudioGenerationStart(wrapper);

                    do
                    {
                        System.Threading.Thread.Sleep(50);
                    } while (worker.IsAlive || !process.HasExited);

                    if (process.ExitCode == 0)
                    {
                        processAudioFile(wrapper, outputFile);
                    }
                    else
                    {
                        using (System.IO.StreamReader sr = process.StandardError)
                        {
                            string errorMessage = "Could not generate the text: " + wrapper +
                                                  System.Environment.NewLine + "Exit code: " + process.ExitCode +
                                                  System.Environment.NewLine + sr.ReadToEnd();
                            Debug.LogError(errorMessage);
                            onErrorInfo(wrapper, errorMessage);
                        }
                    }

                    process.Dispose();
                }
            }
        }
        private void getVoicesInEditor()
        {
            if (System.IO.File.Exists(applicationName))
            {
                System.Collections.Generic.List <Model.Voice>
                voices = new System.Collections.Generic.List <Model.Voice>();
#if ENABLE_IL2CPP
                Common.Util.CTProcess process = new Common.Util.CTProcess();
#else
                System.Diagnostics.Process process = new System.Diagnostics.Process();
#endif
                process.StartInfo.FileName  = applicationName;
                process.StartInfo.Arguments = "--voices";

                try
                {
                    System.Threading.Thread worker = new System.Threading.Thread(() => startProcess(ref process, Util.Constants.DEFAULT_TTS_KILL_TIME));
                    worker.Start();

                    do
                    {
                        System.Threading.Thread.Sleep(50);
                    } while (worker.IsAlive || !process.HasExited);

                    if (Util.Constants.DEV_DEBUG)
                    {
                        Debug.Log("Finished after: " + (process.ExitTime - process.StartTime).Seconds);
                    }

                    if (process.ExitCode == 0)
                    {
                        using (System.IO.StreamReader streamReader = process.StandardOutput)
                        {
                            while (!streamReader.EndOfStream)
                            {
                                var reply = streamReader.ReadLine();

                                if (!string.IsNullOrEmpty(reply))
                                {
                                    if (reply.StartsWith(idVoice))
                                    {
                                        string[] splittedString = reply.Split(splitChar,
                                                                              System.StringSplitOptions.RemoveEmptyEntries);

                                        if (splittedString.Length == 6)
                                        {
                                            //if (!splittedString[1].CTContains("espeak")) //ignore eSpeak voices
                                            //{
                                            voices.Add(new Model.Voice(splittedString[1], splittedString[2],
                                                                       Util.Helper.StringToGender(splittedString[3]), splittedString[4],
                                                                       splittedString[5]));
                                            //}
                                        }
                                        else
                                        {
                                            Debug.LogWarning("Voice is invalid: " + reply);
                                        }
                                    }
                                }
                            }
                        }
                    }
                    else
                    {
                        using (System.IO.StreamReader sr = process.StandardError)
                        {
                            string errorMessage = "Could not get any voices: " + process.ExitCode +
                                                  System.Environment.NewLine + sr.ReadToEnd();
                            Debug.LogError(errorMessage);
                        }
                    }
                }
                catch (System.Exception ex)
                {
                    string errorMessage = "Could not get any voices!" + System.Environment.NewLine + ex;
                    Debug.LogError(errorMessage);
                }

                process.Dispose();

                cachedVoices = voices.OrderBy(s => s.Name).ToList();

                if (Util.Constants.DEV_DEBUG)
                {
                    Debug.Log("Voices read: " + cachedVoices.CTDump());
                }
            }
            else
            {
                string errorMessage = "Could not find the TTS-wrapper: '" + applicationName + "'";
                Debug.LogError(errorMessage);
            }

            onVoicesReady();
        }