public void SortLinesBySpeaker(bool descending, EasyVoiceSettings settings) { for (int i = 0; i < LineCount(); i++) { for (int k = i + 1; k < LineCount(); k++) { int compareOrdinal = String.CompareOrdinal(GetSpeakerNameOrSelectDefault(i), GetSpeakerNameOrSelectDefault(k)); if (compareOrdinal > 0) { if (!descending) { Swap(i, k); } } else if (compareOrdinal < 0) { if (descending) { Swap(i, k); } } } } // This isn't very optimized and each swap is also not optimized }
public void Initialize() { #if DEBUG_MESSAGES Debug.Log("Initializing settings (querier = " + queriedForVoiceList + ")"); #endif //Hide(); instance = this; if (querier == null) { InitializeQuerier(); } if (!queriedForVoiceList) { if (querier != null) { queriedForVoiceList = true; querier.QueryForVoiceList(this); } } //if (defaultVoice == defaultSpeakerNameString) // defaultVoice = GetFirstSpeakerNameOrDefault(); }
public static CreateFilesCheckResult CreateFilesPreCheck(EasyVoiceSettings settings) { if (!settings.IsDefaultFolderValid()) return CreateFilesCheckResult.badDefaultFolder; string fullPath = settings.GetFullClipDefaultPath(); if (!Directory.Exists(fullPath)) return CreateFilesCheckResult.missingDefaultFolder; if (!settings.querier.VerifyApp()) return CreateFilesCheckResult.querierFailedToVerifyApp; return CreateFilesCheckResult.ok; // no apparent problems }
public static CreateFilesCheckResult CreateFilesPreCheck(EasyVoiceSettings settings) { if (!settings.IsDefaultFolderValid()) { return(CreateFilesCheckResult.badDefaultFolder); } string fullPath = settings.GetFullClipDefaultPath(); if (!Directory.Exists(fullPath)) { return(CreateFilesCheckResult.missingDefaultFolder); } if (!settings.querier.VerifyApp()) { return(CreateFilesCheckResult.querierFailedToVerifyApp); } return(CreateFilesCheckResult.ok); // no apparent problems }
public override void QueryForVoiceList(EasyVoiceSettings settings) { settings.voiceNames = null; settings.voiceDescriptions = null; settings.voiceGenders = null; settings.voiceAges = null; Process voiceListRequest = new Process(); //ProcessStartInfo startInfo = new ProcessStartInfo(); ////startInfo.FileName = Application.dataPath + @"/../EasyVoiceApps/EasyVoiceMacTerminalSpoof/bin/Debug/EasyVoiceMacTerminalSpoof.exe"; ////startInfo.Arguments = "-v '?' -break"; //startInfo.FileName = @"/usr/bin/say"; //startInfo.Arguments = "-v '?'"; //startInfo.CreateNoWindow = true; //startInfo.RedirectStandardOutput = true; // we need to capture it //startInfo.RedirectStandardError = true; // we need to capture it //startInfo.UseShellExecute = false; // must be false for redirect output //voiceListRequest.StartInfo = startInfo; //voiceListRequest.StartInfo.FileName = Application.dataPath + @"/../EasyVoiceApps/EasyVoiceMacTerminalSpoof/bin/Debug/EasyVoiceMacTerminalSpoof.exe"; //voiceListRequest.StartInfo.Arguments = "-v '?' -break"; voiceListRequest.StartInfo.FileName = @"/usr/bin/say"; voiceListRequest.StartInfo.Arguments = "-v '?'"; voiceListRequest.StartInfo.CreateNoWindow = true; voiceListRequest.StartInfo.RedirectStandardOutput = true; // we need to capture it voiceListRequest.StartInfo.RedirectStandardError = true; // we need to capture it voiceListRequest.StartInfo.UseShellExecute = false; // must be false for redirect output #if DEBUG_MESSAGES Debug.Log("Starting query..."); #endif try { voiceListRequest.Start(); voiceListRequest.WaitForExit(); } catch (Exception exception) { #if USE_CLOSE voiceListRequest.Close(); #endif Debug.LogError("Process start/run error: " + exception); return; } if (voiceListRequest.ExitCode == 0) { using (StreamReader streamReader = voiceListRequest.StandardOutput) { settings.voiceNames = new List<string>(); settings.voiceDescriptions = new List<string>(); settings.voiceGenders = new List<string>(); settings.voiceAges = new List<string>(); while (!streamReader.EndOfStream) { string reply = streamReader.ReadLine(); // Skip empty strings if (string.IsNullOrEmpty(reply)) continue; Match match = Regex.Match(reply, @"^([^#]+?)\s*([^ ]+)\s*# (.*?)$"); if (match.Success) { settings.voiceNames.Add(match.Groups[1].ToString()); settings.voiceDescriptions.Add(match.Groups[3].ToString()); settings.voiceGenders.Add(""); settings.voiceAges.Add(""); #if DEBUG_MESSAGES Debug.Log(settings.voiceNames[settings.voiceNames.Count - 1] + " -- " + settings.voiceDescriptions[settings.voiceNames.Count - 1]); #endif } else { #if DEBUG_MESSAGES // Apparently custom voices can insert extra lines into the terminal output, so we cannot print this in production Debug.LogError("Process returned unexpected line: " + reply); #endif } } //string result = streamReader.ReadToEnd(); //Debug.Log(result); } } else { using (StreamReader streamReader = voiceListRequest.StandardError) { string result = streamReader.ReadToEnd(); // If "say" reports there is no '?' voice, then it doesn't support -v '?' syntax and we need to do the ls speech folder if (result.StartsWith("Voice `?' not found")) { #if USE_CLOSE voiceListRequest.Close(); #endif QueryForVoiceListLs(settings); return; } Debug.LogError("Process error: " + result); } } #if USE_CLOSE voiceListRequest.Close(); #endif }
private void QueryForVoiceListLs(EasyVoiceSettings settings) { Process voiceListRequest = new Process(); //ProcessStartInfo startInfo = new ProcessStartInfo(); ////startInfo.FileName = Application.dataPath + @"/../EasyVoiceApps/EasyVoiceMacTerminalSpoof/bin/Debug/EasyVoiceMacTerminalSpoof.exe"; ////startInfo.Arguments = "-ls"; //startInfo.FileName = @"ls"; //startInfo.Arguments = "/System/Library/Speech/Voices"; //startInfo.CreateNoWindow = true; //startInfo.RedirectStandardOutput = true; // we need to capture it //startInfo.RedirectStandardError = true; // we need to capture it //startInfo.UseShellExecute = false; // must be false for redirect output //voiceListRequest.StartInfo = startInfo; //voiceListRequest.StartInfo.FileName = Application.dataPath + @"/../EasyVoiceApps/EasyVoiceMacTerminalSpoof/bin/Debug/EasyVoiceMacTerminalSpoof.exe"; //voiceListRequest.StartInfo.Arguments = "-ls"; voiceListRequest.StartInfo.FileName = @"ls"; voiceListRequest.StartInfo.Arguments = "/System/Library/Speech/Voices"; voiceListRequest.StartInfo.CreateNoWindow = true; voiceListRequest.StartInfo.RedirectStandardOutput = true; // we need to capture it voiceListRequest.StartInfo.RedirectStandardError = true; // we need to capture it voiceListRequest.StartInfo.UseShellExecute = false; // must be false for redirect output #if DEBUG_MESSAGES Debug.Log("Starting query..."); #endif try { voiceListRequest.Start(); voiceListRequest.WaitForExit(); } catch (Exception exception) { #if USE_CLOSE voiceListRequest.Close(); #endif Debug.LogError("Process start/run error: " + exception); return; } if (voiceListRequest.ExitCode == 0) { using (StreamReader streamReader = voiceListRequest.StandardOutput) { settings.voiceNames = new List <string>(); settings.voiceDescriptions = new List <string>(); settings.voiceGenders = new List <string>(); settings.voiceAges = new List <string>(); while (!streamReader.EndOfStream) { string reply = streamReader.ReadLine(); MatchCollection matches = Regex.Matches(reply, @"([^\s]+?)\.SpeechVoice"); foreach (Match match in matches) { settings.voiceNames.Add(match.Groups[1].ToString()); settings.voiceDescriptions.Add(""); settings.voiceGenders.Add(""); settings.voiceAges.Add(""); #if DEBUG_MESSAGES Debug.Log(settings.voiceNames[settings.voiceNames.Count - 1] + " -- " + settings.voiceDescriptions[settings.voiceNames.Count - 1]); #endif } } if (settings.voiceNames.Count == 0) { Debug.LogError("Process couldn't parse any speech names"); return; } //string result = streamReader.ReadToEnd(); //Debug.Log(result); } } else { using (StreamReader streamReader = voiceListRequest.StandardError) { string result = streamReader.ReadToEnd(); Debug.LogError("Process error: " + result); } } #if USE_CLOSE voiceListRequest.Close(); #endif }
public static ImportResult ImportData(string fileName, EasyVoiceSettings settings, bool append) { try { if (!File.Exists(fileName)) { Debug.LogWarning("EasyVoice.ImportData tried to open the file returned by Unity's dialog, but such file doesn't appear to exist: \"" + fileName + "\"!"); return(ImportResult.fail); } FileStream fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read); StreamReader streamReader = new StreamReader(fileStream, settings.exportCSVFileEncodingUTF8 ? Encoding.Unicode : Encoding.ASCII); string header = streamReader.ReadLine(); List <string> headerSplit = SplitLine(header); if (headerSplit == null || headerSplit.Count != 6 || headerSplit[0] != "ID" || headerSplit[1] != "Group" || headerSplit[2] != "Status" || headerSplit[3] != "Speaker" || headerSplit[4] != "Text" || headerSplit[5] != "File name") { Debug.LogWarning("EasyVoice.ImportData opened the CSV the file, but the header syntax did not match the expected format!"); return(ImportResult.fail); } List <int> tempIds = new List <int>(); List <string> tempGroups = new List <string>(); List <byte> tempStatuses = new List <byte>(); List <string> tempSpeakerNames = new List <string>(); List <string> tempSpeechTexts = new List <string>(); List <string> tempFileNames = new List <string>(); List <LineIssue> tempIssues = new List <LineIssue>(); while (!streamReader.EndOfStream) { string line = streamReader.ReadLine(); List <string> splitLine = SplitLine(line); //Debug.Log(splitLine); if (splitLine != null && splitLine.Count == 6) { int id; if (!int.TryParse(splitLine[0], out id)) { Debug.LogWarning("EasyVoice.ImportData opened the CSV the file, but an encountered id field syntax did not match the expected format!"); return(ImportResult.fail); } tempIds.Add(id); tempGroups.Add(splitLine[3]); byte status; if (!byte.TryParse(splitLine[2], out status)) { Debug.LogWarning("EasyVoice.ImportData opened the CSV the file, but an encountered status field syntax did not match the expected format!"); return(ImportResult.fail); } tempStatuses.Add(status); tempSpeakerNames.Add(splitLine[3]); tempSpeechTexts.Add(splitLine[4]); tempFileNames.Add(splitLine[5]); tempIssues.Add(0); } else { Debug.LogWarning("EasyVoice.ImportData opened the CSV the file, but an encountered line syntax did not match the expected format!"); return(ImportResult.fail); } } streamReader.Close(); fileStream.Close(); if (!append) { settings.data.DeleteAllLines(); } lastImportStartingLineCount = settings.data.LineCount(); bool defaultFolderValid = settings.IsDefaultFolderValid(); // so we don't check this too many times bool clipFound = false; for (int i = 0; i < tempSpeakerNames.Count; i++) { settings.data.AddNewLine(tempIds[i], tempGroups[i], tempStatuses[i], tempSpeakerNames[i], tempSpeechTexts[i], tempFileNames[i], tempIssues[i]); // If we need to find a clip (haven't found one yet) and also settings are valid to do this check if (!clipFound && defaultFolderValid) { string assetFileName, fullFileName; EasyVoiceClipCreator.GenerateFullFileName(i, out assetFileName, out fullFileName); AudioClip foundClip = (AudioClip)AssetDatabase.LoadAssetAtPath(assetFileName, typeof(AudioClip)); if (foundClip != null) { clipFound = true; } } } EasyVoiceIssueChecker.CheckAllLineIssues(); // this will get called again after linking clips, but we don't know if user will decide to do this yet return(clipFound ? ImportResult.matchingClipsFound : ImportResult.okay); } catch (Exception e) { Debug.LogError("EasyVoice.ImportData encountered an error: " + e); return(ImportResult.fail); } }
public void SetInstance() { instance = this; }
public void SortLinesBySpeaker(bool descending, EasyVoiceSettings settings) { for (int i = 0; i < LineCount(); i++) { for (int k = i + 1; k < LineCount(); k++) { int compareOrdinal = String.CompareOrdinal(GetSpeakerNameOrSelectDefault(i), GetSpeakerNameOrSelectDefault(k)); if (compareOrdinal > 0) { if (!descending) Swap(i, k); } else if (compareOrdinal < 0) { if (descending) Swap(i, k); } } } // This isn't very optimized and each swap is also not optimized }
public override void QueryForVoiceList(EasyVoiceSettings settings) { settings.voiceNames = null; settings.voiceDescriptions = null; settings.voiceGenders = null; settings.voiceAges = null; string fileName = FileName(); if (!File.Exists(fileName)) return; Process voiceListRequest = new Process(); //ProcessStartInfo startInfo = new ProcessStartInfo(); //startInfo.FileName = fileName; //startInfo.Arguments = "voiceList"; //startInfo.CreateNoWindow = true; //startInfo.RedirectStandardOutput = true; // we need to capture it //startInfo.RedirectStandardError = true; // we need to capture it //startInfo.UseShellExecute = false; // must be false for redirect output //voiceListRequest.StartInfo = startInfo; voiceListRequest.StartInfo.FileName = fileName; voiceListRequest.StartInfo.Arguments = "voiceList"; voiceListRequest.StartInfo.CreateNoWindow = true; voiceListRequest.StartInfo.RedirectStandardOutput = true; // we need to capture it voiceListRequest.StartInfo.RedirectStandardError = true; // we need to capture it voiceListRequest.StartInfo.UseShellExecute = false; // must be false for redirect output #if DEBUG_MESSAGES Debug.Log("Starting query..."); #endif voiceListRequest.Start(); voiceListRequest.WaitForExit(); if (voiceListRequest.ExitCode == 0) { using (StreamReader streamReader = voiceListRequest.StandardOutput) { string reply = streamReader.ReadLine(); if (reply == "VOICE LIST") { int count = int.Parse(streamReader.ReadLine()); settings.voiceNames = new List<string>(count); settings.voiceDescriptions = new List<string>(count); settings.voiceGenders = new List<string>(count); settings.voiceAges = new List<string>(count); for (int i = 0; i < count; i++) { settings.voiceNames.Add(streamReader.ReadLine()); settings.voiceDescriptions.Add(streamReader.ReadLine()); settings.voiceGenders.Add(streamReader.ReadLine()); settings.voiceAges.Add(streamReader.ReadLine()); #if DEBUG_MESSAGES Debug.Log(settings.voiceNames[settings.voiceNames.Count - 1] + ", " + settings.voiceGenders[settings.voiceNames.Count - 1] + ", " + settings.voiceAges[settings.voiceNames.Count - 1] + " -- " + settings.voiceDescriptions[settings.voiceNames.Count - 1]); #endif } } else if (reply == "ERROR") { Debug.LogError("EasyVoice Windows console returned an error for " + streamReader.ReadLine() + streamReader.ReadLine()); } else { Debug.LogError("Unexpected process output: " + reply + "\r\n" + streamReader.ReadToEnd()); } //string result = streamReader.ReadToEnd(); //Debug.Log(result); } } else { using (StreamReader streamReader = voiceListRequest.StandardError) { string result = streamReader.ReadToEnd(); Debug.LogError("Process error: " + result); } } #if USE_CLOSE voiceListRequest.Close(); #endif }
public static bool CreateFiles(EasyVoiceSettings settings) { if (CreateFilesPreCheck(settings) != CreateFilesCheckResult.ok) // this duplicates Editor Window UI, btu is quick enough return false; List<int> created = new List<int>(); lastCreatedAssetFileNames.Clear(); // if this is not empty, something wen't wrong? well, we can't fix it anyway without knowing details, and if we know details, we probably already either addressed them or notified the user //List<List<LineIssue>> issues = EasyVoiceIssueChecker.GetLineIssues(settings); List<int> lineIndices = new List<int>(); for (int i = 0; i < settings.data.LineCount(); i++) { if (!settings.data.GetOutputStatus(i)) continue; EasyVoiceIssueChecker.CheckLineIssues(i); if (IssuePreventsFileMaking(settings.data.GetIssues(i))) // most overwriting is "okay" continue; lineIndices.Add(i); } for (int i = 0; i < lineIndices.Count; i++) { int lineIndex = lineIndices[i]; string assetFileName; // this is Unity internal asset path starting with "Assets\" and including extension string fullFileName; // this is the file name, including the system path and extension GenerateFullFileName(lineIndex, out assetFileName, out fullFileName); #if DEBUG_MESSAGES Debug.Log(assetFileName); #endif settings.querier.AskToMakeFile( settings.data.GetSpeechText(lineIndex), settings.data.GetSpeakerNameOrSelectDefault(lineIndex), fullFileName, settings.osxFileFormat); // Check if the file has the wrong extension if (Path.GetExtension(fullFileName) != settings.querier.FileExtension) { #if DEBUG_MESSAGES Debug.Log("Audio clip file has a different extension than expected (\"" + settings.querier.FileExtension + "\")"); #endif int extensionIndex = fullFileName.LastIndexOf('.'); if (extensionIndex != 0) { string newName = fullFileName.Substring(0, extensionIndex) + settings.querier.FileExtension; File.Move(fullFileName, newName); extensionIndex = assetFileName.LastIndexOf('.'); if (extensionIndex != 0) // just in case asset file name is messed up assetFileName = assetFileName.Substring(0, extensionIndex) + settings.querier.FileExtension; #if DEBUG_MESSAGES Debug.Log("Renamed audio clip asset to \"" + newName + "\" and internal asset path to \"" + assetFileName + "\""); #endif } } created.Add(lineIndex); lastCreatedAssetFileNames.Add(assetFileName); settings.data.SetOutputStatus(lineIndex, false); EditorUtility.DisplayProgressBar(EasyVoiceSettings.progressDialogTitle, EasyVoiceSettings.progressDialogText, (i + 1f) / (lineIndices.Count + 1)); } #if UNITY_EDITOR //AssetDatabase.Refresh(); -- using AssetDatabase.ImportAsset instead #endif #if DEBUG_MESSAGES foreach (string lastCreatedAssetFileName in lastCreatedAssetFileNames) Debug.Log("Asset will be expected for linking: " + lastCreatedAssetFileName); #endif if (settings.linkClips) { for (int i = 0; i < created.Count; i++) { // Force asset to import AssetDatabase.ImportAsset(lastCreatedAssetFileNames[i], ImportAssetOptions.ForceSynchronousImport); // Get the new asset AudioClip foundClip = (AudioClip)AssetDatabase.LoadAssetAtPath(lastCreatedAssetFileNames[i], typeof(AudioClip)); //if (foundClip != null) //{ // System.Threading.Thread.Sleep(500); // wait a little bit of OS to possibly refresh, then retry // AssetDatabase.ImportAsset(lastCreatedAssetFileNames[i], ImportAssetOptions.ForceSynchronousImport); // foundClip = (AudioClip)AssetDatabase.LoadAssetAtPath(lastCreatedAssetFileNames[i], typeof(AudioClip)); //} if (foundClip != null) { #if DEBUG_MESSAGES Debug.Log("Audio clip to link was found at: " + lastCreatedAssetFileNames[i]); #endif // if (!lastCreatedAssetFileNames[i].EndsWith(settings.querier.FileExtension)) // { //#if DEBUG_MESSAGES // Debug.Log("Audio clip has a different extension than expected (\"" + settings.querier.FileExtension + "\")"); //#endif // int extensionIndex = lastCreatedAssetFileNames[i].LastIndexOf('.'); // if (extensionIndex > 0 && extensionIndex > lastCreatedAssetFileNames[i].Length - 10) // some sanity // { // int slashIndex = lastCreatedAssetFileNames[i].LastIndexOf('/'); // if (slashIndex != -1 && slashIndex < extensionIndex) // some more sanity // { // string newName = lastCreatedAssetFileNames[i].Substring(slashIndex + 1, extensionIndex - slashIndex - 1) + settings.querier.FileExtension; //#if DEBUG_MESSAGES // Debug.Log("Renaming audio clip asset to \"" + newName + "\""); //#endif // Debug.Log(AssetDatabase.RenameAsset(lastCreatedAssetFileNames[i], newName)); -- CAN'T, extension isn't renamed // } // } // } settings.data.SetClip(created[i], foundClip, false); // TODO: VERIFY? } else { Debug.LogWarning("EasyVoice expected an AudioClip asset to be generated at \"" + lastCreatedAssetFileNames[i] + "\", but it wasn't found!"); } } } #if DEBUG_MESSAGES else { Debug.Log("Settings not set to link created clips, skipping."); } #endif lastCreatedAssetFileNames.Clear(); return true; }
private void QueryForVoiceListLs(EasyVoiceSettings settings) { Process voiceListRequest = new Process(); //ProcessStartInfo startInfo = new ProcessStartInfo(); ////startInfo.FileName = Application.dataPath + @"/../EasyVoiceApps/EasyVoiceMacTerminalSpoof/bin/Debug/EasyVoiceMacTerminalSpoof.exe"; ////startInfo.Arguments = "-ls"; //startInfo.FileName = @"ls"; //startInfo.Arguments = "/System/Library/Speech/Voices"; //startInfo.CreateNoWindow = true; //startInfo.RedirectStandardOutput = true; // we need to capture it //startInfo.RedirectStandardError = true; // we need to capture it //startInfo.UseShellExecute = false; // must be false for redirect output //voiceListRequest.StartInfo = startInfo; //voiceListRequest.StartInfo.FileName = Application.dataPath + @"/../EasyVoiceApps/EasyVoiceMacTerminalSpoof/bin/Debug/EasyVoiceMacTerminalSpoof.exe"; //voiceListRequest.StartInfo.Arguments = "-ls"; voiceListRequest.StartInfo.FileName = @"ls"; voiceListRequest.StartInfo.Arguments = "/System/Library/Speech/Voices"; voiceListRequest.StartInfo.CreateNoWindow = true; voiceListRequest.StartInfo.RedirectStandardOutput = true; // we need to capture it voiceListRequest.StartInfo.RedirectStandardError = true; // we need to capture it voiceListRequest.StartInfo.UseShellExecute = false; // must be false for redirect output #if DEBUG_MESSAGES Debug.Log("Starting query..."); #endif try { voiceListRequest.Start(); voiceListRequest.WaitForExit(); } catch (Exception exception) { #if USE_CLOSE voiceListRequest.Close(); #endif Debug.LogError("Process start/run error: " + exception); return; } if (voiceListRequest.ExitCode == 0) { using (StreamReader streamReader = voiceListRequest.StandardOutput) { settings.voiceNames = new List<string>(); settings.voiceDescriptions = new List<string>(); settings.voiceGenders = new List<string>(); settings.voiceAges = new List<string>(); while (!streamReader.EndOfStream) { string reply = streamReader.ReadLine(); MatchCollection matches = Regex.Matches(reply, @"([^\s]+?)\.SpeechVoice"); foreach (Match match in matches) { settings.voiceNames.Add(match.Groups[1].ToString()); settings.voiceDescriptions.Add(""); settings.voiceGenders.Add(""); settings.voiceAges.Add(""); #if DEBUG_MESSAGES Debug.Log(settings.voiceNames[settings.voiceNames.Count - 1] + " -- " + settings.voiceDescriptions[settings.voiceNames.Count - 1]); #endif } } if (settings.voiceNames.Count == 0) { Debug.LogError("Process couldn't parse any speech names"); return; } //string result = streamReader.ReadToEnd(); //Debug.Log(result); } } else { using (StreamReader streamReader = voiceListRequest.StandardError) { string result = streamReader.ReadToEnd(); Debug.LogError("Process error: " + result); } } #if USE_CLOSE voiceListRequest.Close(); #endif }
public override void QueryForVoiceList(EasyVoiceSettings settings) { settings.voiceNames = null; settings.voiceDescriptions = null; settings.voiceGenders = null; settings.voiceAges = null; Process voiceListRequest = new Process(); //ProcessStartInfo startInfo = new ProcessStartInfo(); ////startInfo.FileName = Application.dataPath + @"/../EasyVoiceApps/EasyVoiceMacTerminalSpoof/bin/Debug/EasyVoiceMacTerminalSpoof.exe"; ////startInfo.Arguments = "-v '?' -break"; //startInfo.FileName = @"/usr/bin/say"; //startInfo.Arguments = "-v '?'"; //startInfo.CreateNoWindow = true; //startInfo.RedirectStandardOutput = true; // we need to capture it //startInfo.RedirectStandardError = true; // we need to capture it //startInfo.UseShellExecute = false; // must be false for redirect output //voiceListRequest.StartInfo = startInfo; //voiceListRequest.StartInfo.FileName = Application.dataPath + @"/../EasyVoiceApps/EasyVoiceMacTerminalSpoof/bin/Debug/EasyVoiceMacTerminalSpoof.exe"; //voiceListRequest.StartInfo.Arguments = "-v '?' -break"; voiceListRequest.StartInfo.FileName = @"/usr/bin/say"; voiceListRequest.StartInfo.Arguments = "-v '?'"; voiceListRequest.StartInfo.CreateNoWindow = true; voiceListRequest.StartInfo.RedirectStandardOutput = true; // we need to capture it voiceListRequest.StartInfo.RedirectStandardError = true; // we need to capture it voiceListRequest.StartInfo.UseShellExecute = false; // must be false for redirect output #if DEBUG_MESSAGES Debug.Log("Starting query..."); #endif try { voiceListRequest.Start(); voiceListRequest.WaitForExit(); } catch (Exception exception) { #if USE_CLOSE voiceListRequest.Close(); #endif Debug.LogError("Process start/run error: " + exception); return; } if (voiceListRequest.ExitCode == 0) { using (StreamReader streamReader = voiceListRequest.StandardOutput) { settings.voiceNames = new List <string>(); settings.voiceDescriptions = new List <string>(); settings.voiceGenders = new List <string>(); settings.voiceAges = new List <string>(); while (!streamReader.EndOfStream) { string reply = streamReader.ReadLine(); // Skip empty strings if (string.IsNullOrEmpty(reply)) { continue; } Match match = Regex.Match(reply, @"^([^#]+?)\s*([^ ]+)\s*# (.*?)$"); if (match.Success) { settings.voiceNames.Add(match.Groups[1].ToString()); settings.voiceDescriptions.Add(match.Groups[3].ToString()); settings.voiceGenders.Add(""); settings.voiceAges.Add(""); #if DEBUG_MESSAGES Debug.Log(settings.voiceNames[settings.voiceNames.Count - 1] + " -- " + settings.voiceDescriptions[settings.voiceNames.Count - 1]); #endif } else { #if DEBUG_MESSAGES // Apparently custom voices can insert extra lines into the terminal output, so we cannot print this in production Debug.LogError("Process returned unexpected line: " + reply); #endif } } //string result = streamReader.ReadToEnd(); //Debug.Log(result); } } else { using (StreamReader streamReader = voiceListRequest.StandardError) { string result = streamReader.ReadToEnd(); // If "say" reports there is no '?' voice, then it doesn't support -v '?' syntax and we need to do the ls speech folder if (result.StartsWith("Voice `?' not found")) { #if USE_CLOSE voiceListRequest.Close(); #endif QueryForVoiceListLs(settings); return; } Debug.LogError("Process error: " + result); } } #if USE_CLOSE voiceListRequest.Close(); #endif }
public void Initialize() { #if DEBUG_MESSAGES Debug.Log("Initializing settings (querier = " + queriedForVoiceList + ")"); #endif //Hide(); instance = this; if (querier == null) { InitializeQuerier(); } if (!queriedForVoiceList) { if (querier != null) { queriedForVoiceList = true; querier.QueryForVoiceList(this); } } //if (defaultVoice == defaultSpeakerNameString) // defaultVoice = GetFirstSpeakerNameOrDefault(); }
private static AudioClipLoadType LoadType(EasyVoiceSettings.AudioImportSettings.LoadType loadType) { switch (loadType) { case EasyVoiceSettings.AudioImportSettings.LoadType.DecompressOnLoad: return AudioClipLoadType.DecompressOnLoad; case EasyVoiceSettings.AudioImportSettings.LoadType.CompressedInMemory: return AudioClipLoadType.CompressedInMemory; case EasyVoiceSettings.AudioImportSettings.LoadType.Streaming: return AudioClipLoadType.Streaming; default: return AudioClipLoadType.DecompressOnLoad; // Do we have corrupted data? } }
//public static EasyVoiceSettings.AudioImportSettings.CompressionFormat CompressionFormat(AudioCompressionFormat format) //{ // switch (format) // { // case AudioCompressionFormat.PCM: // return EasyVoiceSettings.AudioImportSettings.CompressionFormat.PCM; // case AudioCompressionFormat.Vorbis: // return EasyVoiceSettings.AudioImportSettings.CompressionFormat.Vorbis; // case AudioCompressionFormat.ADPCM: // return EasyVoiceSettings.AudioImportSettings.CompressionFormat.ADPCM; // //case AudioCompressionFormat.MP3: // // return EasyVoiceSettings.AudioImportSettings.CompressionFormat.MP3; -- Unity doesn't support this for overall/default settings // //case AudioCompressionFormat.VAG: // // return EasyVoiceSettings.AudioImportSettings.CompressionFormat.VAG; -- Unity doesn't support this for overall/default settings // //case AudioCompressionFormat.HEVAG: // // return EasyVoiceSettings.AudioImportSettings.CompressionFormat.HEVAG; -- Unity doesn't support this for overall/default settings // default: // return EasyVoiceSettings.AudioImportSettings.CompressionFormat.Vorbis; // Unity has a new value? // } //} private static AudioSampleRateSetting SampleRate(EasyVoiceSettings.AudioImportSettings.SampleRate sampleRate) { switch (sampleRate) { case EasyVoiceSettings.AudioImportSettings.SampleRate.PreserveSampleRate: return AudioSampleRateSetting.PreserveSampleRate; case EasyVoiceSettings.AudioImportSettings.SampleRate.OptimizeSampleRate: return AudioSampleRateSetting.OptimizeSampleRate; case EasyVoiceSettings.AudioImportSettings.SampleRate.OverrideSampleRate: return AudioSampleRateSetting.OverrideSampleRate; default: return AudioSampleRateSetting.PreserveSampleRate; // Do we have corrupted data? } }
//public static EasyVoiceSettings.AudioImportSettings.LoadType LoadType(AudioClipLoadType loadType) //{ // switch (loadType) // { // case AudioClipLoadType.DecompressOnLoad: // return EasyVoiceSettings.AudioImportSettings.LoadType.DecompressOnLoad; // case AudioClipLoadType.CompressedInMemory: // return EasyVoiceSettings.AudioImportSettings.LoadType.CompressedInMemory; // case AudioClipLoadType.Streaming: // return EasyVoiceSettings.AudioImportSettings.LoadType.Streaming; // default: // return EasyVoiceSettings.AudioImportSettings.LoadType.DecompressOnLoad; // Unity has a new value? // } //} private static AudioCompressionFormat CompressionFormat(EasyVoiceSettings.AudioImportSettings.CompressionFormat format) { switch (format) { case EasyVoiceSettings.AudioImportSettings.CompressionFormat.PCM: return AudioCompressionFormat.PCM; case EasyVoiceSettings.AudioImportSettings.CompressionFormat.Vorbis: return AudioCompressionFormat.Vorbis; case EasyVoiceSettings.AudioImportSettings.CompressionFormat.ADPCM: return AudioCompressionFormat.ADPCM; //case EasyVoiceSettings.AudioImportSettings.CompressionFormat.MP3: -- Unity doesn't support this for overall/default settings // return AudioCompressionFormat.MP3; //case EasyVoiceSettings.AudioImportSettings.CompressionFormat.VAG: -- Unity doesn't support this for overall/default settings // return AudioCompressionFormat.VAG; //case EasyVoiceSettings.AudioImportSettings.CompressionFormat.HEVAG: -- Unity doesn't support this for overall/default settings // return AudioCompressionFormat.HEVAG; default: return AudioCompressionFormat.Vorbis; // Do we have corrupted data? } }
public abstract void QueryForVoiceList(EasyVoiceSettings settings);
public static ImportResult ImportData(string fileName, EasyVoiceSettings settings, bool append) { try { if (!File.Exists(fileName)) { Debug.LogWarning("EasyVoice.ImportData tried to open the file returned by Unity's dialog, but such file doesn't appear to exist: \"" + fileName + "\"!"); return ImportResult.fail; } FileStream fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read); StreamReader streamReader = new StreamReader(fileStream, settings.exportCSVFileEncodingUTF8 ? Encoding.Unicode : Encoding.ASCII); string header = streamReader.ReadLine(); List<string> headerSplit = SplitLine(header); if (headerSplit == null || headerSplit.Count != 6 || headerSplit[0] != "ID" || headerSplit[1] != "Group" || headerSplit[2] != "Status" || headerSplit[3] != "Speaker" || headerSplit[4] != "Text" || headerSplit[5] != "File name") { Debug.LogWarning("EasyVoice.ImportData opened the CSV the file, but the header syntax did not match the expected format!"); return ImportResult.fail; } List<int> tempIds = new List<int>(); List<string> tempGroups = new List<string>(); List<byte> tempStatuses = new List<byte>(); List<string> tempSpeakerNames = new List<string>(); List<string> tempSpeechTexts = new List<string>(); List<string> tempFileNames = new List<string>(); List<LineIssue> tempIssues = new List<LineIssue>(); while (!streamReader.EndOfStream) { string line = streamReader.ReadLine(); List<string> splitLine = SplitLine(line); //Debug.Log(splitLine); if (splitLine != null && splitLine.Count == 6) { int id; if (!int.TryParse(splitLine[0], out id)) { Debug.LogWarning("EasyVoice.ImportData opened the CSV the file, but an encountered id field syntax did not match the expected format!"); return ImportResult.fail; } tempIds.Add(id); tempGroups.Add(splitLine[3]); byte status; if (!byte.TryParse(splitLine[2], out status)) { Debug.LogWarning("EasyVoice.ImportData opened the CSV the file, but an encountered status field syntax did not match the expected format!"); return ImportResult.fail; } tempStatuses.Add(status); tempSpeakerNames.Add(splitLine[3]); tempSpeechTexts.Add(splitLine[4]); tempFileNames.Add(splitLine[5]); tempIssues.Add(0); } else { Debug.LogWarning("EasyVoice.ImportData opened the CSV the file, but an encountered line syntax did not match the expected format!"); return ImportResult.fail; } } streamReader.Close(); fileStream.Close(); if (!append) settings.data.DeleteAllLines(); lastImportStartingLineCount = settings.data.LineCount(); bool defaultFolderValid = settings.IsDefaultFolderValid(); // so we don't check this too many times bool clipFound = false; for (int i = 0; i < tempSpeakerNames.Count; i++) { settings.data.AddNewLine(tempIds[i], tempGroups[i], tempStatuses[i], tempSpeakerNames[i], tempSpeechTexts[i], tempFileNames[i], tempIssues[i]); // If we need to find a clip (haven't found one yet) and also settings are valid to do this check if (!clipFound && defaultFolderValid) { string assetFileName, fullFileName; EasyVoiceClipCreator.GenerateFullFileName(i, out assetFileName, out fullFileName); AudioClip foundClip = (AudioClip)AssetDatabase.LoadAssetAtPath(assetFileName, typeof(AudioClip)); if (foundClip != null) clipFound = true; } } EasyVoiceIssueChecker.CheckAllLineIssues(); // this will get called again after linking clips, but we don't know if user will decide to do this yet return clipFound ? ImportResult.matchingClipsFound : ImportResult.okay; } catch (Exception e) { Debug.LogError("EasyVoice.ImportData encountered an error: " + e); return ImportResult.fail; } }
public void SetInstance() { instance = this; }
public static bool CreateFiles(EasyVoiceSettings settings) { if (CreateFilesPreCheck(settings) != CreateFilesCheckResult.ok) // this duplicates Editor Window UI, btu is quick enough { return(false); } List <int> created = new List <int>(); lastCreatedAssetFileNames.Clear(); // if this is not empty, something wen't wrong? well, we can't fix it anyway without knowing details, and if we know details, we probably already either addressed them or notified the user //List<List<LineIssue>> issues = EasyVoiceIssueChecker.GetLineIssues(settings); List <int> lineIndices = new List <int>(); for (int i = 0; i < settings.data.LineCount(); i++) { if (!settings.data.GetOutputStatus(i)) { continue; } EasyVoiceIssueChecker.CheckLineIssues(i); if (IssuePreventsFileMaking(settings.data.GetIssues(i))) // most overwriting is "okay" { continue; } lineIndices.Add(i); } for (int i = 0; i < lineIndices.Count; i++) { int lineIndex = lineIndices[i]; string assetFileName; // this is Unity internal asset path starting with "Assets\" and including extension string fullFileName; // this is the file name, including the system path and extension GenerateFullFileName(lineIndex, out assetFileName, out fullFileName); #if DEBUG_MESSAGES Debug.Log(assetFileName); #endif settings.querier.AskToMakeFile( settings.data.GetSpeechText(lineIndex), settings.data.GetSpeakerNameOrSelectDefault(lineIndex), fullFileName, settings.osxFileFormat); // Check if the file has the wrong extension if (Path.GetExtension(fullFileName) != settings.querier.FileExtension) { #if DEBUG_MESSAGES Debug.Log("Audio clip file has a different extension than expected (\"" + settings.querier.FileExtension + "\")"); #endif int extensionIndex = fullFileName.LastIndexOf('.'); if (extensionIndex != 0) { string newName = fullFileName.Substring(0, extensionIndex) + settings.querier.FileExtension; File.Move(fullFileName, newName); extensionIndex = assetFileName.LastIndexOf('.'); if (extensionIndex != 0) // just in case asset file name is messed up { assetFileName = assetFileName.Substring(0, extensionIndex) + settings.querier.FileExtension; } #if DEBUG_MESSAGES Debug.Log("Renamed audio clip asset to \"" + newName + "\" and internal asset path to \"" + assetFileName + "\""); #endif } } created.Add(lineIndex); lastCreatedAssetFileNames.Add(assetFileName); settings.data.SetOutputStatus(lineIndex, false); EditorUtility.DisplayProgressBar(EasyVoiceSettings.progressDialogTitle, EasyVoiceSettings.progressDialogText, (i + 1f) / (lineIndices.Count + 1)); } #if UNITY_EDITOR //AssetDatabase.Refresh(); -- using AssetDatabase.ImportAsset instead #endif #if DEBUG_MESSAGES foreach (string lastCreatedAssetFileName in lastCreatedAssetFileNames) { Debug.Log("Asset will be expected for linking: " + lastCreatedAssetFileName); } #endif if (settings.linkClips) { for (int i = 0; i < created.Count; i++) { // Force asset to import AssetDatabase.ImportAsset(lastCreatedAssetFileNames[i], ImportAssetOptions.ForceSynchronousImport); // Get the new asset AudioClip foundClip = (AudioClip)AssetDatabase.LoadAssetAtPath(lastCreatedAssetFileNames[i], typeof(AudioClip)); //if (foundClip != null) //{ // System.Threading.Thread.Sleep(500); // wait a little bit of OS to possibly refresh, then retry // AssetDatabase.ImportAsset(lastCreatedAssetFileNames[i], ImportAssetOptions.ForceSynchronousImport); // foundClip = (AudioClip)AssetDatabase.LoadAssetAtPath(lastCreatedAssetFileNames[i], typeof(AudioClip)); //} if (foundClip != null) { #if DEBUG_MESSAGES Debug.Log("Audio clip to link was found at: " + lastCreatedAssetFileNames[i]); #endif // if (!lastCreatedAssetFileNames[i].EndsWith(settings.querier.FileExtension)) // { //#if DEBUG_MESSAGES // Debug.Log("Audio clip has a different extension than expected (\"" + settings.querier.FileExtension + "\")"); //#endif // int extensionIndex = lastCreatedAssetFileNames[i].LastIndexOf('.'); // if (extensionIndex > 0 && extensionIndex > lastCreatedAssetFileNames[i].Length - 10) // some sanity // { // int slashIndex = lastCreatedAssetFileNames[i].LastIndexOf('/'); // if (slashIndex != -1 && slashIndex < extensionIndex) // some more sanity // { // string newName = lastCreatedAssetFileNames[i].Substring(slashIndex + 1, extensionIndex - slashIndex - 1) + settings.querier.FileExtension; //#if DEBUG_MESSAGES // Debug.Log("Renaming audio clip asset to \"" + newName + "\""); //#endif // Debug.Log(AssetDatabase.RenameAsset(lastCreatedAssetFileNames[i], newName)); -- CAN'T, extension isn't renamed // } // } // } settings.data.SetClip(created[i], foundClip, false); // TODO: VERIFY? } else { Debug.LogWarning("EasyVoice expected an AudioClip asset to be generated at \"" + lastCreatedAssetFileNames[i] + "\", but it wasn't found!"); } } } #if DEBUG_MESSAGES else { Debug.Log("Settings not set to link created clips, skipping."); } #endif lastCreatedAssetFileNames.Clear(); return(true); }
private void FindOrCreateSettings() { #if DEBUG_MESSAGES Debug.Log("Finding or creating settings"); #endif EasyVoiceSettings foundAsset = (EasyVoiceSettings)AssetDatabase.LoadAssetAtPath(EasyVoiceSettings.settingAssetName, typeof(EasyVoiceSettings)); if (foundAsset != null) { #if DEBUG_MESSAGES Debug.Log("Found settings asset"); #endif settings = foundAsset; //settings.Hide(); EditorUtility.SetDirty(settings); } else { settings = ScriptableObject.CreateInstance<EasyVoiceSettings>(); if (settings != null) { //settings.Hide(); AssetDatabase.CreateAsset(settings, EasyVoiceSettings.settingAssetName); #if DEBUG_MESSAGES Debug.Log("Created settings asset"); #endif settings.Initialize(); EditorUtility.SetDirty(settings); } } }
private void OnGUI_SettingsAssetSelection() { EditorGUILayout.HelpBox("EasyVoice could not find or create its settings asset at \"" + EasyVoiceSettings.settingAssetName + "\"!", MessageType.Error); if (GUILayout.Button("Try to find or re-create settings asset")) { FindOrCreateSettings(); } GUILayout.Label("Or assign an existing setting asset from another location -- drop it here:"); EasyVoiceSettings newSettingsAsset = (EasyVoiceSettings)EditorGUILayout.ObjectField(null, typeof(EasyVoiceSettings), false); if (newSettingsAsset != null) { settings = newSettingsAsset; //settings.Hide(); EditorUtility.SetDirty(settings); } GUILayout.Label("Note: If the settings asset is not at \"" + EasyVoiceSettings.settingAssetName + "\", EasyVoice won't find it next run."); }
public override void QueryForVoiceList(EasyVoiceSettings settings) { settings.voiceNames = null; settings.voiceDescriptions = null; settings.voiceGenders = null; settings.voiceAges = null; string fileName = FileName(); if (!File.Exists(fileName)) { return; } Process voiceListRequest = new Process(); //ProcessStartInfo startInfo = new ProcessStartInfo(); //startInfo.FileName = fileName; //startInfo.Arguments = "voiceList"; //startInfo.CreateNoWindow = true; //startInfo.RedirectStandardOutput = true; // we need to capture it //startInfo.RedirectStandardError = true; // we need to capture it //startInfo.UseShellExecute = false; // must be false for redirect output //voiceListRequest.StartInfo = startInfo; voiceListRequest.StartInfo.FileName = fileName; voiceListRequest.StartInfo.Arguments = "voiceList"; voiceListRequest.StartInfo.CreateNoWindow = true; voiceListRequest.StartInfo.RedirectStandardOutput = true; // we need to capture it voiceListRequest.StartInfo.RedirectStandardError = true; // we need to capture it voiceListRequest.StartInfo.UseShellExecute = false; // must be false for redirect output #if DEBUG_MESSAGES Debug.Log("Starting query..."); #endif voiceListRequest.Start(); voiceListRequest.WaitForExit(); if (voiceListRequest.ExitCode == 0) { using (StreamReader streamReader = voiceListRequest.StandardOutput) { string reply = streamReader.ReadLine(); if (reply == "VOICE LIST") { int count = int.Parse(streamReader.ReadLine()); settings.voiceNames = new List <string>(count); settings.voiceDescriptions = new List <string>(count); settings.voiceGenders = new List <string>(count); settings.voiceAges = new List <string>(count); for (int i = 0; i < count; i++) { settings.voiceNames.Add(streamReader.ReadLine()); settings.voiceDescriptions.Add(streamReader.ReadLine()); settings.voiceGenders.Add(streamReader.ReadLine()); settings.voiceAges.Add(streamReader.ReadLine()); #if DEBUG_MESSAGES Debug.Log(settings.voiceNames[settings.voiceNames.Count - 1] + ", " + settings.voiceGenders[settings.voiceNames.Count - 1] + ", " + settings.voiceAges[settings.voiceNames.Count - 1] + " -- " + settings.voiceDescriptions[settings.voiceNames.Count - 1]); #endif } } else if (reply == "ERROR") { Debug.LogError("EasyVoice Windows console returned an error for " + streamReader.ReadLine() + streamReader.ReadLine()); } else { Debug.LogError("Unexpected process output: " + reply + "\r\n" + streamReader.ReadToEnd()); } //string result = streamReader.ReadToEnd(); //Debug.Log(result); } } else { using (StreamReader streamReader = voiceListRequest.StandardError) { string result = streamReader.ReadToEnd(); Debug.LogError("Process error: " + result); } } #if USE_CLOSE voiceListRequest.Close(); #endif }
public abstract void QueryForVoiceList(EasyVoiceSettings settings);