diff --git a/OpenUtau.Core/Api/Phonemizer.cs b/OpenUtau.Core/Api/Phonemizer.cs
index 6f283c360..d54e6f270 100644
--- a/OpenUtau.Core/Api/Phonemizer.cs
+++ b/OpenUtau.Core/Api/Phonemizer.cs
@@ -86,7 +86,7 @@ public struct PhonemeAttributes {
///
/// Tone shift. Shifts the note tone used for oto lookup.
///
- public int toneShift;
+ public int? toneShift;
///
/// Alternate index. The number suffix of duplicate aliases.
///
@@ -94,7 +94,7 @@ public struct PhonemeAttributes {
///
/// Voice color.
///
- public string voiceColor;
+ public string? voiceColor;
}
public struct PhonemeExpression {
@@ -176,7 +176,13 @@ public struct Result {
///
public virtual bool LegacyMapping => false;
- public virtual void SetUp(Note[][] notes, UProject project, UTrack track) { }
+ public UProject? project;
+ public UTrack? track;
+
+ public virtual void SetUp(Note[][] notes, UProject project, UTrack track) {
+ this.project = project;
+ this.track = track;
+ }
///
/// Phonemize a consecutive sequence of notes. This is the main logic of a phonemizer.
@@ -259,6 +265,44 @@ protected Result MakeSimpleResult(string phoneme) {
};
}
+ public double GetParentConsonantStretchRatio() {
+ if (project != null && track != null) {
+ if (track.TryGetExpDescriptor(project, Core.Format.Ustx.VEL, out var trackVEL)) {
+ return Math.Pow(2, 1.0 - trackVEL.CustomDefaultValue / 100.0);
+ }
+ }
+ return 1;
+ }
+
+ public int GetParentToneShift() {
+ if (project != null && track != null) {
+ if (track.TryGetExpDescriptor(project, Core.Format.Ustx.SHFT, out var trackTS)) {
+ return (int)trackTS.CustomDefaultValue;
+ }
+ }
+ return 0;
+ }
+
+ public int? GetParentAlternate() {
+ if (project != null && track != null) {
+ if (track.TryGetExpDescriptor(project, Core.Format.Ustx.ALT, out var trackAlt)) {
+ if (trackAlt.CustomDefaultValue != 0) {
+ return (int)trackAlt.CustomDefaultValue;
+ }
+ }
+ }
+ return null;
+ }
+
+ public string GetParentVoiceColor() {
+ if (project != null && track != null) {
+ if (track.TryGetExpDescriptor(project, Core.Format.Ustx.CLR, out var trackCLR)) {
+ return track.VoiceColorExp.options[(int)trackCLR.CustomDefaultValue];
+ }
+ }
+ return string.Empty;
+ }
+
///
/// Utility method to map a phoneme alias to proper pitch using prefixmap.
/// For example, MapPhoneme("あ", 72, singer) may return "あC5".
diff --git a/OpenUtau.Core/BaseChinesePhonemizer.cs b/OpenUtau.Core/BaseChinesePhonemizer.cs
index d81c8038e..447e4ca27 100644
--- a/OpenUtau.Core/BaseChinesePhonemizer.cs
+++ b/OpenUtau.Core/BaseChinesePhonemizer.cs
@@ -44,6 +44,7 @@ public static void RomanizeNotes(Note[][] groups) {
}
public override void SetUp(Note[][] groups, UProject project, UTrack track) {
+ base.SetUp(groups, project, track);
RomanizeNotes(groups);
}
}
diff --git a/OpenUtau.Core/DefaultPhonemizer.cs b/OpenUtau.Core/DefaultPhonemizer.cs
index 0eeba399e..2019356be 100644
--- a/OpenUtau.Core/DefaultPhonemizer.cs
+++ b/OpenUtau.Core/DefaultPhonemizer.cs
@@ -16,7 +16,11 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN
// For this simple phonemizer, all these notes maps to a single phoneme.
string alias = notes[0].lyric;
var attr0 = notes[0].phonemeAttributes?.FirstOrDefault(attr => attr.index == 0) ?? default;
- if (singer.TryGetMappedOto(notes[0].lyric, notes[0].tone + attr0.toneShift, attr0.voiceColor, out var oto)) {
+ string color = attr0.voiceColor ?? GetParentVoiceColor();
+ int shift = attr0.toneShift ?? GetParentToneShift();
+ int? alt = attr0.alternate ?? GetParentAlternate();
+
+ if (singer.TryGetMappedOto(notes[0].lyric + alt, notes[0].tone + shift, color, out var oto)) {
alias = oto.Alias;
}
return new Result {
diff --git a/OpenUtau.Core/DiffSinger/Phonemizers/DiffSingerKoreanPhonemizer.cs b/OpenUtau.Core/DiffSinger/Phonemizers/DiffSingerKoreanPhonemizer.cs
index e28cd1d46..98bdb0df7 100644
--- a/OpenUtau.Core/DiffSinger/Phonemizers/DiffSingerKoreanPhonemizer.cs
+++ b/OpenUtau.Core/DiffSinger/Phonemizers/DiffSingerKoreanPhonemizer.cs
@@ -1,4 +1,4 @@
-using OpenUtau.Api;
+using OpenUtau.Api;
using OpenUtau.Core.Ustx;
using System.Collections.Generic;
using System.Linq;
@@ -12,6 +12,7 @@ public class DiffSingerKoreanPhonemizer : DiffSingerBasePhonemizer
public override string GetLangCode()=>"ko";
public override void SetUp(Note[][] groups, UProject project, UTrack track) {
+ base.SetUp(groups, project, track);
if (groups.Length == 0) {
return;
}
diff --git a/OpenUtau.Core/Enunu/EnunuKoreanPhonemizer.cs b/OpenUtau.Core/Enunu/EnunuKoreanPhonemizer.cs
index 3103fea0e..4ae84b95c 100644
--- a/OpenUtau.Core/Enunu/EnunuKoreanPhonemizer.cs
+++ b/OpenUtau.Core/Enunu/EnunuKoreanPhonemizer.cs
@@ -395,6 +395,7 @@ public enum BatchimType{
Dictionary partResult = new Dictionary();
public override void SetUp(Note[][] notes, UProject project, UTrack track) {
+ base.SetUp(notes, project, track);
partResult.Clear();
if (notes.Length == 0 || singer == null || !singer.Found) {
return;
diff --git a/OpenUtau.Core/Enunu/EnunuPhonemizer.cs b/OpenUtau.Core/Enunu/EnunuPhonemizer.cs
index ac818c5fe..ca875afad 100644
--- a/OpenUtau.Core/Enunu/EnunuPhonemizer.cs
+++ b/OpenUtau.Core/Enunu/EnunuPhonemizer.cs
@@ -35,6 +35,7 @@ public override void SetSinger(USinger singer) {
}
public override void SetUp(Note[][] notes, UProject project, UTrack track) {
+ base.SetUp(notes, project, track);
partResult.Clear();
if (notes.Length == 0 || singer == null || !singer.Found) {
return;
@@ -174,4 +175,4 @@ public override void CleanUp() {
partResult.Clear();
}
}
-}
\ No newline at end of file
+}
diff --git a/OpenUtau.Core/MachineLearningPhonemizer.cs b/OpenUtau.Core/MachineLearningPhonemizer.cs
index 2ad4c2d75..519e001be 100644
--- a/OpenUtau.Core/MachineLearningPhonemizer.cs
+++ b/OpenUtau.Core/MachineLearningPhonemizer.cs
@@ -18,6 +18,7 @@ public abstract class MachineLearningPhonemizer : Phonemizer
//groups is a two-dimensional array of Note, each Note[] represents a lyrical note and its following slur notes
//Run phoneme timing model in sections to prevent butterfly effect
public override void SetUp(Note[][] groups, UProject project, UTrack track) {
+ base.SetUp(groups, project, track);
SetUpException = null;
lastProcessPartException = null;
partResult.Clear();
diff --git a/OpenUtau.Core/Ustx/UNote.cs b/OpenUtau.Core/Ustx/UNote.cs
index b873e1850..45af0432c 100644
--- a/OpenUtau.Core/Ustx/UNote.cs
+++ b/OpenUtau.Core/Ustx/UNote.cs
@@ -139,7 +139,7 @@ internal Phonemizer.Note ToPhonemizerNote(UTrack track, UPart part) {
attr.index = exp.index.Value;
if (exp.abbr == Format.Ustx.VEL) {
attr.consonantStretchRatio = Math.Pow(2, 1.0 - exp.value / 100.0);
- } else if (exp.abbr == Format.Ustx.ALT) {
+ } else if (exp.abbr == Format.Ustx.ALT && exp.value != 0) { // 0 means no alt (nothing added)
attr.alternate = (int)exp.value;
} else if (exp.abbr == Format.Ustx.CLR && track.VoiceColorExp != null) {
int optionIdx = (int)exp.value;
diff --git a/OpenUtau.Core/Vogen/VogenBasePhonemizer.cs b/OpenUtau.Core/Vogen/VogenBasePhonemizer.cs
index 747530f9a..9105d93b3 100644
--- a/OpenUtau.Core/Vogen/VogenBasePhonemizer.cs
+++ b/OpenUtau.Core/Vogen/VogenBasePhonemizer.cs
@@ -38,6 +38,7 @@ private void AddGroup(List phrase, Note[] group){
});
}
public override void SetUp(Note[][] groups, UProject project, UTrack track) {
+ base.SetUp(groups, project, track);
if (groups.Length == 0) {
return;
}
diff --git a/OpenUtau.Core/Voicevox/Phonemizers/VoicevoxPhonemizer.cs b/OpenUtau.Core/Voicevox/Phonemizers/VoicevoxPhonemizer.cs
index 2360fd669..3e93f7ab3 100644
--- a/OpenUtau.Core/Voicevox/Phonemizers/VoicevoxPhonemizer.cs
+++ b/OpenUtau.Core/Voicevox/Phonemizers/VoicevoxPhonemizer.cs
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
-using System.IO;
using System.Linq;
using OpenUtau.Api;
using OpenUtau.Core.Ustx;
@@ -17,6 +16,7 @@ public override void SetSinger(USinger singer) {
}
public override void SetUp(Note[][] notes, UProject project, UTrack track) {
+ base.SetUp(notes, project, track);
partResult.Clear();
VoicevoxNote[] vNotes = new VoicevoxNote[notes.Length];
for (int i = 0; i < notes.Length; i++) {
diff --git a/OpenUtau.Plugin.Builtin/BaseKoreanPhonemizer.cs b/OpenUtau.Plugin.Builtin/BaseKoreanPhonemizer.cs
index 029394c33..3eed0c1ea 100644
--- a/OpenUtau.Plugin.Builtin/BaseKoreanPhonemizer.cs
+++ b/OpenUtau.Plugin.Builtin/BaseKoreanPhonemizer.cs
@@ -29,21 +29,18 @@ protected virtual bool additionalTest(string lyric) {
return false;
}
public override void SetSinger(USinger singer) => this.singer = singer;
- public static string? FindInOto(USinger singer, string phoneme, Note note, bool nullIfNotFound = false) {
+ public string? FindInOto(USinger singer, string phoneme, Note note, bool nullIfNotFound = false) {
// 음소와 노트를 입력받고, 다음계 및 보이스컬러 에일리어스를 적용한다.
// nullIfNotFound가 true이면 음소가 찾아지지 않을 때 음소가 아닌 null을 리턴한다.
// nullIfNotFound가 false면 음소가 찾아지지 않을 때 그대로 음소를 반환
string phonemeToReturn;
var attr = note.phonemeAttributes?.FirstOrDefault(attr => attr.index == 0) ?? default;
- string color = attr.voiceColor ?? string.Empty;
- int toneShift = 0;
- int? alt = null;
+ string color = attr.voiceColor ?? GetParentVoiceColor();
+ int toneShift = attr.toneShift ?? GetParentToneShift();
+ int? alt = attr.alternate ?? GetParentAlternate();
if (phoneme.Equals("")) {return phoneme;}
- if (singer.TryGetMappedOto(phoneme + alt, note.tone + toneShift, color, out var otoAlt)) {
- phonemeToReturn = otoAlt.Alias;
- }
- else if (singer.TryGetMappedOto(phoneme, note.tone + toneShift, color, out var oto)) {
+ if (singer.TryGetMappedOto(phoneme + alt, note.tone + toneShift, color, out var oto)) {
phonemeToReturn = oto.Alias;
}
else if (singer.TryGetMappedOto(phoneme, note.tone, color, out oto)) {
diff --git a/OpenUtau.Plugin.Builtin/CantoneseSyoPhonemizer.cs b/OpenUtau.Plugin.Builtin/CantoneseSyoPhonemizer.cs
index dbbbc4d9f..410ac8aee 100644
--- a/OpenUtau.Plugin.Builtin/CantoneseSyoPhonemizer.cs
+++ b/OpenUtau.Plugin.Builtin/CantoneseSyoPhonemizer.cs
@@ -71,6 +71,7 @@ static CantoneseSyoPhonemizer() {
///
///
public override void SetUp(Note[][] groups, UProject project, UTrack track) {
+ base.SetUp(groups, project, track);
JyutpingConversion.RomanizeNotes(groups);
}
public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevNeighbour, Note? nextNeighbour, Note[] prevNeighbours) {
@@ -98,17 +99,6 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN
string phoneme0 = lyric;
- // Get color
- string color = string.Empty;
- int toneShift = 0;
- int? alt = 0;
- if (note.phonemeAttributes != null) {
- var attr = note.phonemeAttributes.FirstOrDefault(attr0 => attr0.index == 0);
- color = attr.voiceColor;
- toneShift = attr.toneShift;
- alt = attr.alternate;
- }
-
string fin = $"{vowel} -";
// We will need to split the total duration for phonemes, so we compute it here.
int totalDuration = notes.Sum(n => n.duration);
@@ -316,17 +306,17 @@ public void SetUp(Note[][] groups) {
private bool checkOtoUntilHit(List input, Note note, out UOto oto) {
oto = default;
var attr = note.phonemeAttributes?.FirstOrDefault(attrCheck => attrCheck.index == 0) ?? default;
+ string color = attr.voiceColor ?? GetParentVoiceColor();
+ int shift = attr.toneShift ?? GetParentToneShift();
+ int? alt = attr.alternate ?? GetParentAlternate();
var otos = new List();
foreach (string test in input) {
- if (singer.TryGetMappedOto(test + attr.alternate, note.tone + attr.toneShift, attr.voiceColor, out var otoAlt)) {
- otos.Add(otoAlt);
- } else if (singer.TryGetMappedOto(test, note.tone + attr.toneShift, attr.voiceColor, out var otoCandidacy)) {
+ if (singer.TryGetMappedOto(test + alt, note.tone + shift, color, out var otoCandidacy)) {
otos.Add(otoCandidacy);
}
}
- string color = attr.voiceColor ?? "";
if (otos.Count > 0) {
oto = otos.FirstOrDefault(oto => oto.IsColorMatch(color));
if (oto == null) {
@@ -341,17 +331,17 @@ private bool checkOtoUntilHit(List input, Note note, out UOto oto) {
private bool checkOtoUntilHitFinal(List input, Note note, out UOto oto) {
oto = default;
var attr = note.phonemeAttributes?.FirstOrDefault(attrCheck => attrCheck.index == 1) ?? default;
+ string color = attr.voiceColor ?? GetParentVoiceColor();
+ int shift = attr.toneShift ?? GetParentToneShift();
+ int? alt = attr.alternate ?? GetParentAlternate();
var otos = new List();
foreach (string test in input) {
- if (singer.TryGetMappedOto(test + attr.alternate, note.tone + attr.toneShift, attr.voiceColor, out var otoAlt)) {
- otos.Add(otoAlt);
- } else if (singer.TryGetMappedOto(test, note.tone + attr.toneShift, attr.voiceColor, out var otoCandidacy)) {
+ if (singer.TryGetMappedOto(test + alt, note.tone + shift, color, out var otoCandidacy)) {
otos.Add(otoCandidacy);
}
}
- string color = attr.voiceColor ?? "";
if (otos.Count > 0) {
oto = otos.FirstOrDefault(oto => oto.IsColorMatch(color));
if (oto != null) {
diff --git a/OpenUtau.Plugin.Builtin/ChineseCVVCPhonemizer.cs b/OpenUtau.Plugin.Builtin/ChineseCVVCPhonemizer.cs
index 431f4b435..f27394a71 100644
--- a/OpenUtau.Plugin.Builtin/ChineseCVVCPhonemizer.cs
+++ b/OpenUtau.Plugin.Builtin/ChineseCVVCPhonemizer.cs
@@ -34,7 +34,7 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN
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)) {
+ if (singer.TryGetMappedOto($"{prevVowel} R", notes[0].tone + (attr0.toneShift ?? GetParentToneShift()), attr0.voiceColor ?? GetParentVoiceColor(), out var oto1)) {
return MakeSimpleResult(oto1.Alias);
}
return MakeSimpleResult($"{prevVowel} R");
@@ -42,8 +42,8 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN
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)) {
+ if (singer.TryGetMappedOto($"{prevVowel} {lyric}", notes[0].tone + (attr0.toneShift ?? GetParentToneShift()), attr0.voiceColor ?? GetParentVoiceColor(), out var oto)) {
+ if (nextNeighbour == null && singer.TryGetMappedOto($"{currVowel} R", notes[0].tone + (attr1.toneShift ?? GetParentToneShift()), attr1.voiceColor ?? GetParentVoiceColor(), out var oto1)) {
// automatically add ending if present
return new Result {
phonemes = new Phoneme[] {
@@ -61,7 +61,7 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN
}
int vcLen = 120;
int endTick = notes[^1].position + notes[^1].duration;
- if (singer.TryGetMappedOto(lyric, notes[0].tone + attr1.toneShift, attr1.voiceColor, out var cvOto)) {
+ if (singer.TryGetMappedOto(lyric, notes[0].tone + (attr1.toneShift ?? GetParentToneShift()), attr1.voiceColor ?? GetParentVoiceColor(), out var cvOto)) {
vcLen = -timeAxis.MsToTickAt(-cvOto.Preutter, endTick);
if (cvOto.Overlap == 0 && vcLen < 120) {
vcLen = Math.Min(120, vcLen * 2); // explosive consonant with short preutter.
@@ -71,30 +71,30 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN
}
}
- if (singer.TryGetMappedOto(lyric, notes[0].tone + attr0.toneShift, attr0.voiceColor, out var cvOtoSimple)) {
+ if (singer.TryGetMappedOto(lyric, notes[0].tone + (attr0.toneShift ?? GetParentToneShift()), attr0.voiceColor ?? GetParentVoiceColor(), 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)) {
+ if (singer.TryGetMappedOto(vcPhoneme, prevNeighbour.Value.tone + (attr0.toneShift ?? GetParentToneShift()), attr0.voiceColor ?? GetParentVoiceColor(), out oto)) {
vcPhoneme = oto.Alias;
}
// prevDuration calculated on basis of previous note length
int prevDuration = notes[0].position - prevNeighbour.Value.position;
// vcLength depends on the Vel of the current base note
- vcLen = Convert.ToInt32(Math.Min(prevDuration / 1.5, Math.Max(30, vcLen * (attr1.consonantStretchRatio ?? 1))));
+ vcLen = Convert.ToInt32(Math.Min(prevDuration / 1.5, Math.Max(30, vcLen * (attr1.consonantStretchRatio ?? GetParentConsonantStretchRatio()))));
} else {
- if (singer.TryGetMappedOto(vcPhoneme, notes[0].tone + attr0.toneShift, attr0.voiceColor, out oto)) {
+ if (singer.TryGetMappedOto(vcPhoneme, notes[0].tone + (attr0.toneShift ?? GetParentToneShift()), attr0.voiceColor ?? GetParentVoiceColor(), out oto)) {
vcPhoneme = oto.Alias;
}
// no previous note, so length can be minimum velocity regardless of oto
- vcLen = Convert.ToInt32(Math.Min(vcLen * 2, Math.Max(30, vcLen * (attr1.consonantStretchRatio ?? 1))));
+ vcLen = Convert.ToInt32(Math.Min(vcLen * 2, Math.Max(30, vcLen * (attr1.consonantStretchRatio ?? GetParentConsonantStretchRatio()))));
}
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)) {
+ if (singer.TryGetMappedOto($"{prevVowel} {lyric}", notes[0].tone + (attr0.toneShift ?? GetParentToneShift()), attr0.voiceColor ?? GetParentVoiceColor(), out var oto0)) {
+ if (singer.TryGetMappedOto($"{currVowel} R", notes[0].tone + (attr1.toneShift ?? GetParentToneShift()), attr1.voiceColor ?? GetParentVoiceColor(), out var otoEnd)) {
// automatically add ending if present
return new Result {
phonemes = new Phoneme[] {
@@ -110,10 +110,10 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN
}
} else {
// use vc if present
- if (prevNeighbour == null && singer.TryGetMappedOto(vcPhoneme, notes[0].tone + attr0.toneShift, attr0.voiceColor, out var vcOto1)) {
+ if (prevNeighbour == null && singer.TryGetMappedOto(vcPhoneme, notes[0].tone + (attr0.toneShift ?? GetParentToneShift()), attr0.voiceColor ?? GetParentVoiceColor(), 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)) {
+ if (singer.TryGetMappedOto($"{currVowel} R", notes[0].tone + (attr2.toneShift ?? GetParentToneShift()), attr2.voiceColor ?? GetParentVoiceColor(), out var otoEnd)) {
return new Result {
phonemes = new Phoneme[] {
new Phoneme() {
@@ -130,10 +130,10 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN
},
};
}
- } else if (prevNeighbour != null && singer.TryGetMappedOto(vcPhoneme, prevNeighbour.Value.tone + attr0.toneShift, attr0.voiceColor, out var vcOto2)) {
+ } else if (prevNeighbour != null && singer.TryGetMappedOto(vcPhoneme, prevNeighbour.Value.tone + (attr0.toneShift ?? GetParentToneShift()), attr0.voiceColor ?? GetParentVoiceColor(), 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)) {
+ if (singer.TryGetMappedOto($"{currVowel} R", notes[0].tone + (attr2.toneShift ?? GetParentToneShift()), attr2.voiceColor ?? GetParentVoiceColor(), out var otoEnd)) {
return new Result {
phonemes = new Phoneme[] {
new Phoneme() {
@@ -151,7 +151,7 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN
};
}
} // just base note and ending
- if (singer.TryGetMappedOto($"{currVowel} R", notes[0].tone + attr1.toneShift, attr1.voiceColor, out var otoEnd1)) {
+ if (singer.TryGetMappedOto($"{currVowel} R", notes[0].tone + (attr1.toneShift ?? GetParentToneShift()), attr1.voiceColor ?? GetParentVoiceColor(), out var otoEnd1)) {
return new Result {
phonemes = new Phoneme[] {
new Phoneme() {
@@ -167,7 +167,7 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN
}
}
- if (singer.TryGetMappedOto(vcPhoneme, notes[0].tone + attr0.toneShift, attr0.voiceColor, out oto)) {
+ if (singer.TryGetMappedOto(vcPhoneme, notes[0].tone + (attr0.toneShift ?? GetParentToneShift()), attr0.voiceColor ?? GetParentVoiceColor(), out oto)) {
return new Result {
phonemes = new Phoneme[] {
new Phoneme() {
@@ -257,7 +257,8 @@ protected void RomanizeNotes(Note[][] groups) {
}
public override void SetUp(Note[][] groups, UProject project, UTrack track) {
+ base.SetUp(groups, project, track);
RomanizeNotes(groups);
}
}
-}
\ No newline at end of file
+}
diff --git a/OpenUtau.Plugin.Builtin/ChineseCVVPhonemizer.cs b/OpenUtau.Plugin.Builtin/ChineseCVVPhonemizer.cs
index 625398e75..9baab4836 100644
--- a/OpenUtau.Plugin.Builtin/ChineseCVVPhonemizer.cs
+++ b/OpenUtau.Plugin.Builtin/ChineseCVVPhonemizer.cs
@@ -56,6 +56,7 @@ protected override Dictionary LoadVowelFallbacks() {
}
public override void SetUp(Note[][] groups, UProject project, UTrack track) {
+ base.SetUp(groups, project, track);
BaseChinesePhonemizer.RomanizeNotes(groups);
}
}
diff --git a/OpenUtau.Plugin.Builtin/ChineseCVVPlusPhonemizer.cs b/OpenUtau.Plugin.Builtin/ChineseCVVPlusPhonemizer.cs
index 03581a9e9..8071effd9 100644
--- a/OpenUtau.Plugin.Builtin/ChineseCVVPlusPhonemizer.cs
+++ b/OpenUtau.Plugin.Builtin/ChineseCVVPlusPhonemizer.cs
@@ -225,20 +225,18 @@ private string GetLyricVowel(string lyric) {
}
// Method to check if the alias exists in oto.ini.
- public static bool isExistPhonemeInOto(USinger singer, string phoneme, Note note) {
+ public bool isExistPhonemeInOto(string phoneme, Note note) {
var attr = note.phonemeAttributes?.FirstOrDefault(attr => attr.index == 0) ?? default;
- string color = attr.voiceColor ?? string.Empty;
+ string color = attr.voiceColor ?? GetParentVoiceColor();
+ int toneShift = attr.toneShift ?? GetParentToneShift();
+ int? alt = attr.alternate ?? GetParentAlternate();
- var toneShift = 0;
- int? alt = null;
if (phoneme.Equals(string.Empty)) {
return false;
}
- if (singer.TryGetMappedOto(phoneme + alt, note.tone + toneShift, color, out var otoAlt)) {
- return true;
- } else if (singer.TryGetMappedOto(phoneme, note.tone + toneShift, color, out var oto)) {
+ if (singer.TryGetMappedOto(phoneme + alt, note.tone + toneShift, color, out var oto)) {
return true;
} else if (singer.TryGetMappedOto(phoneme, note.tone, color, out oto)) {
return true;
@@ -247,16 +245,13 @@ public static bool isExistPhonemeInOto(USinger singer, string phoneme, Note note
return false;
}
- static string GetOtoAlias(USinger singer, string phoneme, Note note) {
+ string GetOtoAlias(string phoneme, Note note) {
var attr = note.phonemeAttributes?.FirstOrDefault(attr => attr.index == 0) ?? default;
- string color = attr.voiceColor ?? string.Empty;
- int? alt = attr.alternate;
- var toneShift = attr.toneShift;
-
+ string color = attr.voiceColor ?? GetParentVoiceColor();
+ var toneShift = attr.toneShift ?? GetParentToneShift();
+ int? alt = attr.alternate ?? GetParentAlternate();
- if (singer.TryGetMappedOto(phoneme + alt, note.tone + toneShift, color, out var otoAlt)) {
- return otoAlt.Alias;
- } else if (singer.TryGetMappedOto(phoneme, note.tone + toneShift, color, out var oto)) {
+ if (singer.TryGetMappedOto(phoneme + alt, note.tone + toneShift, color, out var oto)) {
return oto.Alias;
} else if (singer.TryGetMappedOto(phoneme, note.tone, color, out oto)) {
return oto.Alias;
@@ -287,7 +282,7 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN
foreach (var phoneticHint in phoneticHints.Select((hint, index) => (hint, index))) {
phonemes[phoneticHint.index] = new Phoneme {
- phoneme = GetOtoAlias(singer, phoneticHint.hint.Trim(), notes[0]) ,
+ phoneme = GetOtoAlias(phoneticHint.hint.Trim(), notes[0]) ,
// The position is evenly divided into n parts.
position = totalDuration - ((totalDuration / phoneticHints.Length) * (phoneticHints.Length - phoneticHint.index)),
};
@@ -300,7 +295,7 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN
// If the note is an End Breath note
if (Config.SupportedTailBreath.Contains(phoneme) && prevNeighbour != null) {
- phoneme = GetOtoAlias(singer, $"{GetLyricVowel(prevNeighbour?.lyric)} {phoneme}", notes[0]);
+ phoneme = GetOtoAlias($"{GetLyricVowel(prevNeighbour?.lyric)} {phoneme}", notes[0]);
return new Result {
// Output in the form "Basic vowel shape + End Breath written with lyrics"
@@ -309,10 +304,10 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN
}
// If retan is set to True in zhcvvplus.yaml, there is no previous note, and the "- lyrics" alias exists in oto.ini
- if (Config.UseRetan && prevNeighbour == null && isExistPhonemeInOto(singer, $"- {phoneme}", notes[0])) {
+ if (Config.UseRetan && prevNeighbour == null && isExistPhonemeInOto($"- {phoneme}", notes[0])) {
// 가사를 "- 가사"로 변경
phoneme = $"- {phoneme}";
- phoneme = GetOtoAlias(singer, phoneme, notes[0]);
+ phoneme = GetOtoAlias(phoneme, notes[0]);
}
// If the lyrics require a tail vowel
@@ -339,8 +334,8 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN
// Change to the position specified in zhcvvplus.yaml.
tailVowelPosition = Config.FastTailVowelTimingTick;
}
- phoneme = GetOtoAlias(singer, phoneme, notes[0]);
- tailPhoneme = GetOtoAlias(singer, tailPhoneme, notes[0]);
+ phoneme = GetOtoAlias(phoneme, notes[0]);
+ tailPhoneme = GetOtoAlias(tailPhoneme, notes[0]);
return new Result() {
phonemes = new Phoneme[] {
new Phoneme { phoneme = phoneme }, // Original note lyrics
@@ -354,7 +349,7 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN
return new Result {
phonemes = new Phoneme[] {
new Phoneme() {
- phoneme = GetOtoAlias(singer, phoneme, notes[0]), // 防止无尾音歌词在多音阶情况下丢失prefix map suffix
+ phoneme = GetOtoAlias(phoneme, notes[0]), // 防止无尾音歌词在多音阶情况下丢失prefix map suffix
}
}
};
diff --git a/OpenUtau.Plugin.Builtin/EnunuOnnx/EnunuOnnxPhonemizer.cs b/OpenUtau.Plugin.Builtin/EnunuOnnx/EnunuOnnxPhonemizer.cs
index 8c3b74a07..6826d7ab6 100644
--- a/OpenUtau.Plugin.Builtin/EnunuOnnx/EnunuOnnxPhonemizer.cs
+++ b/OpenUtau.Plugin.Builtin/EnunuOnnx/EnunuOnnxPhonemizer.cs
@@ -210,6 +210,7 @@ public void LoadQuestionSet(string path, Encoding encoding) {
}
public override void SetUp(Note[][] groups, UProject project, UTrack track) {
+ base.SetUp(groups, project, track);
if (groups.Length == 0) {
return;
}
diff --git a/OpenUtau.Plugin.Builtin/ItalianCVVCPhonemizer.cs b/OpenUtau.Plugin.Builtin/ItalianCVVCPhonemizer.cs
index 42bf1cc90..ca9b22c1c 100644
--- a/OpenUtau.Plugin.Builtin/ItalianCVVCPhonemizer.cs
+++ b/OpenUtau.Plugin.Builtin/ItalianCVVCPhonemizer.cs
@@ -88,7 +88,7 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN
if (prevNeighbour == null) {
// Use "- V" or "- CV" if present in voicebank
var initial = $"-{currentLyric}";
- if (singer.TryGetMappedOto(initial, note.tone + attr0.toneShift, attr0.voiceColor, out var oto)) {
+ if (singer.TryGetMappedOto(initial, note.tone + (attr0.toneShift ?? GetParentToneShift()), attr0.voiceColor ?? GetParentVoiceColor(), out var oto)) {
currentLyric = oto.Alias;
}
} else if (plainVowels.Contains(currentLyric)) {
@@ -96,11 +96,11 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN
// Current note is VV
if (vowelLookup.TryGetValue(prevUnicode.LastOrDefault() ?? string.Empty, out var vow)) {
currentLyric = $"{vow} {currentLyric}";
- if (singer.TryGetMappedOto(currentLyric, note.tone + attr0.toneShift, attr0.voiceColor, out var oto)) {
+ if (singer.TryGetMappedOto(currentLyric, note.tone + (attr0.toneShift ?? GetParentToneShift()), attr0.voiceColor ?? GetParentVoiceColor(), out var oto)) {
currentLyric = oto.Alias;
}
}
- } else if (singer.TryGetMappedOto(currentLyric, note.tone + attr0.toneShift, attr0.voiceColor, out var oto)) {
+ } else if (singer.TryGetMappedOto(currentLyric, note.tone + (attr0.toneShift ?? GetParentToneShift()), attr0.voiceColor ?? GetParentVoiceColor(), out var oto)) {
currentLyric = oto.Alias;
}
@@ -147,7 +147,7 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN
}
var vcPhoneme = $"{vowel} {consonant}";
- if (singer.TryGetMappedOto(vcPhoneme, note.tone + attr1.toneShift, attr1.voiceColor, out var oto1)) {
+ if (singer.TryGetMappedOto(vcPhoneme, note.tone + (attr1.toneShift ?? GetParentToneShift()), attr1.voiceColor ?? GetParentVoiceColor(), out var oto1)) {
vcPhoneme = oto1.Alias;
} else {
return new Result {
@@ -162,7 +162,7 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN
int totalDuration = notes.Sum(n => n.duration);
int vcLength = 120;
var nextAttr = nextNeighbour.Value.phonemeAttributes?.FirstOrDefault(attr => attr.index == 0) ?? default;
- if (singer.TryGetMappedOto(nextLyric, nextNeighbour.Value.tone + nextAttr.toneShift, nextAttr.voiceColor, out var oto)) {
+ if (singer.TryGetMappedOto(nextLyric, nextNeighbour.Value.tone + (nextAttr.toneShift ?? GetParentToneShift()), nextAttr.voiceColor ?? GetParentVoiceColor(), out var oto)) {
vcLength = MsToTick(oto.Preutter);
}
vcLength = Math.Min(totalDuration / 2, vcLength);
diff --git a/OpenUtau.Plugin.Builtin/JapaneseCVVCPhonemizer.cs b/OpenUtau.Plugin.Builtin/JapaneseCVVCPhonemizer.cs
index 3bdfd82d9..11acdceea 100644
--- a/OpenUtau.Plugin.Builtin/JapaneseCVVCPhonemizer.cs
+++ b/OpenUtau.Plugin.Builtin/JapaneseCVVCPhonemizer.cs
@@ -103,17 +103,17 @@ static JapaneseCVVCPhonemizer() {
private bool checkOtoUntilHit(string[] input, Note note, out UOto oto) {
oto = default;
var attr = note.phonemeAttributes?.FirstOrDefault(attr => attr.index == 0) ?? default;
+ string color = attr.voiceColor ?? GetParentVoiceColor();
+ int shift = attr.toneShift ?? GetParentToneShift();
+ int? alt = attr.alternate ?? GetParentAlternate();
var otos = new List();
foreach (string test in input) {
- if (singer.TryGetMappedOto(test + attr.alternate, note.tone + attr.toneShift, attr.voiceColor, out var otoAlt)) {
- otos.Add(otoAlt);
- } else if (singer.TryGetMappedOto(test, note.tone + attr.toneShift, attr.voiceColor, out var otoCandidacy)) {
+ if (singer.TryGetMappedOto(test + alt, note.tone + shift, color, out var otoCandidacy)) {
otos.Add(otoCandidacy);
}
}
- string color = attr.voiceColor ?? "";
if (otos.Count > 0) {
oto = otos.FirstOrDefault(oto => oto.IsColorMatch(color));
if (oto == null) {
@@ -129,17 +129,17 @@ private bool checkOtoUntilHit(string[] input, Note note, out UOto oto) {
private bool checkOtoUntilHitVc(string[] input, Note note, out UOto oto) {
oto = default;
var attr = note.phonemeAttributes?.FirstOrDefault(attr => attr.index == 1) ?? default;
+ string color = attr.voiceColor ?? GetParentVoiceColor();
+ int shift = attr.toneShift ?? GetParentToneShift();
+ int? alt = attr.alternate ?? GetParentAlternate();
var otos = new List();
foreach (string test in input) {
- if (singer.TryGetMappedOto(test + attr.alternate, note.tone + attr.toneShift, attr.voiceColor, out var otoAlt)) {
- otos.Add(otoAlt);
- } else if (singer.TryGetMappedOto(test, note.tone + attr.toneShift, attr.voiceColor, out var otoCandidacy)) {
+ if (singer.TryGetMappedOto(test + alt, note.tone + shift, color, out var otoCandidacy)) {
otos.Add(otoCandidacy);
}
}
- string color = attr.voiceColor ?? "";
if (otos.Count > 0) {
oto = otos.FirstOrDefault(oto => oto.IsColorMatch(color));
if (oto != null) {
@@ -257,7 +257,7 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN
int totalDuration = notes.Sum(n => n.duration);
int vcLength = 120;
var nextAttr = nextNeighbour.Value.phonemeAttributes?.FirstOrDefault(attr => attr.index == 0) ?? default;
- if (singer.TryGetMappedOto(nextLyric, nextNeighbour.Value.tone + nextAttr.toneShift, nextAttr.voiceColor, out var oto)) {
+ if (singer.TryGetMappedOto(nextLyric, nextNeighbour.Value.tone + (nextAttr.toneShift ?? GetParentToneShift()), nextAttr.voiceColor ?? GetParentVoiceColor(), out var oto)) {
// If overlap is a negative value, vcLength is longer than Preutter
if (oto.Overlap < 0) {
vcLength = MsToTick(oto.Preutter - oto.Overlap);
@@ -266,7 +266,7 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN
}
}
// vcLength depends on the Vel of the next note
- vcLength = Convert.ToInt32(Math.Min(totalDuration / 2, vcLength * (nextAttr.consonantStretchRatio ?? 1)));
+ vcLength = Convert.ToInt32(Math.Min(totalDuration / 2, vcLength * (nextAttr.consonantStretchRatio ?? GetParentConsonantStretchRatio())));
return new Result {
phonemes = new Phoneme[] {
diff --git a/OpenUtau.Plugin.Builtin/JapanesePresampPhonemizer.cs b/OpenUtau.Plugin.Builtin/JapanesePresampPhonemizer.cs
index fceed12e9..648fcd414 100644
--- a/OpenUtau.Plugin.Builtin/JapanesePresampPhonemizer.cs
+++ b/OpenUtau.Plugin.Builtin/JapanesePresampPhonemizer.cs
@@ -20,8 +20,6 @@ public class JapanesePresampPhonemizer : Phonemizer {
private USinger singer;
private Presamp presamp;
- private UProject project;
- private UTrack track;
// in case voicebank is missing certain symbols
static readonly string[] substitution = new string[] {
@@ -39,11 +37,6 @@ static JapanesePresampPhonemizer() {
.ToDictionary(t => t.Item1, t => t.Item2);
}
- public override void SetUp(Note[][] groups, UProject project, UTrack track) {
- this.project = project;
- this.track = track;
- }
-
public override void SetSinger(USinger singer) {
if (this.singer == singer) {
return;
@@ -199,7 +192,7 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN
&& checkOtoUntilHit(new List { currentLyric }, note, out var oto)) {
int endTick = notes[^1].position + notes[^1].duration;
var attr = note.phonemeAttributes?.FirstOrDefault(attr => attr.index == 0) ?? default;
- var cLength = Math.Max(30, -timeAxis.MsToTickAt(-oto.Preutter, endTick) * (attr.consonantStretchRatio ?? 1));
+ var cLength = Math.Max(30, -timeAxis.MsToTickAt(-oto.Preutter, endTick) * (attr.consonantStretchRatio ?? GetParentConsonantStretchRatio()));
if (prevNeighbour != null) {
cLength = Math.Min(prevNeighbour.Value.duration / 2, cLength);
@@ -225,7 +218,7 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN
// Insert 2nd phoneme (when next doesn't have hint)
if (nextNeighbour != null && string.IsNullOrEmpty(nextNeighbour.Value.phoneticHint)) {
int totalDuration = notes.Sum(n => n.duration);
- if (TickToMs(totalDuration) < 100 && presamp.MustVC == false) {
+ if (timeAxis.TickPosToMsPos(totalDuration) < 100 && presamp.MustVC == false) {
return new Result { phonemes = result.ToArray() };
}
@@ -312,7 +305,7 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN
int vcLength = 120;
int endTick = notes[^1].position + notes[^1].duration;
var nextAttr = nextNeighbour.Value.phonemeAttributes?.FirstOrDefault(attr => attr.index == 0) ?? default;
- if (singer.TryGetMappedOto(nextLyric, nextNeighbour.Value.tone + nextAttr.toneShift, nextAttr.voiceColor, out var nextOto)) {
+ if (singer.TryGetMappedOto(nextLyric, nextNeighbour.Value.tone + (nextAttr.toneShift ?? GetParentToneShift()), nextAttr.voiceColor ?? GetParentVoiceColor(), out var nextOto)) {
// If overlap is a negative value, vcLength is longer than Preutter
if (nextOto.Overlap < 0) {
vcLength = -timeAxis.MsToTickAt(-(nextOto.Preutter - nextOto.Overlap), endTick);
@@ -321,7 +314,7 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN
}
}
// Minimam is 30 tick, maximum is half of note
- vcLength = Convert.ToInt32(Math.Min(totalDuration / 2, Math.Max(30, vcLength * (nextAttr.consonantStretchRatio ?? 1))));
+ vcLength = Convert.ToInt32(Math.Min(totalDuration / 2, Math.Max(30, vcLength * (nextAttr.consonantStretchRatio ?? GetParentConsonantStretchRatio()))));
result.Add(new Phoneme() {
phoneme = vcPhoneme,
@@ -338,19 +331,16 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN
return new Result { phonemes = result.ToArray() };
}
- // make it quicker to check multiple oto occurrences at once rather than spamming if else if
private bool checkOtoUntilHit(List input, Note note, out UOto oto) {
oto = default;
var attr = note.phonemeAttributes?.FirstOrDefault(attr => attr.index == 0) ?? default;
- // track.TryGetExpression(project, Core.Format.Ustx.CLR, out var trackExp);
- // string color = attr.voiceColor ?? trackExp.descriptor.options[(int)trackExp.value];
- string color = attr.voiceColor ?? string.Empty;
+ string color = attr.voiceColor ?? GetParentVoiceColor();
+ int shift = attr.toneShift ?? GetParentToneShift();
+ int? alt = attr.alternate ?? GetParentAlternate();
var otos = new List();
foreach (string test in input) {
- if (singer.TryGetMappedOto(test + attr.alternate, note.tone + attr.toneShift, color, out var otoAlt)) {
- otos.Add(otoAlt);
- } else if (singer.TryGetMappedOto(test, note.tone + attr.toneShift, color, out var otoCandidacy)) {
+ if (singer.TryGetMappedOto(test + alt, note.tone + shift, color, out var otoCandidacy)) {
otos.Add(otoCandidacy);
}
}
@@ -369,13 +359,13 @@ private bool checkOtoUntilHit(List input, Note note, int index, out UOto
colorIndex = null;
var attr = note.phonemeAttributes?.FirstOrDefault(attr => attr.index == index) ?? default;
var attr0 = note.phonemeAttributes?.FirstOrDefault(attr => attr.index == 0) ?? default;
- string color = attr.voiceColor ?? attr0.voiceColor ?? string.Empty;
+ string color = attr.voiceColor ?? attr0.voiceColor ?? GetParentVoiceColor();
+ int shift = attr.toneShift ?? attr0.toneShift ?? GetParentToneShift();
+ int? alt = attr.alternate ?? GetParentAlternate();
var otos = new List();
foreach (string test in input) {
- if (singer.TryGetMappedOto(test + attr.alternate, note.tone + attr.toneShift, color, out var otoAlt)) {
- otos.Add(otoAlt);
- } else if (singer.TryGetMappedOto(test, note.tone + attr.toneShift, color, out var otoCandidacy)) {
+ if (singer.TryGetMappedOto(test + alt, note.tone + shift, color, out var otoCandidacy)) {
otos.Add(otoCandidacy);
}
}
@@ -383,11 +373,11 @@ private bool checkOtoUntilHit(List input, Note note, int index, out UOto
if (otos.Count > 0) {
oto = otos.FirstOrDefault(oto => oto.IsColorMatch(color));
if (oto != null) {
- if (track.VoiceColorExp.options.Contains(color)) {
+ if (track != null && track.VoiceColorExp.options.Contains(color)) {
colorIndex = Array.IndexOf(track.VoiceColorExp.options, color);
}
return true;
- } else if (index != 1 && index != 2) {
+ } else if (index != 1 && index != 2) { // Main phoneme is required, preC and VC are not required
oto = otos.First();
return true;
}
diff --git a/OpenUtau.Plugin.Builtin/JapaneseVCVPhonemizer.cs b/OpenUtau.Plugin.Builtin/JapaneseVCVPhonemizer.cs
index 40df4d382..281075fd1 100644
--- a/OpenUtau.Plugin.Builtin/JapaneseVCVPhonemizer.cs
+++ b/OpenUtau.Plugin.Builtin/JapaneseVCVPhonemizer.cs
@@ -90,13 +90,13 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN
private bool CheckOtoUntilHit(string[] input, Note note, out UOto oto) {
oto = default;
var attr = note.phonemeAttributes?.FirstOrDefault(attr => attr.index == 0) ?? default;
- string color = attr.voiceColor ?? "";
+ string color = attr.voiceColor ?? GetParentVoiceColor();
+ int shift = attr.toneShift ?? GetParentToneShift();
+ int? alt = attr.alternate ?? GetParentAlternate();
var otos = new List();
foreach (string test in input) {
- if (singer.TryGetMappedOto(test + attr.alternate, note.tone + attr.toneShift, color, out var otoAlt)) {
- otos.Add(otoAlt);
- } else if (singer.TryGetMappedOto(test, note.tone + attr.toneShift, color, out var otoCandidacy)) {
+ if (singer.TryGetMappedOto(test + alt, note.tone + shift, color, out var otoCandidacy)) {
otos.Add(otoCandidacy);
}
}
diff --git a/OpenUtau.Plugin.Builtin/KOtoJAPhonemizer.cs b/OpenUtau.Plugin.Builtin/KOtoJAPhonemizer.cs
index f05e18a7d..a85e5f680 100644
--- a/OpenUtau.Plugin.Builtin/KOtoJAPhonemizer.cs
+++ b/OpenUtau.Plugin.Builtin/KOtoJAPhonemizer.cs
@@ -313,6 +313,7 @@ static KOtoJAPhonemizer() {
/// Apply Korean sandhi rules to Hangeul lyrics.
///
public override void SetUp(Note[][] groups, UProject project, UTrack track) {
+ base.SetUp(groups, project, track);
// variate lyrics
RomanizeNotes(groups, false);
}
@@ -393,19 +394,19 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN
int? alt2;
PhonemeAttributes attr = note.phonemeAttributes.FirstOrDefault(a => a.index == 0);
- color = attr.voiceColor;
- shift = attr.toneShift;
- alt = attr.alternate;
+ color = attr.voiceColor ?? GetParentVoiceColor();
+ shift = attr.toneShift ?? GetParentToneShift();
+ alt = attr.alternate ?? GetParentAlternate();
PhonemeAttributes attr1 = note.phonemeAttributes.FirstOrDefault(a => a.index == 1);
- color1 = attr1.voiceColor;
- shift1 = attr1.toneShift;
- alt1 = attr1.alternate;
+ color1 = attr1.voiceColor ?? GetParentVoiceColor();
+ shift1 = attr1.toneShift ?? GetParentToneShift();
+ alt1 = attr1.alternate ?? GetParentAlternate();
PhonemeAttributes attr2 = note.phonemeAttributes.FirstOrDefault(a => a.index == 2);
- color2 = attr2.voiceColor;
- shift2 = attr2.toneShift;
- alt2 = attr2.alternate;
+ color2 = attr2.voiceColor ?? GetParentVoiceColor();
+ shift2 = attr2.toneShift ?? GetParentToneShift();
+ alt2 = attr2.alternate ?? GetParentAlternate();
string[] currIMF;
string currPhoneme;
@@ -476,9 +477,7 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN
}
}
// Map alias (apply shift + color)
- if (singer.TryGetMappedOto(currPhoneme + alt, note.tone + shift, color, out var otoAlt)) {
- currPhoneme = otoAlt.Alias;
- } else if (singer.TryGetMappedOto(currPhoneme, note.tone + shift, color, out var oto)) {
+ if (singer.TryGetMappedOto(currPhoneme + alt, note.tone + shift, color, out var oto)) {
currPhoneme = oto.Alias;
}
@@ -648,7 +647,7 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN
}
}
// vcLength depends on the Vel of the current base note
- vcLength = Convert.ToInt32(Math.Min(totalDuration / 2, vcLength * (attr1.consonantStretchRatio ?? 1)));
+ vcLength = Convert.ToInt32(Math.Min(totalDuration / 2, vcLength * (attr1.consonantStretchRatio ?? GetParentConsonantStretchRatio())));
if (string.IsNullOrEmpty(prevIMF[2])) {
if (prevIMF[1][0] == 'w' || prevIMF[1][0] == 'y') {
@@ -678,9 +677,7 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN
if (substituteLookup.TryGetValue(consonant ?? string.Empty, out con)) {
vcPhonemes[1] = $"{prevConnect} {con}";
}
- if (singer.TryGetMappedOto(currPhoneme + alt1, note.tone + shift1, color1, out var otoAlt)) {
- currPhoneme = otoAlt.Alias;
- } else if (singer.TryGetMappedOto(currPhoneme, note.tone + shift1, color1, out var oto0)) {
+ if (singer.TryGetMappedOto(currPhoneme + alt1, note.tone + shift1, color1, out var oto0)) {
currPhoneme = oto0.Alias;
}
string secondPhoneme = (currIMF[1][0] == 'w' || currIMF[1][0] == 'y') ? currIMF[1].Remove(0, 1) : currIMF[1];
@@ -742,19 +739,13 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN
int noteLength = 0;
for (int i = 0; i < notes.Length; i++) noteLength += notes[i].duration;
int secondPosition = Math.Max(noteLength - (nextNeighbour == null ? 120 : 180), noteLength / 2);
- if (singer.TryGetMappedOto(currPhoneme + alt1, note.tone + shift1, color1, out var otoAlt0)) {
- currPhoneme = otoAlt0.Alias;
- } else if (singer.TryGetMappedOto(currPhoneme, note.tone + shift1, color1, out var oto0)) {
+ if (singer.TryGetMappedOto(currPhoneme + alt1, note.tone + shift1, color1, out oto0)) {
currPhoneme = oto0.Alias;
}
- if (singer.TryGetMappedOto(vcPhoneme ?? vcPhonemes[1] ?? string.Empty + alt, prevNeighbour.Value.tone + shift, color, out var otoVcAlt)) {
- vcPhoneme = otoVcAlt.Alias;
- } else if (singer.TryGetMappedOto(vcPhoneme ?? vcPhonemes[1] ?? string.Empty, prevNeighbour.Value.tone + shift, color, out var otoVc)) {
+ if (singer.TryGetMappedOto(vcPhoneme ?? vcPhonemes[1] ?? string.Empty + alt, prevNeighbour.Value.tone + shift, color, out var otoVc)) {
vcPhoneme = otoVc.Alias;
}
- if (singer.TryGetMappedOto(secondPhoneme + alt2, note.tone + shift2, color2, out var otoAlt3)) {
- secondPhoneme = otoAlt3.Alias;
- } else if (singer.TryGetMappedOto(secondPhoneme, note.tone + shift2, color2, out var oto3)) {
+ if (singer.TryGetMappedOto(secondPhoneme + alt2, note.tone + shift2, color2, out var oto3)) {
secondPhoneme = oto3.Alias;
}
if (singer.TryGetMappedOto(vcPhoneme, note.tone + shift, color, out _)
@@ -803,9 +794,7 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN
if (string.IsNullOrEmpty(currIMF[2])) {
// Map alias (apply shift + color)
- if (singer.TryGetMappedOto(currPhoneme + alt, note.tone + shift, color, out var otoAlt)) {
- currPhoneme = otoAlt.Alias;
- } else if (singer.TryGetMappedOto(currPhoneme, note.tone + shift, color, out var oto)) {
+ if (singer.TryGetMappedOto(currPhoneme + alt, note.tone + shift, color, out var oto)) {
currPhoneme = oto.Alias;
}
return new Result {
@@ -874,14 +863,10 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN
for (int i = 0; i < notes.Length; i++) noteLength += notes[i].duration;
int secondPosition = Math.Max(noteLength - (nextNeighbour == null ? 120 : 180), noteLength / 2);
// Map alias (apply shift + color)
- if (singer.TryGetMappedOto(currPhoneme + alt, note.tone + shift, color, out var otoAlt)) {
- currPhoneme = otoAlt.Alias;
- } else if (singer.TryGetMappedOto(currPhoneme, note.tone + shift, color, out var oto)) {
+ if (singer.TryGetMappedOto(currPhoneme + alt, note.tone + shift, color, out var oto)) {
currPhoneme = oto.Alias;
}
- if (singer.TryGetMappedOto(secondPhoneme + alt1, note.tone + shift1, color1, out var otoalt)) {
- secondPhoneme = otoalt.Alias;
- } else if (singer.TryGetMappedOto(secondPhoneme, note.tone + shift1, color1, out var oto)) {
+ if (singer.TryGetMappedOto(secondPhoneme + alt1, note.tone + shift1, color1, out oto)) {
secondPhoneme = oto.Alias;
}
// Return Result
diff --git a/OpenUtau.Plugin.Builtin/KoreanCBNNPhonemizer.cs b/OpenUtau.Plugin.Builtin/KoreanCBNNPhonemizer.cs
index 008f86847..01763b3f5 100644
--- a/OpenUtau.Plugin.Builtin/KoreanCBNNPhonemizer.cs
+++ b/OpenUtau.Plugin.Builtin/KoreanCBNNPhonemizer.cs
@@ -219,7 +219,7 @@ private Result ConvertForCBNN(Note[] notes, string[] prevLyric, string[] thisLyr
}
private string? FindInOto(String phoneme, Note note, bool nullIfNotFound=false){
- return BaseKoreanPhonemizer.FindInOto(singer, phoneme, note, nullIfNotFound);
+ return FindInOto(singer, phoneme, note, nullIfNotFound);
}
@@ -282,4 +282,4 @@ public override Result GenerateEndSound(Note[] notes, Note? prev, Note? next, No
return GenerateResult(FindInOto($"{prevMidVowel} {endSound}", note));
}
}
-}
\ No newline at end of file
+}
diff --git a/OpenUtau.Plugin.Builtin/KoreanCVCCVPhonemizer.cs b/OpenUtau.Plugin.Builtin/KoreanCVCCVPhonemizer.cs
index d42470b77..705a23e5d 100644
--- a/OpenUtau.Plugin.Builtin/KoreanCVCCVPhonemizer.cs
+++ b/OpenUtau.Plugin.Builtin/KoreanCVCCVPhonemizer.cs
@@ -213,6 +213,7 @@ private char[] SeparateHangul(char letter) {
/// Apply Korean sandhi rules to Hangeul lyrics.
///
public override void SetUp(Note[][] groups, UProject project, UTrack track) {
+ base.SetUp(groups, project, track);
// variate lyrics
KoreanPhonemizerUtil.RomanizeNotes(groups, false);
}
diff --git a/OpenUtau.Plugin.Builtin/KoreanCVCPhonemizer.cs b/OpenUtau.Plugin.Builtin/KoreanCVCPhonemizer.cs
index 6c1fa2afd..ecef09b30 100644
--- a/OpenUtau.Plugin.Builtin/KoreanCVCPhonemizer.cs
+++ b/OpenUtau.Plugin.Builtin/KoreanCVCPhonemizer.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Linq;
using OpenUtau.Api;
@@ -96,6 +96,7 @@ string getConsonant(string str) {
/// Apply Korean sandhi rules to Hangeul lyrics.
///
public override void SetUp(Note[][] groups, UProject project, UTrack track) {
+ base.SetUp(groups, project, track);
// variate lyrics
KoreanPhonemizerUtil.RomanizeNotes(groups, false);
}
@@ -155,7 +156,7 @@ 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, note.tone + (attr0.toneShift ?? GetParentToneShift()), attr0.voiceColor ?? GetParentVoiceColor(), out oto)){
return true;
}
}
@@ -592,7 +593,7 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN
int fcLength = totalDuration / 3;
if ((TCLfinal == "k") || (TCLfinal == "p") || (TCLfinal == "t")) { fcLength = totalDuration / 2; }
- if (singer.TryGetMappedOto(CV, note.tone + attr0.toneShift, attr0.voiceColor, out var oto1) && singer.TryGetMappedOto(FC, note.tone + attr0.toneShift, attr0.voiceColor, out var oto2)) {
+ if (singer.TryGetMappedOto(CV, note.tone + (attr0.toneShift ?? GetParentToneShift()), attr0.voiceColor ?? GetParentVoiceColor(), out var oto1) && singer.TryGetMappedOto(FC, note.tone + (attr0.toneShift ?? GetParentToneShift()), attr0.voiceColor ?? GetParentVoiceColor(), out var oto2)) {
CV = oto1.Alias;
FC = oto2.Alias;
return new Result {
@@ -622,7 +623,7 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN
else if ((TNLconsonant == "gg") || (TNLconsonant == "dd") || (TNLconsonant == "bb") || (TNLconsonant == "ss") || (TNLconsonant == "jj")) { vcLength = totalDuration / 2; }
vcLength = Math.Min(totalDuration / 2, vcLength);
- if (singer.TryGetMappedOto(CV, note.tone + attr0.toneShift, attr0.voiceColor, out var oto1) && singer.TryGetMappedOto(VC, note.tone + attr0.toneShift, attr0.voiceColor, out var oto2)) {
+ if (singer.TryGetMappedOto(CV, note.tone + (attr0.toneShift ?? GetParentToneShift()), attr0.voiceColor ?? GetParentVoiceColor(), out var oto1) && singer.TryGetMappedOto(VC, note.tone + (attr0.toneShift ?? GetParentToneShift()), attr0.voiceColor ?? GetParentVoiceColor(), out var oto2)) {
CV = oto1.Alias;
VC = oto2.Alias;
return new Result {
@@ -642,13 +643,13 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN
var nextAttr = nextNeighbour.Value.phonemeAttributes?.FirstOrDefault(attr => attr.index == 0) ?? default;
var nextUnicode = ToUnicodeElements(nextNeighbour?.lyric);
var nextLyric = string.Join("", nextUnicode);
- if (singer.TryGetMappedOto(nextLyric, nextNeighbour.Value.tone + nextAttr.toneShift, nextAttr.voiceColor, out var oto0)) {
+ if (singer.TryGetMappedOto(nextLyric, nextNeighbour.Value.tone + (nextAttr.toneShift ?? GetParentToneShift()), nextAttr.voiceColor ?? GetParentVoiceColor(), out var oto0)) {
vcLength = MsToTick(oto0.Preutter);
}
vcLength = Math.Min(totalDuration / 2, vcLength);
- if (singer.TryGetMappedOto(CV, note.tone + attr0.toneShift, attr0.voiceColor, out var oto1) && singer.TryGetMappedOto(VC, note.tone + attr0.toneShift, attr0.voiceColor, out var oto2)) {
+ if (singer.TryGetMappedOto(CV, note.tone + (attr0.toneShift ?? GetParentToneShift()), attr0.voiceColor ?? GetParentVoiceColor(), out var oto1) && singer.TryGetMappedOto(VC, note.tone + (attr0.toneShift ?? GetParentToneShift()), attr0.voiceColor ?? GetParentVoiceColor(), out var oto2)) {
CV = oto1.Alias;
VC = oto2.Alias;
return new Result {
@@ -665,7 +666,7 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN
}
}
// 그 외(받침 없는 마지막 노트)
- if (singer.TryGetMappedOto(CV, note.tone + attr0.toneShift, attr0.voiceColor, out var oto)) {
+ if (singer.TryGetMappedOto(CV, note.tone + (attr0.toneShift ?? GetParentToneShift()), attr0.voiceColor ?? GetParentVoiceColor(), out var oto)) {
CV = oto.Alias;
return new Result {
phonemes = new Phoneme[] {
@@ -687,7 +688,7 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN
endBreath = $"{TPLplainfinal} R";
}
- if (singer.TryGetMappedOto(endBreath, note.tone + attr0.toneShift, attr0.voiceColor, out var oto)){
+ if (singer.TryGetMappedOto(endBreath, note.tone + (attr0.toneShift ?? GetParentToneShift()), attr0.voiceColor ?? GetParentVoiceColor(), out var oto)){
endBreath = oto.Alias;
return new Result {
phonemes = new Phoneme[] {
@@ -892,7 +893,7 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN
int vcLength = 60;
var nextAttr = nextNeighbour.Value.phonemeAttributes?.FirstOrDefault(attr => attr.index == 0) ?? default;
- if (singer.TryGetMappedOto(nextLyric, nextNeighbour.Value.tone + nextAttr.toneShift, nextAttr.voiceColor, out var oto)) {
+ if (singer.TryGetMappedOto(nextLyric, nextNeighbour.Value.tone + (nextAttr.toneShift ?? GetParentToneShift()), nextAttr.voiceColor ?? GetParentVoiceColor(), out var oto)) {
vcLength = MsToTick(oto.Preutter);
} else if ((TNLconsonant == "r") || (TNLconsonant == "h")) { vcLength = 30; }
else if (TNLconsonant == "s") { vcLength = totalDuration / 3; }
diff --git a/OpenUtau.Plugin.Builtin/KoreanCVPhonemizer.cs b/OpenUtau.Plugin.Builtin/KoreanCVPhonemizer.cs
index 3a9447701..3b7cc65cb 100644
--- a/OpenUtau.Plugin.Builtin/KoreanCVPhonemizer.cs
+++ b/OpenUtau.Plugin.Builtin/KoreanCVPhonemizer.cs
@@ -339,7 +339,7 @@ private Result ConvertForCV(Note[] notes, string[] prevLyric, string[] thisLyric
}
private string? FindInOto(String phoneme, Note note, bool nullIfNotFound=false){
- return BaseKoreanPhonemizer.FindInOto(singer, phoneme, note, nullIfNotFound);
+ return FindInOto(singer, phoneme, note, nullIfNotFound);
}
@@ -415,4 +415,4 @@ public override Result GenerateEndSound(Note[] notes, Note? prev, Note? next, No
return GenerateResult(FindInOto($"{prevMidVowel} {endSound}", note));
}
}
-}
\ No newline at end of file
+}
diff --git a/OpenUtau.Plugin.Builtin/KoreanCVVCStandardPronunciationPhonemizer.cs b/OpenUtau.Plugin.Builtin/KoreanCVVCStandardPronunciationPhonemizer.cs
index c1f5e560a..4931ffdd5 100644
--- a/OpenUtau.Plugin.Builtin/KoreanCVVCStandardPronunciationPhonemizer.cs
+++ b/OpenUtau.Plugin.Builtin/KoreanCVVCStandardPronunciationPhonemizer.cs
@@ -277,7 +277,7 @@ private Result ConvertForCVVC(Note[] notes, string[] prevLyric, string[] thisLyr
}
private string? FindInOto(String phoneme, Note note, bool nullIfNotFound=false){
- return BaseKoreanPhonemizer.FindInOto(singer, phoneme, note, nullIfNotFound);
+ return FindInOto(singer, phoneme, note, nullIfNotFound);
}
private bool IsENPhoneme(String phoneme) {
@@ -468,4 +468,4 @@ public override Result GenerateEndSound(Note[] notes, Note? prev, Note? next, No
return GenerateResult(FindInOto($"{prevMidVowel} {endSound}", note));
}
}
-}
\ No newline at end of file
+}
diff --git a/OpenUtau.Plugin.Builtin/KoreanVCVPhonemizer.cs b/OpenUtau.Plugin.Builtin/KoreanVCVPhonemizer.cs
index 541d5e2a1..2bbcfbff3 100644
--- a/OpenUtau.Plugin.Builtin/KoreanVCVPhonemizer.cs
+++ b/OpenUtau.Plugin.Builtin/KoreanVCVPhonemizer.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
@@ -44,8 +44,9 @@ public class KoreanVCVPhonemizer : BaseKoreanPhonemizer
/// Apply Korean sandhi rules to Hangeul lyrics.
///
public override void SetUp(Note[][] groups, UProject project, UTrack track) {
- // variate lyrics
- RomanizeNotes(groups, false);
+ base.SetUp(groups, project, track);
+ // variate lyrics
+ RomanizeNotes(groups, false);
}
///
@@ -138,14 +139,14 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN
int? alt1;
PhonemeAttributes attr = note.phonemeAttributes.FirstOrDefault(a => a.index == 0);
- color = attr.voiceColor;
- shift = attr.toneShift;
- alt = attr.alternate;
+ color = attr.voiceColor ?? GetParentVoiceColor();
+ shift = attr.toneShift ?? GetParentToneShift();
+ alt = attr.alternate ?? GetParentAlternate();
PhonemeAttributes attr1 = note.phonemeAttributes.FirstOrDefault(a => a.index == 1);
- color1 = attr1.voiceColor;
- shift1 = attr1.toneShift;
- alt1 = attr1.alternate;
+ color1 = attr1.voiceColor ?? GetParentVoiceColor();
+ shift1 = attr1.toneShift ?? GetParentToneShift();
+ alt1 = attr1.alternate ?? GetParentAlternate();
string[] currIMF;
string currPhoneme;
@@ -207,9 +208,7 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN
}
// Map alias (apply shift + color)
- if (singer.TryGetMappedOto(currPhoneme + alt, note.tone + shift, color, out var otoAlt)) {
- currPhoneme = otoAlt.Alias;
- } else if (singer.TryGetMappedOto(currPhoneme, note.tone + shift, color, out var oto)) {
+ if (singer.TryGetMappedOto(currPhoneme + alt, note.tone + shift, color, out var oto)) {
currPhoneme = oto.Alias;
}
@@ -296,9 +295,7 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN
if (string.IsNullOrEmpty(currIMF[2]))
{
// Map alias (apply shift + color)
- if (singer.TryGetMappedOto(currPhoneme + alt, note.tone + shift, color, out var otoAlt)) {
- currPhoneme = otoAlt.Alias;
- } else if (singer.TryGetMappedOto(currPhoneme, note.tone + shift, color, out var oto)) {
+ if (singer.TryGetMappedOto(currPhoneme + alt, note.tone + shift, color, out var oto)) {
currPhoneme = oto.Alias;
}
@@ -340,15 +337,11 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN
int secondPosition = Math.Max(noteLength - (nextNeighbour == null ? 120 : 180), noteLength / 2);
// Map alias (apply shift + color)
- if (singer.TryGetMappedOto(currPhoneme + alt, note.tone + shift, color, out var otoAlt)) {
- currPhoneme = otoAlt.Alias;
- } else if (singer.TryGetMappedOto(currPhoneme, note.tone + shift, color, out var oto)) {
+ if (singer.TryGetMappedOto(currPhoneme + alt, note.tone + shift, color, out var oto)) {
currPhoneme = oto.Alias;
}
- if (singer.TryGetMappedOto(secondPhoneme + alt1, note.tone + shift1, color1, out var otoAlt1)) {
- secondPhoneme = otoAlt1.Alias;
- } else if (singer.TryGetMappedOto(secondPhoneme, note.tone + shift1, color1, out var oto)) {
+ if (singer.TryGetMappedOto(secondPhoneme + alt1, note.tone + shift1, color1, out oto)) {
secondPhoneme = oto.Alias;
}
diff --git a/OpenUtau.Plugin.Builtin/PhonemeBasedPhonemizer.cs b/OpenUtau.Plugin.Builtin/PhonemeBasedPhonemizer.cs
index 2c33d0a99..7f6447631 100644
--- a/OpenUtau.Plugin.Builtin/PhonemeBasedPhonemizer.cs
+++ b/OpenUtau.Plugin.Builtin/PhonemeBasedPhonemizer.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Linq;
using OpenUtau.Api;
@@ -62,7 +62,7 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN
// The user is using a tail "-" note to produce a " -" sound.
if (note.lyric == "-" && prevSymbols != null) {
var attr = note.phonemeAttributes?.FirstOrDefault() ?? default;
- string color = attr.voiceColor;
+ string color = attr.voiceColor ?? GetParentVoiceColor();
string alias = $"{prevSymbols.Last()} -";
if (singer.TryGetMappedOto(alias, note.tone, color, out var oto)) {
return MakeSimpleResult(oto.Alias);
@@ -143,9 +143,9 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN
string prevSymbol = prevSymbols == null ? "-" : prevSymbols.Last();
for (int i = 0; i < symbols.Length; i++) {
var attr = note.phonemeAttributes?.FirstOrDefault(attr => attr.index == i) ?? default;
- string alt = attr.alternate?.ToString() ?? string.Empty;
- string color = attr.voiceColor;
- int toneShift = attr.toneShift;
+ string alt = (attr.alternate ?? GetParentAlternate())?.ToString() ?? string.Empty;
+ string color = attr.voiceColor ?? GetParentVoiceColor();
+ int toneShift = attr.toneShift ?? GetParentToneShift();
var phoneme = phonemes[i];
while (noteIndex < notes.Length - 1 && notes[noteIndex].position - note.position < phoneme.position) {
noteIndex++;
@@ -219,4 +219,4 @@ void DistributeDuration(bool[] isVowel, Phoneme[] phonemes, int startIndex, int
}
}
}
-}
\ No newline at end of file
+}
diff --git a/OpenUtau.Plugin.Builtin/PresampSamplePhonemizer.cs b/OpenUtau.Plugin.Builtin/PresampSamplePhonemizer.cs
index d330d681b..63e53ee58 100644
--- a/OpenUtau.Plugin.Builtin/PresampSamplePhonemizer.cs
+++ b/OpenUtau.Plugin.Builtin/PresampSamplePhonemizer.cs
@@ -1,10 +1,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Text.RegularExpressions;
using Classic;
using OpenUtau.Api;
-using OpenUtau.Classic;
using OpenUtau.Core.Ustx;
#if DEBUG
@@ -60,25 +58,25 @@ 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;
if (lyric == "-" || lyric.ToLowerInvariant() == "r") {
- if (singer.TryGetMappedOto($"{prevVowel}{vcpad}R", notes[0].tone + attr0.toneShift, attr0.voiceColor, out var oto1)) {
+ if (singer.TryGetMappedOto($"{prevVowel}{vcpad}R", notes[0].tone + (attr0.toneShift ?? GetParentToneShift()), attr0.voiceColor ?? GetParentVoiceColor(), out var oto1)) {
return MakeSimpleResult(oto1.Alias);
}
return MakeSimpleResult($"{prevVowel}{vcpad}R");
}
int totalDuration = notes.Sum(n => n.duration);
- if (singer.TryGetMappedOto($"{prevVowel}{vcpad}{lyric}", notes[0].tone + attr0.toneShift, attr0.voiceColor, out var oto)) {
+ if (singer.TryGetMappedOto($"{prevVowel}{vcpad}{lyric}", notes[0].tone + (attr0.toneShift ?? GetParentToneShift()), attr0.voiceColor ?? GetParentVoiceColor(), out var oto)) {
return MakeSimpleResult(oto.Alias);
}
int vcLen = 120;
- if (singer.TryGetMappedOto(lyric, notes[0].tone + attr0.toneShift, attr0.voiceColor, out var cvOto)) {
+ if (singer.TryGetMappedOto(lyric, notes[0].tone + (attr0.toneShift ?? GetParentToneShift()), attr0.voiceColor ?? GetParentVoiceColor(), out var cvOto)) {
if (cvOto.Overlap < 0) {
vcLen = MsToTick(cvOto.Preutter - cvOto.Overlap);
} else {
vcLen = MsToTick(cvOto.Preutter);
}
- vcLen = Convert.ToInt32(Math.Min(totalDuration / 2, vcLen * (attr0.consonantStretchRatio ?? 1)));
+ vcLen = Convert.ToInt32(Math.Min(totalDuration / 2, vcLen * (attr0.consonantStretchRatio ?? GetParentConsonantStretchRatio())));
}
- if (singer.TryGetMappedOto($"{prevVowel}{vcpad}{consonant}", notes[0].tone + attr0.toneShift, attr0.voiceColor, out oto)) {
+ if (singer.TryGetMappedOto($"{prevVowel}{vcpad}{consonant}", notes[0].tone + (attr0.toneShift ?? GetParentToneShift()), attr0.voiceColor ?? GetParentVoiceColor(), out oto)) {
return new Result {
phonemes = new Phoneme[] {
new Phoneme() {
diff --git a/OpenUtau.Plugin.Builtin/SyllableBasedPhonemizer.cs b/OpenUtau.Plugin.Builtin/SyllableBasedPhonemizer.cs
index c576430f0..95ca6df74 100644
--- a/OpenUtau.Plugin.Builtin/SyllableBasedPhonemizer.cs
+++ b/OpenUtau.Plugin.Builtin/SyllableBasedPhonemizer.cs
@@ -217,9 +217,9 @@ protected virtual Phoneme[] AssignAllAffixes(List phonemes, Note[] note
int noteIndex = 0;
for (int i = 0; i < phonemes.Count; i++) {
var attr = notes[0].phonemeAttributes?.FirstOrDefault(attr => attr.index == i) ?? default;
- string alt = attr.alternate?.ToString() ?? string.Empty;
- string color = attr.voiceColor;
- int toneShift = attr.toneShift;
+ string alt = (attr.alternate ?? GetParentAlternate())?.ToString() ?? string.Empty;
+ string color = attr.voiceColor ?? GetParentVoiceColor();
+ int toneShift = attr.toneShift ?? GetParentToneShift();
var phoneme = phonemes[i];
while (noteIndex < notes.Length - 1 && notes[noteIndex].position - notes[0].position < phoneme.position) {
noteIndex++;
@@ -692,9 +692,9 @@ protected virtual Note[] HandleNotEnoughNotes(Note[] notes, List vowelIds)
///
protected virtual string[] HandleWordNotFound(Note note) {
var attr = note.phonemeAttributes?.FirstOrDefault(attr => attr.index == 0) ?? default;
- string alt = attr.alternate?.ToString() ?? string.Empty;
- string color = attr.voiceColor;
- int toneShift = attr.toneShift;
+ string alt = (attr.alternate ?? GetParentAlternate())?.ToString() ?? string.Empty;
+ string color = attr.voiceColor ?? GetParentVoiceColor();
+ int toneShift = attr.toneShift ?? GetParentToneShift();
var mpdlyric = MapPhoneme(note.lyric, note.tone + toneShift, color, alt, singer);
if(HasOto(mpdlyric, note.tone)){
error = mpdlyric;
diff --git a/OpenUtau.Plugin.Builtin/ThaiVCCVPhonemizer.cs b/OpenUtau.Plugin.Builtin/ThaiVCCVPhonemizer.cs
index 6fd646a49..9dc3e2db5 100644
--- a/OpenUtau.Plugin.Builtin/ThaiVCCVPhonemizer.cs
+++ b/OpenUtau.Plugin.Builtin/ThaiVCCVPhonemizer.cs
@@ -68,7 +68,7 @@ private bool checkOtoUntilHit(string[] input, Note note, out UOto oto) {
var attr = note.phonemeAttributes?.FirstOrDefault(attr => attr.index == 0) ?? default;
foreach (string test in input) {
- if (singer.TryGetMappedOto(test, note.tone + attr.toneShift, attr.voiceColor, out var otoCandidacy)) {
+ if (singer.TryGetMappedOto(test, note.tone + (attr.toneShift ?? GetParentToneShift()), attr.voiceColor ?? GetParentVoiceColor(), out var otoCandidacy)) {
oto = otoCandidacy;
return true;
}
@@ -180,7 +180,7 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN
nextCheck = nextTh.Consonant + nextTh.Dipthong + nextTh.Vowel;
}
var nextAttr = nextNeighbour.Value.phonemeAttributes?.FirstOrDefault(attr => attr.index == 0) ?? default;
- if (singer.TryGetMappedOto(nextCheck, nextNeighbour.Value.tone + nextAttr.toneShift, nextAttr.voiceColor, out var nextOto)) {
+ if (singer.TryGetMappedOto(nextCheck, nextNeighbour.Value.tone + (nextAttr.toneShift ?? GetParentToneShift()), nextAttr.voiceColor ?? GetParentVoiceColor(), out var nextOto)) {
if (oto.Overlap > 0) {
vcPosition = noteDuration - MsToTick(nextOto.Overlap) - MsToTick(nextOto.Preutter);
}
diff --git a/OpenUtau.Plugin.Builtin/TurkishCVVCPhonemizer.cs b/OpenUtau.Plugin.Builtin/TurkishCVVCPhonemizer.cs
index 5d25be093..d4a4f555c 100644
--- a/OpenUtau.Plugin.Builtin/TurkishCVVCPhonemizer.cs
+++ b/OpenUtau.Plugin.Builtin/TurkishCVVCPhonemizer.cs
@@ -21,17 +21,17 @@ public class TurkishCVVCPhonemizer : Phonemizer {
private bool checkOtoUntilHit(string[] input, Note note, out UOto oto) {
oto = default;
var attr = note.phonemeAttributes?.FirstOrDefault(attr => attr.index == 0) ?? default;
+ string color = attr.voiceColor ?? GetParentVoiceColor();
+ int shift = attr.toneShift ?? GetParentToneShift();
+ int? alt = attr.alternate ?? GetParentAlternate();
var otos = new List();
foreach (string test in input) {
- if (singer.TryGetMappedOto(test + attr.alternate, note.tone + attr.toneShift, attr.voiceColor, out var otoAlt)) {
- otos.Add(otoAlt);
- } else if (singer.TryGetMappedOto(test, note.tone + attr.toneShift, attr.voiceColor, out var otoCandidacy)) {
+ if (singer.TryGetMappedOto(test + alt, note.tone + shift, color, out var otoCandidacy)) {
otos.Add(otoCandidacy);
}
}
- string color = attr.voiceColor ?? "";
if (otos.Count > 0) {
if (otos.Any(oto => (oto.Color ?? string.Empty) == color)) {
oto = otos.Find(oto => (oto.Color ?? string.Empty) == color);
@@ -279,7 +279,7 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN
if (nextNeighbour != null) {
isEndCoeff = 1;
var attr0 = nextNeighbour.Value.phonemeAttributes?.FirstOrDefault(attr => attr.index == 0) ?? default; //next first
- if (singer.TryGetMappedOto(getNoteStart(phonemesNext, phonemesCurrent)[0], note.tone + attr0.toneShift, attr0.voiceColor, out var oto0)) {
+ if (singer.TryGetMappedOto(getNoteStart(phonemesNext, phonemesCurrent)[0], note.tone + (attr0.toneShift ?? GetParentToneShift()), attr0.voiceColor ?? GetParentVoiceColor(), out var oto0)) {
// If overlap is a negative value, vcLength is longer than Preutter
if (oto0.Overlap < 0)
lastLengthFromOto = timeAxis.MsPosToTickPos(oto0.Preutter - oto0.Overlap);
@@ -289,7 +289,7 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN
}
// vcLength depends on the Vel of the note
var attr1 = note.phonemeAttributes?.FirstOrDefault(attr => attr.index == 1) ?? default; // current last (noteEnd)
- var vcLength = Convert.ToInt32(Math.Min(totalDuration / (2 * isEndCoeff), lastLengthFromOto * isCVCoeff * (attr1.consonantStretchRatio ?? 1)));
+ var vcLength = Convert.ToInt32(Math.Min(totalDuration / (2 * isEndCoeff), lastLengthFromOto * isCVCoeff * (attr1.consonantStretchRatio ?? GetParentConsonantStretchRatio())));
if (noteEndCC == "") {
return new Result {
@@ -307,7 +307,7 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN
int ccLengthFromOto = 60;
var attr2 = note.phonemeAttributes?.FirstOrDefault(attr => attr.index == 2) ?? default;
if (nextNeighbour != null) {
- if (singer.TryGetMappedOto(noteEndCC, note.tone + attr2.toneShift, attr2.voiceColor, out var oto1)) {
+ if (singer.TryGetMappedOto(noteEndCC, note.tone + (attr2.toneShift ?? GetParentToneShift()), attr2.voiceColor ?? GetParentVoiceColor(), out var oto1)) {
// If overlap is a negative value, vcLength is longer than Preutter
if (oto1.Overlap < 0) {
ccLengthFromOto = timeAxis.MsPosToTickPos(oto1.Preutter - oto1.Overlap);
@@ -316,8 +316,8 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN
}
}
}
- vcLength = Convert.ToInt32(Math.Min(totalDuration / 3, ccLengthFromOto * (attr1.consonantStretchRatio ?? 1)));
- var ccLength = Convert.ToInt32(Math.Min(totalDuration / 3, lastLengthFromOto * (attr2.consonantStretchRatio ?? 1)));
+ vcLength = Convert.ToInt32(Math.Min(totalDuration / 3, ccLengthFromOto * (attr1.consonantStretchRatio ?? GetParentConsonantStretchRatio())));
+ var ccLength = Convert.ToInt32(Math.Min(totalDuration / 3, lastLengthFromOto * (attr2.consonantStretchRatio ?? GetParentConsonantStretchRatio())));
List exp = new List();
PhonemeExpression e = new PhonemeExpression() { abbr = Core.Format.Ustx.VOL, value = 70 };
diff --git a/OpenUtau.Plugin.Builtin/VietnameseCVVCPhonemizer.cs b/OpenUtau.Plugin.Builtin/VietnameseCVVCPhonemizer.cs
index 66881e045..6cd89635c 100644
--- a/OpenUtau.Plugin.Builtin/VietnameseCVVCPhonemizer.cs
+++ b/OpenUtau.Plugin.Builtin/VietnameseCVVCPhonemizer.cs
@@ -1323,9 +1323,9 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN
int noteIndex = 0;
for (int i = 0; i < phonemes.Count; i++) {
var attr = note.phonemeAttributes?.FirstOrDefault(attr => attr.index == i) ?? default;
- string alt = attr.alternate?.ToString() ?? string.Empty;
- string color = attr.voiceColor;
- int toneShift = attr.toneShift;
+ string alt = (attr.alternate ?? GetParentAlternate())?.ToString() ?? string.Empty;
+ string color = attr.voiceColor ?? GetParentVoiceColor();
+ int toneShift = attr.toneShift ?? GetParentToneShift();
var phoneme1 = phonemes[i];
while (noteIndex < notes.Length - 1 && notes[noteIndex].position - note.position < phoneme1.position) {
noteIndex++;
diff --git a/OpenUtau.Plugin.Builtin/VietnameseVCVPhonemizer.cs b/OpenUtau.Plugin.Builtin/VietnameseVCVPhonemizer.cs
index 41f6826fb..df41697d8 100644
--- a/OpenUtau.Plugin.Builtin/VietnameseVCVPhonemizer.cs
+++ b/OpenUtau.Plugin.Builtin/VietnameseVCVPhonemizer.cs
@@ -1146,9 +1146,9 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN
int noteIndex = 0;
for (int i = 0; i < phonemes.Count; i++) {
var attr = note.phonemeAttributes?.FirstOrDefault(attr => attr.index == i) ?? default;
- string alt = attr.alternate?.ToString() ?? string.Empty;
- string color = attr.voiceColor;
- int toneShift = attr.toneShift;
+ string alt = (attr.alternate ?? GetParentAlternate())?.ToString() ?? string.Empty;
+ string color = attr.voiceColor ?? GetParentVoiceColor();
+ int toneShift = attr.toneShift ?? GetParentToneShift();
var phoneme1 = phonemes[i];
while (noteIndex < notes.Length - 1 && notes[noteIndex].position - note.position < phoneme1.position) {
noteIndex++;
diff --git a/OpenUtau.Plugin.Builtin/VietnameseVINAPhonemizer.cs b/OpenUtau.Plugin.Builtin/VietnameseVINAPhonemizer.cs
index 395181f9a..cccee2e89 100644
--- a/OpenUtau.Plugin.Builtin/VietnameseVINAPhonemizer.cs
+++ b/OpenUtau.Plugin.Builtin/VietnameseVINAPhonemizer.cs
@@ -2417,9 +2417,9 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN
int noteIndex = 0;
for (int i = 0; i < phonemes.Count; i++) {
var attr = note.phonemeAttributes?.FirstOrDefault(attr => attr.index == i) ?? default;
- string alt = attr.alternate?.ToString() ?? string.Empty;
- string color = attr.voiceColor;
- int toneShift = attr.toneShift;
+ string alt = (attr.alternate ?? GetParentAlternate())?.ToString() ?? string.Empty;
+ string color = attr.voiceColor ?? GetParentVoiceColor();
+ int toneShift = attr.toneShift ?? GetParentToneShift();
var phoneme1 = phonemes[i];
while (noteIndex < notes.Length - 1 && notes[noteIndex].position - note.position < phoneme1.position) {
noteIndex++;
diff --git a/OpenUtau.Test/Plugins/PhonemizerTestBase.cs b/OpenUtau.Test/Plugins/PhonemizerTestBase.cs
index 41dedc2be..0b533ca17 100644
--- a/OpenUtau.Test/Plugins/PhonemizerTestBase.cs
+++ b/OpenUtau.Test/Plugins/PhonemizerTestBase.cs
@@ -148,7 +148,7 @@ void RunPhonemizeTest(string singerName, List groups, string[
index = j,
consonantStretchRatio = 1,
toneShift = phonemeParams.shift,
- alternate = phonemeParams.alt,
+ alternate = phonemeParams.alt == 0 ? null : phonemeParams.alt, // 0 means no alt (nothing added)
voiceColor = phonemeParams.color
};
}