using System.Linq; using UnityEngine; namespace Crosstales.RTVoice.Util { /// Various helper functions. public abstract class Helper : Common.Util.BaseHelper { #region Variables private static readonly string[] appleFemales = { "Alice", //iOS "Alva", "Amelie", //macOS "Amélie", //iOS "Anna", "Carmit", "Catherine", //iOS "Damayanti", "Ellen", "Fiona", //macOS "Helena", //iOS "Ioana", //iOS "Joana", "Kanya", "Karen", "Kyoko", "Laura", "Lekha", "Li-mu", //iOS "Luciana", "Marie", //iOS "Mariska", "Martha", //iOS "Mei-Jia", "Melina", "Milena", "Moira", "Monica", //macOS "Mónica", //iOS "Nicky", //iOS "Nora", "O-ren", //iOS "Paulina", "Samantha", "Sara", "Satu", "Sin-ji", "Tessa", "Ting-Ting", //macOS "Veena", //macOS "Victoria", //macOS "Yelda", "Yu-shu", //iOS "Yuna", "Zosia", "Zuzana" }; private static readonly string[] appleMales = { "Aaron", //??? "Alex", //??? "Arthur", //iOS "Daniel", "Diego", //macOS "Fred", "Gordon", //iOS "Hattori", //iOS "Jorge", //macOS "Juan", //macOS "Luca", //macOS "Maged", "Martin", //iOS "Thomas", "Xander", "Yuri" //macOS //Rishi;UNKNOWN;en-IN //Tian-Tian;UNKNOWN;zh-CN }; private static readonly string[] wsaFemales = { "Ayumi", "Haruka", "Caroline", "Catherine", "Elsa", "Hazel", "Susan", "Heami", "Hedda", "Katja", "Heera", "Heidi", "Helena", "Laura", "Helia", "Helle", "Herena", "Hoda", "Hortence", "Julie", "Huihui", "Yaoyao", "Irina", "Kalpana", "Linda", "Maria", "Paulina", "Sabina", "Tracy", "Yating", "Hanhan", "Zira" }; private static readonly string[] wsaMales = { "Adam", "An", "Andika", "Andrei", "Asaf", "Bart", "Bengt", "Claude", "Cosimo", "Daniel", "Danny", "David", "Mark", "Filip", "Frank", "George", "Hemant", "Ichiro", "Ivan", "James", "Jon", "Kangkang", "Karsten", "Lado", "Matej", "Naayf", "Pablo", "Pattara", "Paul", "Pavel", "Raul", "Ravi", "Richard", "Rizwan", "Shaun", "Stefan", "Stefanos", "Szabolcs", "Tolga", "Valluvar", "Vit", "Zhiwei" }; public static readonly System.Collections.Generic.Dictionary LocaleCodes = new System.Collections.Generic.Dictionary(161); #endregion #region Static constructor static Helper() { LocaleCodes.Add(1025, "ar-sa"); LocaleCodes.Add(1026, "bg"); LocaleCodes.Add(1027, "ca"); LocaleCodes.Add(1028, "zh-tw"); LocaleCodes.Add(1029, "cs"); LocaleCodes.Add(1030, "da"); LocaleCodes.Add(1031, "de-de"); LocaleCodes.Add(1032, "el"); LocaleCodes.Add(1033, "en-us"); LocaleCodes.Add(1034, "es-es"); //traditional LocaleCodes.Add(1035, "fi"); LocaleCodes.Add(1036, "fr-fr"); LocaleCodes.Add(1037, "he"); LocaleCodes.Add(1038, "hu"); LocaleCodes.Add(1039, "is"); LocaleCodes.Add(1040, "it-it"); LocaleCodes.Add(1041, "ja"); LocaleCodes.Add(1042, "ko"); LocaleCodes.Add(1043, "nl-nl"); LocaleCodes.Add(1044, "no-no"); LocaleCodes.Add(1045, "pl"); LocaleCodes.Add(1046, "pt-br"); LocaleCodes.Add(1047, "rm"); LocaleCodes.Add(1048, "ro"); LocaleCodes.Add(1049, "ru"); LocaleCodes.Add(1050, "hr"); LocaleCodes.Add(1051, "sk"); LocaleCodes.Add(1052, "sq"); LocaleCodes.Add(1053, "sv-se"); LocaleCodes.Add(1054, "th"); LocaleCodes.Add(1055, "tr"); LocaleCodes.Add(1056, "ur"); LocaleCodes.Add(1057, "id"); LocaleCodes.Add(1058, "uk"); LocaleCodes.Add(1059, "be"); LocaleCodes.Add(1060, "sl"); LocaleCodes.Add(1061, "et"); LocaleCodes.Add(1062, "lv"); LocaleCodes.Add(1063, "lt"); LocaleCodes.Add(1064, "tg"); LocaleCodes.Add(1065, "fa"); LocaleCodes.Add(1066, "vi"); LocaleCodes.Add(1067, "hy"); LocaleCodes.Add(1068, "az-az"); LocaleCodes.Add(1069, "eu"); LocaleCodes.Add(1070, "sb"); LocaleCodes.Add(1071, "mk"); LocaleCodes.Add(1073, "ts"); LocaleCodes.Add(1074, "tn"); LocaleCodes.Add(1076, "xh"); LocaleCodes.Add(1077, "zu"); LocaleCodes.Add(1078, "af"); LocaleCodes.Add(1080, "fo"); LocaleCodes.Add(1081, "hi"); LocaleCodes.Add(1082, "mt"); LocaleCodes.Add(1084, "gd"); LocaleCodes.Add(1085, "yi"); LocaleCodes.Add(1086, "ms-my"); LocaleCodes.Add(1087, "kk"); LocaleCodes.Add(1089, "sw"); LocaleCodes.Add(1090, "tk"); LocaleCodes.Add(1091, "uz-uz"); LocaleCodes.Add(1092, "tt"); LocaleCodes.Add(1093, "bn"); LocaleCodes.Add(1094, "pa"); LocaleCodes.Add(1095, "gu"); LocaleCodes.Add(1096, "or"); LocaleCodes.Add(1097, "ta"); LocaleCodes.Add(1098, "te"); LocaleCodes.Add(1099, "kn"); LocaleCodes.Add(1100, "ml"); LocaleCodes.Add(1101, "as"); LocaleCodes.Add(1102, "mr"); LocaleCodes.Add(1103, "sa"); LocaleCodes.Add(1104, "mn"); LocaleCodes.Add(1105, "bo"); LocaleCodes.Add(1106, "cy"); LocaleCodes.Add(1107, "km"); LocaleCodes.Add(1108, "lo"); LocaleCodes.Add(1109, "my"); LocaleCodes.Add(1113, "sd"); LocaleCodes.Add(1118, "am"); LocaleCodes.Add(1120, "ks"); LocaleCodes.Add(1121, "ne"); LocaleCodes.Add(1140, "gn"); LocaleCodes.Add(1142, "la"); LocaleCodes.Add(1143, "so"); LocaleCodes.Add(1153, "mi"); LocaleCodes.Add(2049, "ar-iq"); LocaleCodes.Add(2052, "zh-cn"); LocaleCodes.Add(2055, "de-ch"); LocaleCodes.Add(2057, "en-gb"); LocaleCodes.Add(2058, "es-mx"); LocaleCodes.Add(2060, "fr-be"); LocaleCodes.Add(2064, "it-ch"); LocaleCodes.Add(2067, "nl-be"); LocaleCodes.Add(2068, "no-no"); LocaleCodes.Add(2070, "pt-pt"); LocaleCodes.Add(2072, "ro-mo"); LocaleCodes.Add(2073, "ru-mo"); LocaleCodes.Add(2074, "sr-sp"); LocaleCodes.Add(2077, "sv-fi"); LocaleCodes.Add(2092, "az-az"); LocaleCodes.Add(2108, "gd-ie"); LocaleCodes.Add(2110, "ms-bn"); LocaleCodes.Add(2115, "uz-uz"); LocaleCodes.Add(2117, "bn"); LocaleCodes.Add(2128, "mn"); LocaleCodes.Add(3073, "ar-eg"); LocaleCodes.Add(3076, "zh-hk"); LocaleCodes.Add(3079, "de-at"); LocaleCodes.Add(3081, "en-au"); LocaleCodes.Add(3082, "es-es"); //modern LocaleCodes.Add(3084, "fr-ca"); LocaleCodes.Add(3098, "sr-sp"); LocaleCodes.Add(4097, "ar-ly"); LocaleCodes.Add(4100, "zh-sg"); LocaleCodes.Add(4103, "de-lu"); LocaleCodes.Add(4105, "en-ca"); LocaleCodes.Add(4106, "es-gt"); LocaleCodes.Add(4108, "fr-ch"); LocaleCodes.Add(5121, "ar-dz"); LocaleCodes.Add(5124, "zh-mo"); LocaleCodes.Add(5127, "de-li"); LocaleCodes.Add(5129, "en-nz"); LocaleCodes.Add(5130, "es-cr"); LocaleCodes.Add(5132, "fr-lu"); LocaleCodes.Add(5146, "bs"); LocaleCodes.Add(6145, "ar-ma"); LocaleCodes.Add(6153, "en-ie"); LocaleCodes.Add(6154, "es-pa"); LocaleCodes.Add(7169, "ar-tn"); LocaleCodes.Add(7177, "en-za"); LocaleCodes.Add(7178, "es-do"); LocaleCodes.Add(8193, "ar-om"); LocaleCodes.Add(8201, "en-jm"); LocaleCodes.Add(8202, "es-ve"); LocaleCodes.Add(9217, "ar-ye"); LocaleCodes.Add(9225, "en-cb"); LocaleCodes.Add(9226, "es-co"); LocaleCodes.Add(10241, "ar-sy"); LocaleCodes.Add(10249, "en-bz"); LocaleCodes.Add(10250, "es-pe"); LocaleCodes.Add(11265, "ar-jo"); LocaleCodes.Add(11273, "en-tt"); LocaleCodes.Add(11274, "es-ar"); LocaleCodes.Add(12289, "ar-lb"); LocaleCodes.Add(12298, "es-ec"); LocaleCodes.Add(13313, "ar-kw"); LocaleCodes.Add(13321, "en-ph"); LocaleCodes.Add(13322, "es-cl"); LocaleCodes.Add(14337, "ar-ae"); LocaleCodes.Add(14346, "es-uy"); LocaleCodes.Add(15361, "ar-bh"); LocaleCodes.Add(15370, "es-py"); LocaleCodes.Add(16385, "ar-qa"); LocaleCodes.Add(16393, "en-in"); LocaleCodes.Add(16394, "es-bo"); LocaleCodes.Add(17418, "es-sv"); LocaleCodes.Add(18442, "es-hn"); LocaleCodes.Add(19466, "es-ni"); LocaleCodes.Add(20490, "es-pr"); } #endregion #region Static properties /// Checks if the current platform has built-in TTS. /// True if the current platform has built-in TTS. public static bool hasBuiltInTTS => isWindowsBasedPlatform || isAppleBasedPlatform || isAndroidPlatform || isLinuxPlatform; //|| Speaker.isCustomMode && Speaker.CustomVoiceProvider != null && Speaker.CustomVoiceProvider.isPlatformSupported; /// The current provider type. /// Current provider type. public static Model.Enum.ProviderType CurrentProviderType { get { if (Speaker.Instance.CustomMode) return Model.Enum.ProviderType.Custom; if (isWindowsPlatform && !Speaker.Instance.ESpeakMode) return Model.Enum.ProviderType.Windows; if (isAndroidPlatform) return Model.Enum.ProviderType.Android; if (isIOSBasedPlatform) return Model.Enum.ProviderType.iOS; if (isWSABasedPlatform) return Model.Enum.ProviderType.WSA; if (isMacOSPlatform && !Speaker.Instance.ESpeakMode) return Model.Enum.ProviderType.macOS; return Model.Enum.ProviderType.Linux; } } #endregion #region Static methods /// Converts a string to a Gender. /// Gender as text. /// Gender from the given string. public static Model.Enum.Gender StringToGender(string gender) { if ("male".CTEquals(gender) || "m".CTEquals(gender)) { return Model.Enum.Gender.MALE; } if ("female".CTEquals(gender) || "f".CTEquals(gender)) { return Model.Enum.Gender.FEMALE; } return Model.Enum.Gender.UNKNOWN; } /// Converts an Apple voice name to a Gender. /// Voice name. /// Gender from the given Apple voice name. public static Model.Enum.Gender AppleVoiceNameToGender(string voiceName) { if (!string.IsNullOrEmpty(voiceName)) { if (appleFemales.Any(female => voiceName.CTContains(female))) { return Model.Enum.Gender.FEMALE; } if (appleMales.Any(male => voiceName.CTContains(male))) { return Model.Enum.Gender.MALE; } } return Model.Enum.Gender.UNKNOWN; } /// Converts an WSA voice name to a Gender. /// Voice name. /// Gender from the given WSA voice name. public static Model.Enum.Gender WSAVoiceNameToGender(string voiceName) { if (!string.IsNullOrEmpty(voiceName)) { if (wsaFemales.Any(female => voiceName.CTContains(female))) { return Model.Enum.Gender.FEMALE; } if (wsaMales.Any(male => voiceName.CTContains(male))) { return Model.Enum.Gender.MALE; } } return Model.Enum.Gender.UNKNOWN; } /// Cleans a given text to contain only letters or digits. /// Text to clean. /// Removes tags from text (default: true, optional). /// Clears multiple spaces from text (default: true, optional). /// Clears line endings from text (default: true, optional). /// Clean text with only letters and digits. public static string CleanText(string text, bool removeTags = true, bool clearSpaces = true, bool clearLineEndings = true) { string result = text; if (removeTags) { result = ClearTags(result); } if (clearSpaces) { result = ClearSpaces(result); } if (clearLineEndings) { result = ClearLineEndings(result); } return result; } /// Marks the current word or all spoken words from a given text array. /// Array with all text fragments /// Current word index /// Mark the spoken words (default: false, optional) /// Prefix for every marked word (default: green, optional) /// Postfix for every marked word (default: green, optional) /// Marked current word or all spoken words. public static string MarkSpokenText(string[] speechTextArray, int wordIndex, bool markAllSpokenWords = false, string markPrefix = "", string markPostfix = "") { System.Text.StringBuilder sb = new System.Text.StringBuilder(); if (speechTextArray == null) { Debug.LogWarning("The given 'speechTextArray' is null!"); } else { if (wordIndex < 0 || wordIndex > speechTextArray.Length - 1) { Debug.LogWarning("The given 'wordIndex' is invalid: " + wordIndex); } else { for (int ii = 0; ii < wordIndex; ii++) { if (markAllSpokenWords) sb.Append(markPrefix); sb.Append(speechTextArray[ii]); if (markAllSpokenWords) sb.Append(markPostfix); sb.Append(" "); } sb.Append(markPrefix); sb.Append(speechTextArray[wordIndex]); sb.Append(markPostfix); sb.Append(" "); for (int ii = wordIndex + 1; ii < speechTextArray.Length; ii++) { sb.Append(speechTextArray[ii]); sb.Append(" "); } } } return sb.ToString(); } #endregion } } // © 2015-2020 crosstales LLC (https://www.crosstales.com)