diff --git a/OpenUtau.Core/Ustx/UExpression.cs b/OpenUtau.Core/Ustx/UExpression.cs index 8ccf660a1..cf9e294ba 100644 --- a/OpenUtau.Core/Ustx/UExpression.cs +++ b/OpenUtau.Core/Ustx/UExpression.cs @@ -116,5 +116,7 @@ public UExpression Clone() { value = value, }; } + + public override string ToString() => $"{abbr.ToUpper()}: {value}"; } } diff --git a/OpenUtau.Core/Ustx/UProject.cs b/OpenUtau.Core/Ustx/UProject.cs index 8597b8e19..c8b57d9b2 100644 --- a/OpenUtau.Core/Ustx/UProject.cs +++ b/OpenUtau.Core/Ustx/UProject.cs @@ -90,23 +90,27 @@ public void MargeExpression(string oldAbbr, string newAbbr) { parts.Where(p => p is UVoicePart) .OfType() .ForEach(p => p.notes.ForEach(n => ConvertNoteExp(n, tracks[p.trackNo]))); - } else if (voiceParts != null &&voiceParts.Count > 0) { + } else if (voiceParts != null && voiceParts.Count > 0) { voiceParts.ForEach(p => p.notes.ForEach(n => ConvertNoteExp(n, tracks[p.trackNo]))); } expressions.Remove(oldAbbr); void ConvertNoteExp(UNote note, UTrack track) { if (note.phonemeExpressions.Any(e => e.abbr == oldAbbr)) { - note.phonemeExpressions.ForEach(oldExp => { + var toRemove = new List(); + note.phonemeExpressions.Where(e => e.abbr == oldAbbr).ForEach(oldExp => { if (!note.phonemeExpressions.Any(newExp => newExp.abbr == newAbbr && newExp.index == oldExp.index)) { + // When there is only old exp, convert it to new exp oldExp.abbr = newAbbr; if (track.TryGetExpDescriptor(this, newAbbr, out var descriptor)) { oldExp.descriptor = descriptor; } } else { - note.phonemeExpressions.Remove(oldExp); + // When both old and new exp exist, remove the old one + toRemove.Add(oldExp); } }); + toRemove.ForEach(exp => note.phonemeExpressions.Remove(exp)); } } }