diff --git a/OpenUtau.Core/Classic/ExeResampler.cs b/OpenUtau.Core/Classic/ExeResampler.cs index 1069d30b1..24e97541b 100644 --- a/OpenUtau.Core/Classic/ExeResampler.cs +++ b/OpenUtau.Core/Classic/ExeResampler.cs @@ -1,5 +1,7 @@ using System; +using System.Collections.Generic; using System.IO; +using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading; @@ -34,6 +36,27 @@ public ResamplerManifest LoadManifest() { } } + void FixMoreConfig(string moreConfigPath) { + var lines = new List { }; + if (File.Exists(moreConfigPath)) { + lines = File.ReadAllLines(moreConfigPath).ToList(); + } + for (int i = 0; i < lines.Count; i++) { + if (lines[i].StartsWith("resampler-compatibility")) { + if(lines[i] == "resampler-compatibility on"){ + //moreconfig.txt is correct + return; + } else { + lines[i] = "resampler-compatibility on"; + File.WriteAllLines(moreConfigPath, lines); + return; + } + } + } + lines.Add("resampler-compatibility on"); + File.WriteAllLines(moreConfigPath, lines); + } + public ExeResampler(string filePath, string basePath) { if (File.Exists(filePath)) { FilePath = filePath; @@ -42,6 +65,16 @@ public ExeResampler(string filePath, string basePath) { } //Load Resampler Manifest Manifest = LoadManifest(); + //Make moresampler happy + try{ + if(Path.GetFileNameWithoutExtension(filePath) == "moresampler"){ + //Load moreconfig.txt under the same folder with filePath + var moreConfigPath = Path.Combine(Path.GetDirectoryName(filePath), "moreconfig.txt"); + FixMoreConfig(moreConfigPath); + } + } catch (Exception ex){ + Log.Error($"Failed fixing moreconfig.txt for {filePath}: {ex}"); + } } public float[] DoResampler(ResamplerItem args, ILogger logger) { diff --git a/OpenUtau.Core/DiffSinger/Phonemizers/DiffSingerARPAPlusEnglishPhonemizer.cs b/OpenUtau.Core/DiffSinger/Phonemizers/DiffSingerARPAPlusEnglishPhonemizer.cs new file mode 100644 index 000000000..7332b3bc9 --- /dev/null +++ b/OpenUtau.Core/DiffSinger/Phonemizers/DiffSingerARPAPlusEnglishPhonemizer.cs @@ -0,0 +1,97 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using OpenUtau.Api; +using OpenUtau.Core.G2p; + +namespace OpenUtau.Core.DiffSinger { + [Phonemizer("DiffSinger English+ Phonemizer", "DIFFS EN+", language: "EN", author: "Cadlaxa")] + public class DiffSingerARPAPlusEnglishPhonemizer : DiffSingerG2pPhonemizer + // cadlaxa here, this diffsinger english phonemizer just uses the ARPA+ G2p so arpasing+ and this phonemizer + // have same g2p mechanics such as triggering of glottal stop with ('), manual relaxed consonants + // plus other ds features + { + protected override string GetDictionaryName() => "dsdict-en.yaml"; + protected override string GetLangCode() => "en"; + protected override IG2p LoadBaseG2p() => new ArpabetPlusG2p(); + protected override string[] GetBaseG2pVowels() => new string[] { + "aa", "ae", "ah", "ao", "aw", "ax", "ay", "eh", "er", + "ey","ih", "iy", "ow", "oy","uh", "uw" + }; + protected override string[] GetBaseG2pConsonants() => new string[] { + "b", "ch", "d", "dh", "dr", "dx", "f", "g", "hh", "jh", + "k", "l", "m", "n", "ng", "p", "q", "r", "s", "sh", "t", + "th", "tr", "v", "w", "y", "z", "zh" + }; + public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevNeighbour, Note? nextNeighbour, Note[] prevs) { + + if (notes[0].lyric == "-") { + return MakeSimpleResult("SP"); + } + if (notes[0].lyric == "br") { + return MakeSimpleResult("AP"); + } + if (!partResult.TryGetValue(notes[0].position, out var phonemes)) { + throw new Exception("Result not found in the part"); + } + var processedPhonemes = new List(); + + for (int i = 0; i < phonemes.Count; i++) { + var tu = phonemes[i]; + + // Check for "n dx" sequence and replace it with "n" + // the actual phoneme for this is "nx" like (winner [w ih nx er]) + if (i < phonemes.Count - 1 && tu.Item1 == "n" && phonemes[i + 1].Item1 == "dx") { + processedPhonemes.Add(new Phoneme() { + phoneme = "n", + position = tu.Item2 + }); + // Skip the next phoneme ("dx") + i++; + } else if (ShouldReplacePhoneme(tu.Item1, prev, next, prevNeighbour, nextNeighbour, out string replacement)) { + processedPhonemes.Add(new Phoneme() { + phoneme = replacement, + position = tu.Item2 + }); + } else { + processedPhonemes.Add(new Phoneme() { + phoneme = tu.Item1, + position = tu.Item2 + }); + } + } + return new Result { + phonemes = processedPhonemes.ToArray() + }; + } + + // Method to determine if a phoneme should be replaced based on specific conditions + private bool ShouldReplacePhoneme(string phoneme, Note? prev, Note? next, Note? prevNeighbour, Note? nextNeighbour, out string replacement) { + replacement = phoneme; + if (phoneme == "q") { + replacement = "cl"; + return true; + } + if (phoneme == "q") { + // vocal fry the vowel is the prevNeighbour is null + if (!prevNeighbour.HasValue || string.IsNullOrWhiteSpace(prevNeighbour.Value.lyric)) { + replacement = "vf"; + return true; + } + } + // automatic relaxed consonants + if ((phoneme == "t" || phoneme == "d") && (nextNeighbour.HasValue && IsVowel(nextNeighbour.Value))) { + replacement = "dx"; + return true; + } + return false; + } + // Method to check if a phoneme is a vowel + private bool IsVowel(Note note) { + string[] vowels = GetBaseG2pVowels(); + return vowels.Contains(note.lyric); + } + } +} diff --git a/OpenUtau.Core/Voicevox/Phonemizers/SimpleVoicevoxPhonemizer.cs b/OpenUtau.Core/Voicevox/Phonemizers/SimpleVoicevoxPhonemizer.cs index dffbabe70..f2be32bb8 100644 --- a/OpenUtau.Core/Voicevox/Phonemizers/SimpleVoicevoxPhonemizer.cs +++ b/OpenUtau.Core/Voicevox/Phonemizers/SimpleVoicevoxPhonemizer.cs @@ -7,7 +7,7 @@ namespace Voicevox { [Phonemizer("Simple Voicevox Japanese Phonemizer", "S-VOICEVOX JA", language: "JA")] public class SimpleVoicevoxPhonemizer : Phonemizer { - protected VoicevoxSinger singer; + protected VoicevoxSinger singer; public override void SetSinger(USinger singer) { this.singer = singer as VoicevoxSinger; @@ -33,14 +33,12 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN } if (!IsSyllableVowelExtensionNote(notes[i])) { string val = "error"; - if (VoicevoxUtils.phoneme_List.kanas.ContainsKey(notes[i].lyric) || VoicevoxUtils.phoneme_List.paus.ContainsKey(notes[i].lyric)) { - if (VoicevoxUtils.phoneme_List.paus.TryGetValue(notes[i].lyric, out string str)) { - val = str; - } else if (VoicevoxUtils.dic.IsDic(notes[i].lyric)) { - val = VoicevoxUtils.dic.Lyrictodic(notes[i].lyric); - } else { - val = notes[i].lyric; - } + if (VoicevoxUtils.phoneme_List.paus.TryGetValue(notes[i].lyric, out string pau)) { + val = pau; + } else if (VoicevoxUtils.phoneme_List.kanas.ContainsKey(notes[i].lyric)) { + val = notes[i].lyric; + } else if (VoicevoxUtils.dic.IsDic(notes[i].lyric)) { + val = VoicevoxUtils.dic.Lyrictodic(notes[i].lyric); } phonemes.Add(new Phoneme { phoneme = val }); } diff --git a/OpenUtau.Core/Voicevox/VoicevoxRenderer.cs b/OpenUtau.Core/Voicevox/VoicevoxRenderer.cs index 71e7d98e1..dc92c9232 100644 --- a/OpenUtau.Core/Voicevox/VoicevoxRenderer.cs +++ b/OpenUtau.Core/Voicevox/VoicevoxRenderer.cs @@ -66,7 +66,9 @@ public Task Render(RenderPhrase phrase, Progress progress, int tra if (!File.Exists(wavPath)) { var singer = phrase.singer as VoicevoxSinger; if (singer != null) { - VoicevoxUtils.Loaddic(singer); + if (VoicevoxUtils.dic == null) { + VoicevoxUtils.Loaddic(singer); + } try { Log.Information($"Starting Voicevox synthesis"); VoicevoxNote vvNotes = new VoicevoxNote(); diff --git a/OpenUtau.Plugin.Builtin/ArpasingPlusPhonemizer.cs b/OpenUtau.Plugin.Builtin/ArpasingPlusPhonemizer.cs index 03dbe4880..92284ed49 100644 --- a/OpenUtau.Plugin.Builtin/ArpasingPlusPhonemizer.cs +++ b/OpenUtau.Plugin.Builtin/ArpasingPlusPhonemizer.cs @@ -1743,15 +1743,15 @@ protected override double GetTransitionBasicLengthMs(string alias = "") { var numbers = new List { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; foreach (var c in longConsonants) { - if (alias.Contains(c) && !alias.Contains("ng -")) { - return base.GetTransitionBasicLengthMs() * 2.6; + if (alias.Contains(c) && !alias.StartsWith(c) && !alias.Contains($"{c} -")) { + return base.GetTransitionBasicLengthMs() * 2.5; } } - + foreach (var c in normalConsonants) { foreach (var v in normalConsonants.Except(GlideVCCons)) { foreach (var b in normalConsonants.Except(NormVCCons)) { - if (alias.Contains(c) && + if (alias.Contains(c) && !alias.StartsWith(c) && !alias.Contains("dx") && !alias.Contains($"{c} -")) { if ("b,d,g,k,p,t".Split(',').Contains(c)) { hasCons = true; @@ -1770,7 +1770,7 @@ protected override double GetTransitionBasicLengthMs(string alias = "") { if (alias.Contains(c) && !alias.Contains("- ") && alias.Contains($"{v} {c}") && !alias.Contains("dx")) { return base.GetTransitionBasicLengthMs() * 2.0; - } + } } } @@ -1783,7 +1783,7 @@ protected override double GetTransitionBasicLengthMs(string alias = "") { } foreach (var c in affricates) { - if (alias.Contains(c)) { + if (alias.Contains(c) && !alias.StartsWith(c)) { return base.GetTransitionBasicLengthMs() * 1.5; } } @@ -1791,7 +1791,7 @@ protected override double GetTransitionBasicLengthMs(string alias = "") { foreach (var c in connectingGlides) { foreach (var v in vowels.Except(excludedVowels)) { if (alias.Contains($"{v} {c}") && !alias.Contains($"{c} -") && !alias.Contains($"{v} -")) { - return base.GetTransitionBasicLengthMs() * 2.3; + return base.GetTransitionBasicLengthMs() * 2.2; } } } @@ -1807,7 +1807,7 @@ protected override double GetTransitionBasicLengthMs(string alias = "") { foreach (var c in semilongConsonants) { foreach (var v in semilongConsonants.Except(excludedEndings)) { - if (alias.Contains(c) && !alias.Contains($"{c} -") && !alias.Contains($"- q")) { + if (alias.Contains(c) && !alias.StartsWith(c) && !alias.Contains($"{c} -") && !alias.Contains($"- q")) { return base.GetTransitionBasicLengthMs() * 1.5; } } @@ -1815,8 +1815,8 @@ protected override double GetTransitionBasicLengthMs(string alias = "") { foreach (var c in semiVowels) { foreach (var v in semilongConsonants.Except(excludedEndings)) { - if (alias.Contains(c) && !alias.Contains($"{c} -")) { - return base.GetTransitionBasicLengthMs() * 1.6; + if (alias.Contains(c) && !alias.StartsWith(c) && !alias.Contains($"{c} -")) { + return base.GetTransitionBasicLengthMs() * 1.5; } } } @@ -1824,7 +1824,7 @@ protected override double GetTransitionBasicLengthMs(string alias = "") { if (hasCons) { return base.GetTransitionBasicLengthMs() * 1.3; // Value for 'cons' } else if (haslr) { - return base.GetTransitionBasicLengthMs() * 1.3; // Value for 'cons' + return base.GetTransitionBasicLengthMs() * 1.2; // Value for 'cons' } // Check if the alias ends with a consonant or vowel @@ -1841,7 +1841,7 @@ protected override double GetTransitionBasicLengthMs(string alias = "") { break; } } - + // If the alias ends with a consonant or vowel, return 0.5 ms if (isEndingConsonant || isEndingVowel) { return base.GetTransitionBasicLengthMs() * 0.5; diff --git a/OpenUtau.Plugin.Builtin/SimpleVoicevoxENtoJAPhonemizer.cs b/OpenUtau.Plugin.Builtin/SimpleVoicevoxENtoJAPhonemizer.cs index b2162f266..809ca6508 100644 --- a/OpenUtau.Plugin.Builtin/SimpleVoicevoxENtoJAPhonemizer.cs +++ b/OpenUtau.Plugin.Builtin/SimpleVoicevoxENtoJAPhonemizer.cs @@ -359,7 +359,6 @@ protected override List ProcessEnding(Ending ending) { private string ToHiragana(string romaji) { var hiragana = WanaKana.ToHiragana(romaji); - hiragana = hiragana.Replace("ゔ", "ヴ"); return hiragana; } }