Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ZH CVVC] Automatically add syllable ending if present (if next neighbor is null) #973

Merged
merged 6 commits into from
Dec 11, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 102 additions & 5 deletions OpenUtau.Plugin.Builtin/ChineseCVVCPhonemizer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ public class ChineseCVVCPhonemizer : BaseChinesePhonemizer {
private Dictionary<string, string> vowels = new Dictionary<string, string>();
private Dictionary<string, string> consonants = new Dictionary<string, string>();
private USinger singer;

public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevNeighbour, Note? nextNeighbour, Note[] prevNeighbours) {
var lyric = notes[0].lyric;
string consonant = consonants.TryGetValue(lyric, out consonant) ? consonant : lyric;
Expand All @@ -27,13 +26,31 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN
};
var attr0 = notes[0].phonemeAttributes?.FirstOrDefault(attr => attr.index == 0) ?? default;
var attr1 = notes[0].phonemeAttributes?.FirstOrDefault(attr => attr.index == 1) ?? default;
var attr2 = notes[0].phonemeAttributes?.FirstOrDefault(attr => attr.index == 2) ?? default;
if (lyric == "-" || lyric.ToLowerInvariant() == "r") {
if (singer.TryGetMappedOto($"{prevVowel} R", notes[0].tone + attr0.toneShift, attr0.voiceColor, out var oto1)) {
return MakeSimpleResult(oto1.Alias);
}
return MakeSimpleResult($"{prevVowel} R");
}
string currVowel = vowels.TryGetValue(lyric, out currVowel) ? currVowel : lyric;
int totalDuration = notes.Sum(n => n.duration); // totalDuration of current note

if (singer.TryGetMappedOto($"{prevVowel} {lyric}", notes[0].tone + attr0.toneShift, attr0.voiceColor, out var oto)) {
if (nextNeighbour == null && singer.TryGetMappedOto($"{currVowel} R", notes[0].tone + attr1.toneShift, attr1.voiceColor, out var oto1)) {
// automatically add ending if present
return new Result {
phonemes = new Phoneme[] {
new Phoneme() {
phoneme = oto.Alias,
},
new Phoneme() {
phoneme = oto1.Alias,
position = totalDuration - (totalDuration / 6),
},
},
};
}
return MakeSimpleResult(oto.Alias);
}
int vcLen = 120;
Expand All @@ -46,15 +63,20 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN
vcLen = MsToTick(cvOto.Preutter - cvOto.Overlap);
}
}

if (singer.TryGetMappedOto(lyric, notes[0].tone + attr0.toneShift, attr0.voiceColor, out var cvOtoSimple)) {
lyric = cvOtoSimple.Alias;
}

var vcPhoneme = $"{prevVowel} {consonant}";
if (prevNeighbour != null) {
if (singer.TryGetMappedOto(vcPhoneme, prevNeighbour.Value.tone + attr0.toneShift, attr0.voiceColor, out oto)) {
vcPhoneme = oto.Alias;
}
// totalDuration calculated on basis of previous note length
int totalDuration = prevNeighbour.Value.duration;
// prevDuration calculated on basis of previous note length
int prevDuration = prevNeighbour.Value.duration;
// vcLength depends on the Vel of the current base note
vcLen = Convert.ToInt32(Math.Min(totalDuration / 1.5, Math.Max(30, vcLen * (attr1.consonantStretchRatio ?? 1))));
vcLen = Convert.ToInt32(Math.Min(prevDuration / 1.5, Math.Max(30, vcLen * (attr1.consonantStretchRatio ?? 1))));
} else {
if (singer.TryGetMappedOto(vcPhoneme, notes[0].tone + attr0.toneShift, attr0.voiceColor, out oto)) {
vcPhoneme = oto.Alias;
Expand All @@ -63,6 +85,81 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN
vcLen = Convert.ToInt32(Math.Min(vcLen * 2, Math.Max(30, vcLen * (attr1.consonantStretchRatio ?? 1))));
}

if (nextNeighbour == null) { // automatically add ending if present
if (singer.TryGetMappedOto($"{prevVowel} {lyric}", notes[0].tone + attr0.toneShift, attr0.voiceColor, out var oto0)) {
if (singer.TryGetMappedOto($"{currVowel} R", notes[0].tone + attr1.toneShift, attr1.voiceColor, out var otoEnd)) {
// automatically add ending if present
return new Result {
phonemes = new Phoneme[] {
new Phoneme() {
phoneme = oto0.Alias,
},
new Phoneme() {
phoneme = otoEnd.Alias,
position = totalDuration - (totalDuration / 6),
},
},
};
}
} else {
// use vc if present
if (prevNeighbour == null && singer.TryGetMappedOto(vcPhoneme, notes[0].tone + attr0.toneShift, attr0.voiceColor, out var vcOto1)) {
vcPhoneme = vcOto1.Alias;
// automatically add ending if present
if (singer.TryGetMappedOto($"{currVowel} R", notes[0].tone + attr2.toneShift, attr2.voiceColor, out var otoEnd)) {
return new Result {
phonemes = new Phoneme[] {
new Phoneme() {
phoneme = vcPhoneme,
position = -vcLen,
},
new Phoneme() {
phoneme = cvOto?.Alias ?? lyric,
},
new Phoneme() {
phoneme = otoEnd.Alias,
position = totalDuration - (totalDuration / 6),
},
},
};
}
} else if (prevNeighbour != null && singer.TryGetMappedOto(vcPhoneme, prevNeighbour.Value.tone + attr0.toneShift, attr0.voiceColor, out var vcOto2)) {
vcPhoneme = vcOto2.Alias;
// automatically add ending if present
if (singer.TryGetMappedOto($"{currVowel} R", notes[0].tone + attr2.toneShift, attr2.voiceColor, out var otoEnd)) {
return new Result {
phonemes = new Phoneme[] {
new Phoneme() {
phoneme = vcPhoneme,
position = -vcLen,
},
new Phoneme() {
phoneme = cvOto?.Alias ?? lyric,
},
new Phoneme() {
phoneme = otoEnd.Alias,
position = totalDuration - (totalDuration / 6),
},
},
};
}
} // just base note and ending
if (singer.TryGetMappedOto($"{currVowel} R", notes[0].tone + attr1.toneShift, attr1.voiceColor, out var otoEnd1)) {
return new Result {
phonemes = new Phoneme[] {
new Phoneme() {
phoneme = cvOtoSimple?.Alias ?? lyric,
},
new Phoneme() {
phoneme = otoEnd1.Alias,
position = totalDuration - (totalDuration / 6),
},
},
};
}
}
}

if (singer.TryGetMappedOto(vcPhoneme, notes[0].tone + attr0.toneShift, attr0.voiceColor, out oto)) {
return new Result {
phonemes = new Phoneme[] {
Expand All @@ -76,7 +173,7 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN
},
};
}
return MakeSimpleResult(cvOto?.Alias ?? lyric);
return MakeSimpleResult(cvOtoSimple?.Alias ?? lyric);
}

public override void SetSinger(USinger singer) {
Expand Down