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

[JA various phoemizers] PhoneticHint support and Unicode countermeasures #710

Merged
merged 19 commits into from
May 28, 2023
Merged
Show file tree
Hide file tree
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
45 changes: 28 additions & 17 deletions OpenUtau.Plugin.Builtin/JapaneseCVVCPhonemizer.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using OpenUtau.Api;
Expand Down Expand Up @@ -107,7 +107,9 @@ private bool checkOtoUntilHit(string[] input, Note note, out UOto oto){
var attr1 = note.phonemeAttributes?.FirstOrDefault(attr => attr.index == 1) ?? default;

foreach (string test in input){
if (singer.TryGetMappedOto(test, note.tone + attr0.toneShift, attr0.voiceColor, out oto)){
if (singer.TryGetMappedOto(test + attr0.alternate, note.tone + attr0.toneShift, attr0.voiceColor, out oto)) {
return true;
} else if (singer.TryGetMappedOto(test, note.tone + attr0.toneShift, attr0.voiceColor, out oto)){
return true;
}
}
Expand All @@ -118,24 +120,36 @@ private bool checkOtoUntilHit(string[] input, Note note, out UOto oto){
// can probably be cleaned up more but i have work in the morning. have fun.
public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevNeighbour, Note? nextNeighbour, Note[] prevNeighbours) {
var note = notes[0];
var currentUnicode = ToUnicodeElements(note.lyric);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is ToUnicodeElements() no longer needed? How so?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ToUnicodeElements() was only used to count characters correctly.
However, this approach does not allow が aliases to be called from か+゛.

Using Normalize() to remove surrogate characters, will allow correct character counts while resolving differences in string formatting.

var currentLyric = note.lyric;
var currentLyric = note.lyric.Normalize();
if (!string.IsNullOrEmpty(note.phoneticHint)) {
currentLyric = note.phoneticHint.Normalize();
}
var originalCurrentLyric = currentLyric;
var cfLyric = $"* {currentLyric}";
var attr0 = note.phonemeAttributes?.FirstOrDefault(attr => attr.index == 0) ?? default;
var attr1 = note.phonemeAttributes?.FirstOrDefault(attr => attr.index == 1) ?? default;

if (prevNeighbour == null) {
if (!string.IsNullOrEmpty(note.phoneticHint)) {
string[] tests = new string[] { currentLyric };
// Not convert VCV
if (checkOtoUntilHit(tests, note, out var oto)) {
currentLyric = oto.Alias;
}
} else if (prevNeighbour == null) {
// Use "- V" or "- CV" if present in voicebank
var initial = $"- {currentLyric}";
string[] tests = new string[] {initial, currentLyric};
string[] tests = new string[] { initial, currentLyric };
// try [- XX] before trying plain lyric
if (checkOtoUntilHit(tests, note, out var oto)){
if (checkOtoUntilHit(tests, note, out var oto)) {
currentLyric = oto.Alias;
}
} else if (plainVowels.Contains(currentLyric) || nonVowels.Contains(currentLyric)) {
var prevUnicode = ToUnicodeElements(prevNeighbour?.lyric);
var prevLyric = prevNeighbour.Value.lyric.Normalize();
if (!string.IsNullOrEmpty(prevNeighbour.Value.phoneticHint)) {
prevLyric = prevNeighbour.Value.phoneticHint.Normalize();
}
// Current note is VV
if (vowelLookup.TryGetValue(prevUnicode.LastOrDefault() ?? string.Empty, out var vow)) {
if (vowelLookup.TryGetValue(prevLyric.LastOrDefault().ToString() ?? string.Empty, out var vow)) {
var vowLyric = $"{vow} {currentLyric}";
// try vowlyric before cflyric, if both fail try currentlyric
string[] tests = new string[] {vowLyric, cfLyric, currentLyric};
Expand All @@ -150,13 +164,11 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN
}
}

if (nextNeighbour != null) {

var nextUnicode = ToUnicodeElements(nextNeighbour?.lyric);
var nextLyric = string.Join("", nextUnicode);
if (nextNeighbour != null && string.IsNullOrEmpty(nextNeighbour.Value.phoneticHint)) {
var nextLyric = nextNeighbour.Value.lyric.Normalize();

// Check if next note is a vowel and does not require VC
if (nextUnicode.Count < 2 && plainVowels.Contains(nextUnicode.FirstOrDefault() ?? string.Empty)) {
if (nextLyric.Length == 1 && plainVowels.Contains(nextLyric)) {
return new Result {
phonemes = new Phoneme[] {
new Phoneme() {
Expand All @@ -169,14 +181,13 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN
// Insert VC before next neighbor
// Get vowel from current note
var vowel = "";
if (vowelLookup.TryGetValue(currentUnicode.LastOrDefault() ?? string.Empty, out var vow)) {
if (vowelLookup.TryGetValue(originalCurrentLyric.LastOrDefault().ToString() ?? string.Empty, out var vow)) {
vowel = vow;
}

// Get consonant from next note
var consonant = "";
if (consonantLookup.TryGetValue(nextUnicode.FirstOrDefault() ?? string.Empty, out var con)
|| nextUnicode.Count >= 2 && consonantLookup.TryGetValue(string.Join("", nextUnicode.Take(2)), out con)) {
if (consonantLookup.TryGetValue(nextLyric.FirstOrDefault().ToString() ?? string.Empty, out var con) || (nextLyric.Length >= 2 && consonantLookup.TryGetValue(nextLyric.Substring(0, 2), out con))) {
consonant = con;
}

Expand Down
Loading