diff --git a/OpenUtau.Core/KoreanPhonemizerUtil.cs b/OpenUtau.Core/KoreanPhonemizerUtil.cs index 632d195cd..432d16694 100644 --- a/OpenUtau.Core/KoreanPhonemizerUtil.cs +++ b/OpenUtau.Core/KoreanPhonemizerUtil.cs @@ -8,6 +8,7 @@ using OpenUtau.Classic; using Serilog; using static OpenUtau.Api.Phonemizer; +using OpenUtau.Api; namespace OpenUtau.Core { /// @@ -177,20 +178,20 @@ public static Hashtable Separate(string character) { } /// - /// merges separated hangeul into complete hangeul. (Example: {[0]: "ㄱ", [1]: "ㅏ", [2]: " "} => "가"}) + /// merges separated hangeul into complete hangeul. (Example: {[offset + 0]: "ㄱ", [offset + 1]: "ㅏ", [offset + 2]: " "} => "가"}) /// 자모로 쪼개진 한글을 합쳐진 한글로 반환합니다. /// /// separated Hangeul. /// Returns complete Hangeul Character. - public static string Merge(Hashtable separatedHangeul){ + public static string Merge(Hashtable separatedHangeul, int offset = 0){ int firstConsonantIndex; // (ex) 2 int middleVowelIndex; // (ex) 2 int lastConsonantIndex; // (ex) 21 - char firstConsonant = ((string)separatedHangeul[0])[0]; // (ex) "ㄴ" - char middleVowel = ((string)separatedHangeul[1])[0]; // (ex) "ㅑ" - char lastConsonant = ((string)separatedHangeul[2])[0]; // (ex) "ㅇ" + char firstConsonant = ((string)separatedHangeul[offset + 0])[0]; // (ex) "ㄴ" + char middleVowel = ((string)separatedHangeul[offset + 1])[0]; // (ex) "ㅑ" + char lastConsonant = ((string)separatedHangeul[offset + 2])[0]; // (ex) "ㅇ" if (firstConsonant == ' ') {firstConsonant = 'ㅇ';} @@ -371,7 +372,7 @@ private static Hashtable Variate(Hashtable firstCharSeparated, Hashtable nextCha nextFirstConsonant = "ㅇ"; } - if ((!firstLastConsonant.Equals("")) && nextFirstConsonant.Equals("ㅇ") && (!firstLastConsonant.Equals("ㅇ"))) { + if ((!firstLastConsonant.Equals(" ")) && nextFirstConsonant.Equals("ㅇ") && (!firstLastConsonant.Equals("ㅇ"))) { // 연음 2 nextFirstConsonant = firstLastConsonant; firstLastConsonant = " "; @@ -919,10 +920,7 @@ public static String Variate(String? prevNeighbour, String note, String? nextNei result.Add(7, thisNoteSeparated[4]); result.Add(8, thisNoteSeparated[5]); - return Merge(new Hashtable{ - [0] = (string)result[3], - [1] = (string)result[4], - [2] = (string)result[5]}); + return Merge(result, 3); } } else if ((lyrics[0] != null) && (lyrics[2] == null)) { @@ -941,10 +939,7 @@ public static String Variate(String? prevNeighbour, String note, String? nextNei result.Add(7, "null"); result.Add(8, "null"); - return Merge(new Hashtable{ - [0] = (string)result[3], - [1] = (string)result[4], - [2] = (string)result[5]}); + return Merge(result, 3); } else if (whereYeonEum == 0) { // 앞 노트에서 단어가 끝났다고 가정 @@ -959,10 +954,7 @@ public static String Variate(String? prevNeighbour, String note, String? nextNei result.Add(7, "null"); result.Add(8, "null"); - return Merge(new Hashtable{ - [0] = (string)result[3], - [1] = (string)result[4], - [2] = (string)result[5]}); + return Merge(result, 3); } else { Hashtable result = Variate(lyrics[0], lyrics[1], 0); // 첫 글자 @@ -976,10 +968,7 @@ public static String Variate(String? prevNeighbour, String note, String? nextNei result.Add(7, "null"); result.Add(8, "null"); - return Merge(new Hashtable{ - [0] = (string)result[3], - [1] = (string)result[4], - [2] = (string)result[5]}); + return Merge(result, 3); } } else if ((lyrics[0] != null) && (lyrics[2] != null)) { @@ -998,10 +987,7 @@ public static String Variate(String? prevNeighbour, String note, String? nextNei result.Add(7, thisNoteSeparated[4]); result.Add(8, thisNoteSeparated[5]); - return Merge(new Hashtable{ - [0] = (string)result[3], - [1] = (string)result[4], - [2] = (string)result[5]}); + return Merge(result, 3); } else if (whereYeonEum == 0) { // 앞 노트에서 단어가 끝났다고 가정 / 릎. [위] 놓 @@ -1016,10 +1002,7 @@ public static String Variate(String? prevNeighbour, String note, String? nextNei result.Add(7, thisNoteSeparated[4]); result.Add(8, thisNoteSeparated[5]); - return Merge(new Hashtable{ - [0] = (string)result[3], - [1] = (string)result[4], - [2] = (string)result[5]}); + return Merge(result, 3); } else { Hashtable result = Variate(lyrics[0], lyrics[1], 0); @@ -1033,10 +1016,7 @@ public static String Variate(String? prevNeighbour, String note, String? nextNei result.Add(7, thisNoteSeparated[4]); result.Add(8, thisNoteSeparated[5]); - return Merge(new Hashtable{ - [0] = (string)result[3], - [1] = (string)result[4], - [2] = (string)result[5]}); + return Merge(result, 3); } } else { @@ -1060,11 +1040,7 @@ public static String Variate(String? prevNeighbour, String note, String? nextNei result.Add(7, "null"); result.Add(8, "null"); - return Merge(new Hashtable{ - [0] = (string)result[3], - [1] = (string)result[4], - [2] = (string)result[5] - }); + return Merge(result, 3); } } @@ -1081,10 +1057,27 @@ public static Note[] ChangeLyric(Note[] group, string lyric) { }; return group; } - public static void RomanizeNotes(Note[][] groups, Dictionary firstConsonants, Dictionary vowels, Dictionary lastConsonants, string semivowelSeparator=" ") { - // for ENUNU Phonemizer - + + public static void ModifyLyrics(Hashtable lyricSeparated,string lyric, Dictionary firstConsonants, Dictionary vowels, Dictionary lastConsonants, string semivowelSeparator){ + lyric += firstConsonants[(string)lyricSeparated[3]][0]; + if (vowels[(string)lyricSeparated[4]][1] != "") { + // this vowel contains semivowel + lyric += semivowelSeparator + vowels[(string)lyricSeparated[4]][1] + vowels[(string)lyricSeparated[4]][2]; + } + else{ + lyric += " " + vowels[(string)lyricSeparated[4]][2]; + } + + lyric += lastConsonants[(string)lyricSeparated[5]][0]; + } + + public static void RomanizeNotes(Note[][] groups, bool _modifyLyrics = false, Dictionary firstConsonants = null, Dictionary vowels = null, Dictionary lastConsonants = null, string semivowelSeparator = " ") { + // for ENUNU & DIFFS Phonemizer + int noteIdx = 0; + string lyric; + bool modifyLyrics = (!_modifyLyrics || firstConsonants == null || vowels == null || lastConsonants == null) ? false : true; + Note[] currentNote; Note[]? prevNote = null; Note[]? nextNote; @@ -1092,10 +1085,13 @@ public static void RomanizeNotes(Note[][] groups, Dictionary f Note? prevNote_; Note? nextNote_; - List ResultLyrics = new List(); + foreach (Note[] group in groups){ currentNote = groups[noteIdx]; + string originalLyric; // uses this when no variation needed + originalLyric = currentNote[0].lyric; + if (groups.Length > noteIdx + 1 && IsHangeul(groups[noteIdx + 1][0].lyric)) { nextNote = groups[noteIdx + 1]; } @@ -1120,7 +1116,7 @@ public static void RomanizeNotes(Note[][] groups, Dictionary f } else{nextNote_ = null;} - string lyric = ""; + lyric = originalLyric; if (! IsHangeul(currentNote[0].lyric)){ ResultLyrics.Add(currentNote[0].lyric); @@ -1129,27 +1125,27 @@ public static void RomanizeNotes(Note[][] groups, Dictionary f continue; } - Hashtable lyricSeparated = Variate(prevNote_, currentNote[0], nextNote_); - lyric += firstConsonants[(string)lyricSeparated[3]][0]; - if (vowels[(string)lyricSeparated[4]][1] != "") { - // this vowel contains semivowel - lyric += semivowelSeparator + vowels[(string)lyricSeparated[4]][1] + vowels[(string)lyricSeparated[4]][2]; - } - else{ - lyric += " " + vowels[(string)lyricSeparated[4]][2]; - } - - lyric += lastConsonants[(string)lyricSeparated[5]][0]; + + Hashtable lyricSeparated = Variate(prevNote_, currentNote[0], nextNote_); - ResultLyrics.Add(lyric.Trim()); + if (modifyLyrics) { + ModifyLyrics(lyricSeparated, lyric, firstConsonants, vowels, lastConsonants, semivowelSeparator); + } + else { + lyric = Merge(lyricSeparated, 3); + } + + ResultLyrics.Add(lyric.Trim()); - prevNote = currentNote; + prevNote = currentNote; - noteIdx++; + noteIdx++; + } Enumerable.Zip(groups, ResultLyrics.ToArray(), ChangeLyric).Last(); } + /// /// abstract class for Ini Management /// To use, child phonemizer should implement this class(BaseIniManager) with its own setting values!