Skip to content

Commit dee22f5

Browse files
authored
Merge branch 'stakira:master' into master
2 parents 5d3a56b + d97ec8c commit dee22f5

32 files changed

+489
-147
lines changed

OpenUtau.Core/BaseChinesePhonemizer.cs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
using System.Collections.Generic;
22
using System.Linq;
3-
using IKg2p;
43
using OpenUtau.Api;
54
using OpenUtau.Core.Ustx;
5+
using Pinyin;
66

77
namespace OpenUtau.Core {
88
public abstract class BaseChinesePhonemizer : Phonemizer {
@@ -22,16 +22,15 @@ public static Note[] ChangeLyric(Note[] group, string lyric) {
2222
public static string[] Romanize(IEnumerable<string> lyrics) {
2323
var lyricsArray = lyrics.ToArray();
2424
var hanziLyrics = lyricsArray
25-
.Where(ZhG2p.MandarinInstance.IsHanzi)
25+
.Where(Pinyin.Pinyin.Instance.IsHanzi)
2626
.ToList();
27-
List<G2pRes> g2pResults = ZhG2p.MandarinInstance.Convert(hanziLyrics.ToList(), false, false);
28-
var pinyinResult = g2pResults.Select(res => res.syllable).ToArray();
27+
var pinyinResult = Pinyin.Pinyin.Instance.HanziToPinyin(hanziLyrics, ManTone.Style.NORMAL, Pinyin.Error.Default, false, false, false).ToStrList();
2928
if (pinyinResult == null) {
3029
return lyricsArray;
3130
}
3231
var pinyinIndex = 0;
3332
for (int i = 0; i < lyricsArray.Length; i++) {
34-
if (lyricsArray[i].Length == 1 && ZhG2p.MandarinInstance.IsHanzi(lyricsArray[i])) {
33+
if (lyricsArray[i].Length == 1 && Pinyin.Pinyin.Instance.IsHanzi(lyricsArray[i])) {
3534
lyricsArray[i] = pinyinResult[pinyinIndex];
3635
pinyinIndex++;
3736
}

OpenUtau.Core/Classic/ExeResampler.cs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
using System;
2+
using System.Collections.Generic;
23
using System.IO;
4+
using System.Linq;
35
using System.Runtime.InteropServices;
46
using System.Text;
57
using System.Threading;
@@ -34,6 +36,27 @@ public ResamplerManifest LoadManifest() {
3436
}
3537
}
3638

39+
void FixMoreConfig(string moreConfigPath) {
40+
var lines = new List<string> { };
41+
if (File.Exists(moreConfigPath)) {
42+
lines = File.ReadAllLines(moreConfigPath).ToList();
43+
}
44+
for (int i = 0; i < lines.Count; i++) {
45+
if (lines[i].StartsWith("resampler-compatibility")) {
46+
if(lines[i] == "resampler-compatibility on"){
47+
//moreconfig.txt is correct
48+
return;
49+
} else {
50+
lines[i] = "resampler-compatibility on";
51+
File.WriteAllLines(moreConfigPath, lines);
52+
return;
53+
}
54+
}
55+
}
56+
lines.Add("resampler-compatibility on");
57+
File.WriteAllLines(moreConfigPath, lines);
58+
}
59+
3760
public ExeResampler(string filePath, string basePath) {
3861
if (File.Exists(filePath)) {
3962
FilePath = filePath;
@@ -42,6 +65,16 @@ public ExeResampler(string filePath, string basePath) {
4265
}
4366
//Load Resampler Manifest
4467
Manifest = LoadManifest();
68+
//Make moresampler happy
69+
try{
70+
if(Path.GetFileNameWithoutExtension(filePath) == "moresampler"){
71+
//Load moreconfig.txt under the same folder with filePath
72+
var moreConfigPath = Path.Combine(Path.GetDirectoryName(filePath), "moreconfig.txt");
73+
FixMoreConfig(moreConfigPath);
74+
}
75+
} catch (Exception ex){
76+
Log.Error($"Failed fixing moreconfig.txt for {filePath}: {ex}");
77+
}
4578
}
4679

4780
public float[] DoResampler(ResamplerItem args, ILogger logger) {
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.IO;
4+
using System.Linq;
5+
using System.Text;
6+
using OpenUtau.Api;
7+
using OpenUtau.Core.G2p;
8+
9+
namespace OpenUtau.Core.DiffSinger {
10+
[Phonemizer("DiffSinger English+ Phonemizer", "DIFFS EN+", language: "EN", author: "Cadlaxa")]
11+
public class DiffSingerARPAPlusEnglishPhonemizer : DiffSingerG2pPhonemizer
12+
// cadlaxa here, this diffsinger english phonemizer just uses the ARPA+ G2p so arpasing+ and this phonemizer
13+
// have same g2p mechanics such as triggering of glottal stop with ('), manual relaxed consonants
14+
// plus other ds features
15+
{
16+
protected override string GetDictionaryName() => "dsdict-en.yaml";
17+
protected override string GetLangCode() => "en";
18+
protected override IG2p LoadBaseG2p() => new ArpabetPlusG2p();
19+
protected override string[] GetBaseG2pVowels() => new string[] {
20+
"aa", "ae", "ah", "ao", "aw", "ax", "ay", "eh", "er",
21+
"ey","ih", "iy", "ow", "oy","uh", "uw"
22+
};
23+
protected override string[] GetBaseG2pConsonants() => new string[] {
24+
"b", "ch", "d", "dh", "dr", "dx", "f", "g", "hh", "jh",
25+
"k", "l", "m", "n", "ng", "p", "q", "r", "s", "sh", "t",
26+
"th", "tr", "v", "w", "y", "z", "zh"
27+
};
28+
public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevNeighbour, Note? nextNeighbour, Note[] prevs) {
29+
30+
if (notes[0].lyric == "-") {
31+
return MakeSimpleResult("SP");
32+
}
33+
if (notes[0].lyric == "br") {
34+
return MakeSimpleResult("AP");
35+
}
36+
if (!partResult.TryGetValue(notes[0].position, out var phonemes)) {
37+
throw new Exception("Result not found in the part");
38+
}
39+
var processedPhonemes = new List<Phoneme>();
40+
41+
for (int i = 0; i < phonemes.Count; i++) {
42+
var tu = phonemes[i];
43+
44+
// Check for "n dx" sequence and replace it with "n"
45+
// the actual phoneme for this is "nx" like (winner [w ih nx er])
46+
if (i < phonemes.Count - 1 && tu.Item1 == "n" && phonemes[i + 1].Item1 == "dx") {
47+
processedPhonemes.Add(new Phoneme() {
48+
phoneme = "n",
49+
position = tu.Item2
50+
});
51+
// Skip the next phoneme ("dx")
52+
i++;
53+
} else if (ShouldReplacePhoneme(tu.Item1, prev, next, prevNeighbour, nextNeighbour, out string replacement)) {
54+
processedPhonemes.Add(new Phoneme() {
55+
phoneme = replacement,
56+
position = tu.Item2
57+
});
58+
} else {
59+
processedPhonemes.Add(new Phoneme() {
60+
phoneme = tu.Item1,
61+
position = tu.Item2
62+
});
63+
}
64+
}
65+
return new Result {
66+
phonemes = processedPhonemes.ToArray()
67+
};
68+
}
69+
70+
// Method to determine if a phoneme should be replaced based on specific conditions
71+
private bool ShouldReplacePhoneme(string phoneme, Note? prev, Note? next, Note? prevNeighbour, Note? nextNeighbour, out string replacement) {
72+
replacement = phoneme;
73+
if (phoneme == "q") {
74+
replacement = "cl";
75+
return true;
76+
}
77+
if (phoneme == "q") {
78+
// vocal fry the vowel is the prevNeighbour is null
79+
if (!prevNeighbour.HasValue || string.IsNullOrWhiteSpace(prevNeighbour.Value.lyric)) {
80+
replacement = "vf";
81+
return true;
82+
}
83+
}
84+
// automatic relaxed consonants
85+
if ((phoneme == "t" || phoneme == "d") && (nextNeighbour.HasValue && IsVowel(nextNeighbour.Value))) {
86+
replacement = "dx";
87+
return true;
88+
}
89+
return false;
90+
}
91+
// Method to check if a phoneme is a vowel
92+
private bool IsVowel(Note note) {
93+
string[] vowels = GetBaseG2pVowels();
94+
return vowels.Contains(note.lyric);
95+
}
96+
}
97+
}
Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
11
using System.Collections.Generic;
22
using System.Linq;
3-
using IKg2p;
43
using OpenUtau.Api;
4+
using Pinyin;
55

66
namespace OpenUtau.Core.DiffSinger {
77
[Phonemizer("DiffSinger Jyutping Phonemizer", "DIFFS ZH-YUE", language: "ZH-YUE")]
88
public class DiffSingerJyutpingPhonemizer : DiffSingerBasePhonemizer {
99
protected override string GetDictionaryName() => "dsdict-zh-yue.yaml";
10-
protected override string GetLangCode()=>"yue";
10+
protected override string GetLangCode() => "yue";
1111
protected override string[] Romanize(IEnumerable<string> lyrics) {
12-
List<G2pRes> g2pResults = ZhG2p.CantoneseInstance.Convert(lyrics.ToList(), false, false);
13-
return g2pResults.Select(res => res.syllable).ToArray();
12+
return Pinyin.Jyutping.Instance.HanziToPinyin(lyrics.ToList(), CanTone.Style.NORMAL, Pinyin.Error.Default).Select(res => res.pinyin).ToArray();
1413
}
1514
}
1615
}

OpenUtau.Core/Enunu/EnunuClient.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,19 @@
77
namespace OpenUtau.Core.Enunu {
88
class EnunuClient : Util.SingletonBase<EnunuClient> {
99
internal T SendRequest<T>(string[] args) {
10+
return SendRequest<T>(args, "15555");
11+
}
12+
internal T SendRequest<T>(string[] args, string port,int second = 300 ) {
1013
using (var client = new RequestSocket()) {
11-
client.Connect("tcp://localhost:15555");
14+
client.Connect($"tcp://localhost:{port}");
1215
string request = JsonConvert.SerializeObject(args);
1316
Log.Information($"EnunuProcess sending {request}");
1417
client.SendFrame(request);
15-
client.TryReceiveFrameString(TimeSpan.FromSeconds(300), out string? message);
18+
client.TryReceiveFrameString(TimeSpan.FromSeconds(second), out string? message);
1619
Log.Information($"EnunuProcess received {message}");
20+
if (string.IsNullOrEmpty(message)) {
21+
return (T)Activator.CreateInstance(typeof(T))!;
22+
}
1723
return JsonConvert.DeserializeObject<T>(message ?? string.Empty)!;
1824
}
1925
}

OpenUtau.Core/Enunu/EnunuConfig.cs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,11 @@
44

55
namespace OpenUtau.Core.Enunu {
66
class EnunuConfig {
7-
public string tablePath;
8-
public string questionPath;
7+
public string enunu_type = string.Empty;
8+
9+
public string feature_type = string.Empty;
10+
public string tablePath = string.Empty;
11+
public string questionPath = string.Empty;
912
public int sampleRate;
1013
public double framePeriod;
1114
public EnunuExtensions extensions;
@@ -16,8 +19,10 @@ public static EnunuConfig Load(USinger singer) {
1619
if (File.Exists(configPath)) {
1720
var configTxt = File.ReadAllText(configPath);
1821
config = Yaml.DefaultDeserializer.Deserialize<RawEnunuConfig>(configTxt);
22+
config.enunu_type = "ENUNU";
1923
} else {
2024
config = SetSimpleENUNUConfig(singer.Location);
25+
config.enunu_type = "SimpleENUNU";
2126
}
2227
return config.Convert();
2328
}
@@ -70,14 +75,19 @@ class RawEnunuExtensions {
7075
}
7176

7277
class RawEnunuConfig {
73-
public string tablePath;
74-
public string questionPath;
78+
public string enunu_type = string.Empty;
79+
public string feature_type = string.Empty;
80+
public string tablePath = string.Empty;
81+
public string questionPath = string.Empty;
7582
public int sampleRate;
7683
public double framePeriod;
7784
public RawEnunuExtensions extensions;
7885

7986
public EnunuConfig Convert() {
8087
EnunuConfig enunuConfig = new EnunuConfig();
88+
enunuConfig.enunu_type = this.enunu_type;
89+
90+
enunuConfig.feature_type = this.feature_type;
8191
enunuConfig.tablePath = this.tablePath;
8292
enunuConfig.questionPath = this.questionPath;
8393
enunuConfig.sampleRate = this.sampleRate;

OpenUtau.Core/Enunu/EnunuEnglishPhonemizer.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ protected IG2p LoadG2p() {
6060
public override void SetSinger(USinger singer) {
6161
this.singer = singer as EnunuSinger;
6262
g2p = LoadG2p();
63+
if (port == null) {
64+
port = EnunuUtils.SetPortNum();
65+
}
6366
}
6467

6568
string[] GetSymbols(Note note) {

OpenUtau.Core/Enunu/EnunuPhonemizer.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ public class EnunuPhonemizer : Phonemizer {
1313
readonly string PhonemizerType = "ENUNU";
1414

1515
protected EnunuSinger singer;
16+
protected string port;
1617
Dictionary<Note[], Phoneme[]> partResult = new Dictionary<Note[], Phoneme[]>();
1718

1819
struct TimingResult {
@@ -27,6 +28,9 @@ struct TimingResponse {
2728

2829
public override void SetSinger(USinger singer) {
2930
this.singer = singer as EnunuSinger;
31+
if (port == null) {
32+
port = EnunuUtils.SetPortNum();
33+
}
3034
}
3135

3236
public override void SetUp(Note[][] notes, UProject project, UTrack track) {
@@ -42,9 +46,10 @@ public override void SetUp(Note[][] notes, UProject project, UTrack track) {
4246
var scorePath = Path.Join(enutmpPath, $"score.lab");
4347
var timingPath = Path.Join(enutmpPath, $"timing.lab");
4448
var enunuNotes = NoteGroupsToEnunu(notes);
49+
var voicebankNameHash = $"{this.singer.voicebankNameHash:x16}";
4550
if (!File.Exists(scorePath) || !File.Exists(timingPath)) {
4651
EnunuUtils.WriteUst(enunuNotes, bpm, singer, ustPath);
47-
var response = EnunuClient.Inst.SendRequest<TimingResponse>(new string[] { "timing", ustPath });
52+
var response = EnunuClient.Inst.SendRequest<TimingResponse>(new string[] { "timing", ustPath,"", voicebankNameHash, "600" }, port);
4853
if (response.error != null) {
4954
throw new Exception(response.error);
5055
}

0 commit comments

Comments
 (0)