Skip to content

Commit

Permalink
Merge pull request #867 from maiko3tattun/1004_FixParseUstNote
Browse files Browse the repository at this point in the history
Fix parse pitchbend from plugins
  • Loading branch information
stakira authored Oct 20, 2023
2 parents ee83290 + 7d890b2 commit 3e079fa
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 37 deletions.
3 changes: 2 additions & 1 deletion OpenUtau.Core/Classic/Ust.cs
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,8 @@ private static void ParseNote(UNote note, int lastNotePos, int lastNoteEnd, List
lyric = note.lyric,
position = note.position,
duration = note.duration,
noteNum = note.tone
noteNum = note.tone,
pitch = note.pitch
};
ustNote.Parse(lastNotePos, lastNoteEnd, iniLines, out noteTempo);
note.lyric = ustNote.lyric;
Expand Down
85 changes: 57 additions & 28 deletions OpenUtau.Core/Classic/UstNote.cs
Original file line number Diff line number Diff line change
Expand Up @@ -277,48 +277,77 @@ void ParseEnvelope(string ust, IniLine ustLine) {
}

void ParsePitchBend(string pbs, string pbw, string pby, string pbm) {
var pitch = this.pitch != null ? this.pitch.Clone() : new UPitch() ;
var points = pitch.data;

// PBS
if (!string.IsNullOrWhiteSpace(pbs)) {
var pitch = new UPitch();
var points = pitch.data;
points.Clear();
// PBS
var parts = pbs.Contains(';') ? pbs.Split(';') : pbs.Split(',');
float pbsX = parts.Length >= 1 && ParseFloat(parts[0], out pbsX) ? pbsX : 0;
float pbsY = parts.Length >= 2 && ParseFloat(parts[1], out pbsY) ? pbsY : 0;
points.Add(new PitchPoint(pbsX, pbsY));
// PBW, PBY
var x = points.First().X;
if (!string.IsNullOrWhiteSpace(pbw)) {
var w = pbw.Split(',').Select(s => ParseFloat(s, out var v) ? v : 0).ToList();
var y = (pby ?? "").Split(',').Select(s => ParseFloat(s, out var v) ? v : 0).ToList();
if(points.Count > 0) {
points[0] = new PitchPoint(pbsX, pbsY);
} else {
points.Add(new PitchPoint(pbsX, pbsY));
}
}
if (points.Count == 0) {
return;
}
// PBW, PBY
var x = points.First().X;
var w = new List<float>();
var y = new List<float>();
if (!string.IsNullOrWhiteSpace(pbw)) {
w = pbw.Split(',').Select(s => ParseFloat(s, out var v) ? v : 0).ToList();
}
if (!string.IsNullOrWhiteSpace(pby)) {
y = pby.Split(',').Select(s => ParseFloat(s, out var v) ? v : 0).ToList();
}
if (w.Count != 0 || y.Count != 0) {
if (points.Count > 1 && points.Count - 1 == w.Count && y.Count == 0) { // replace w only
for (var i = 0; i < w.Count(); i++) {
x += w[i];
points[i + 1].X = x;
}
} else if (points.Count > 1 && w.Count == 0 && points.Count - 1 == y.Count) { // replace y only
for (var i = 0; i < y.Count(); i++) {
points[i + 1].Y = y[i];
}
} else {
while (w.Count > y.Count) {
y.Add(0);
}
for (var i = points.Count - 1; i > 0; i--) {
points.Remove(points[i]);
}
for (var i = 0; i < w.Count(); i++) {
x += w[i];
points.Add(new PitchPoint(x, y[i]));
}
}
// PBM
if (!string.IsNullOrWhiteSpace(pbm)) {
var m = pbm.Split(new[] { ',' });
for (var i = 0; i < m.Count() && i < points.Count; i++) {
switch (m[i]) {
case "r":
points[i].shape = PitchPointShape.o;
break;
case "s":
points[i].shape = PitchPointShape.l;
break;
case "j":
points[i].shape = PitchPointShape.i;
break;
default:
points[i].shape = PitchPointShape.io;
break;
}
}
// PBM
if (!string.IsNullOrWhiteSpace(pbm)) {
var m = pbm.Split(new[] { ',' });
for (var i = 0; i < m.Count() && i < points.Count; i++) {
switch (m[i]) {
case "r":
points[i].shape = PitchPointShape.o;
break;
case "s":
points[i].shape = PitchPointShape.l;
break;
case "j":
points[i].shape = PitchPointShape.i;
break;
default:
points[i].shape = PitchPointShape.io;
break;
}
}
}
if (points.Count > 1) {
this.pitch = pitch;
}
}
Expand Down
55 changes: 47 additions & 8 deletions OpenUtau.Test/Classic/UstTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,12 @@ public void EqualInLyric() {
Length=15
Lyric=A==B[C=D],EFG
NoteNum=60
PreUtterance=";
PreUtterance=
VBR=80,200,20,20,20,0,-50,0
PBW=292,183
PBS=-222;-19
PBY=-20.7,
";
using (var stream = new MemoryStream()) {
using (var writer = new StreamWriter(stream, leaveOpen: true)) {
writer.Write(ust);
Expand All @@ -73,6 +78,12 @@ public void EqualInLyric() {
Assert.Single(part.notes);
Assert.Equal("A==B[C=D],EFG", part.notes.First().lyric);
Assert.Equal(60, part.notes.First().tone);
Assert.Equivalent(new UPitch {data = new List<PitchPoint> {
new PitchPoint { X = -222, Y = -19, shape = PitchPointShape.io},
new PitchPoint { X = 70, Y = -20.7f, shape = PitchPointShape.io}, // X = -222 + 292 = 70
new PitchPoint { X = 253, Y = 0, shape = PitchPointShape.io} // X = 70 + 183 = 253
}, snapFirst = false } , part.notes.First().pitch);
Assert.Equivalent(new UVibrato { length = 80, period = 200, depth = 20, @in = 20, @out = 20, shift = 0, drift = -50, volLink = 0 }, part.notes.First().vibrato);
}
}
}
Expand All @@ -94,27 +105,37 @@ public void ParsePluginParseNoteTest() {

var before = UNote.Create();
before.lyric = "a";
before.duration = 10;
before.duration = 100;

var first = UNote.Create();
first.lyric = "ka";
first.duration = 20;
first.duration = 200;
first.pitch.data = new List<PitchPoint> {
new PitchPoint { X = -50, Y = 0, shape = PitchPointShape.io},
new PitchPoint { X = 0, Y = 10, shape = PitchPointShape.io},
new PitchPoint { X = 93.75f, Y = -12.2f, shape = PitchPointShape.io},
new PitchPoint { X = 194.7f, Y = 0, shape = PitchPointShape.io}
};

var second = UNote.Create();
second.lyric = "r";
second.duration = 30;
second.duration = 300;

var third = UNote.Create();
third.lyric = "ta";
third.duration = 40;
third.duration = 400;
third.pitch.data = new List<PitchPoint> {
new PitchPoint { X = -100, Y = 0, shape = PitchPointShape.io},
new PitchPoint { X = 130, Y = 0, shape = PitchPointShape.io}
};

var last = UNote.Create();
last.lyric = "na";
last.duration = 50;
last.duration = 500;

var after = UNote.Create();
after.lyric = "ha";
after.duration = 60;
after.duration = 600;

part.notes.Add(before);
part.notes.Add(first);
Expand All @@ -141,12 +162,16 @@ public void ParsePluginParseNoteTest() {
writer.WriteLine("[#0000]");
writer.WriteLine("Length=480");
writer.WriteLine("Lyric=A");
writer.WriteLine("PBY=10,-10,0"); // Change only height of the third point
writer.WriteLine("[#0001]");
writer.WriteLine("Length=480");
writer.WriteLine("Lyric=R");
// duration is null (change)
writer.WriteLine("[#0002]");
writer.WriteLine("Lyric=zo");
writer.WriteLine("PBS=-50"); // Reset points
writer.WriteLine("PBW=100");
writer.WriteLine("PBY=0");
// duration is zero (delete)
writer.WriteLine("[#0003]");
writer.WriteLine("Length=");
Expand All @@ -164,8 +189,22 @@ public void ParsePluginParseNoteTest() {
Assert.Equal(3, toAdd.Count);
Assert.Equal(480, toAdd[0].duration);
Assert.Equal("A", toAdd[0].lyric);
Assert.Equal(40, toAdd[1].duration);
Assert.Equivalent(new UPitch {
data = new List<PitchPoint> {
new PitchPoint { X = -50, Y = 0, shape = PitchPointShape.io},
new PitchPoint { X = 0, Y = 10, shape = PitchPointShape.io},
new PitchPoint { X = 93.75f, Y = -10, shape = PitchPointShape.io},
new PitchPoint { X = 194.7f, Y = 0, shape = PitchPointShape.io}
}, snapFirst = true
}, toAdd[0].pitch);
Assert.Equal(400, toAdd[1].duration);
Assert.Equal("zo", toAdd[1].lyric);
Assert.Equivalent(new UPitch {
data = new List<PitchPoint> {
new PitchPoint { X = -50, Y = 0, shape = PitchPointShape.io},
new PitchPoint { X = 50, Y = 0, shape = PitchPointShape.io}
}, snapFirst = true
}, toAdd[1].pitch);
Assert.Equal(240, toAdd[2].duration);
Assert.Equal("me", toAdd[2].lyric);
} finally {
Expand Down

0 comments on commit 3e079fa

Please sign in to comment.