public UPhoneme Clone(UNote newParent) { var p = new UPhoneme() { Parent = newParent }; return(p); }
public UPhoneme Clone(UNote newParent) { var p = new UPhoneme() { Parent = newParent }; return p; }
private List<int> BuildPitchData(UPhoneme phoneme, UVoicePart part, UProject project) { List<int> pitches = new List<int>(); UNote lastNote = part.Notes.OrderByDescending(x => x).Where(x => x.CompareTo(phoneme.Parent) < 0).FirstOrDefault(); UNote nextNote = part.Notes.Where(x => x.CompareTo(phoneme.Parent) > 0).FirstOrDefault(); // Get relevant pitch points List<PitchPoint> pps = new List<PitchPoint>(); bool lastNoteInvolved = lastNote != null && phoneme.Overlapped; bool nextNoteInvolved = nextNote != null && nextNote.Phonemes[0].Overlapped; double lastVibratoStartMs = 0; double lastVibratoEndMs = 0; double vibratoStartMs = 0; double vibratoEndMs = 0; if (lastNoteInvolved) { double offsetMs = DocManager.Inst.Project.TickToMillisecond(phoneme.Parent.PosTick - lastNote.PosTick); foreach (PitchPoint pp in lastNote.PitchBend.Points) { var newpp = pp.Clone(); newpp.X -= offsetMs; newpp.Y -= (phoneme.Parent.NoteNum - lastNote.NoteNum) * 10; pps.Add(newpp); } if (lastNote.Vibrato.Depth != 0) { lastVibratoStartMs = -DocManager.Inst.Project.TickToMillisecond(lastNote.DurTick) * lastNote.Vibrato.Length / 100; lastVibratoEndMs = 0; } } foreach (PitchPoint pp in phoneme.Parent.PitchBend.Points) pps.Add(pp); if (phoneme.Parent.Vibrato.Depth != 0) { vibratoEndMs = DocManager.Inst.Project.TickToMillisecond(phoneme.Parent.DurTick); vibratoStartMs = vibratoEndMs * (1 - phoneme.Parent.Vibrato.Length / 100); } if (nextNoteInvolved) { double offsetMs = DocManager.Inst.Project.TickToMillisecond(phoneme.Parent.PosTick - nextNote.PosTick); foreach (PitchPoint pp in nextNote.PitchBend.Points) { var newpp = pp.Clone(); newpp.X -= offsetMs; newpp.Y -= (phoneme.Parent.NoteNum - nextNote.NoteNum) * 10; pps.Add(newpp); } } double startMs = DocManager.Inst.Project.TickToMillisecond(phoneme.PosTick) - phoneme.Oto.Preutter; double endMs = DocManager.Inst.Project.TickToMillisecond(phoneme.DurTick) - (nextNote != null && nextNote.Phonemes[0].Overlapped ? nextNote.Phonemes[0].Preutter - nextNote.Phonemes[0].Overlap : 0); if (pps.Count > 0) { if (pps.First().X > startMs) pps.Insert(0, new PitchPoint(startMs, pps.First().Y)); if (pps.Last().X < endMs) pps.Add(new PitchPoint(endMs, pps.Last().Y)); } else { throw new Exception("Zero pitch points."); } // Interpolation const int intervalTick = 5; double intervalMs = DocManager.Inst.Project.TickToMillisecond(intervalTick); double currMs = startMs; int i = 0; while (currMs < endMs) { while (pps[i + 1].X < currMs) i++; double pit = MusicMath.InterpolateShape(pps[i].X, pps[i + 1].X, pps[i].Y, pps[i + 1].Y, currMs, pps[i].Shape); pit *= 10; // Apply vibratos if (currMs < lastVibratoEndMs && currMs >= lastVibratoStartMs) pit += InterpolateVibrato(lastNote.Vibrato, currMs - lastVibratoStartMs); if (currMs < vibratoEndMs && currMs >= vibratoStartMs) pit += InterpolateVibrato(phoneme.Parent.Vibrato, currMs - vibratoStartMs); pitches.Add((int)pit); currMs += intervalMs; } return pitches; }
public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer) { UPhoneme result = new UPhoneme() { PosTick = Convert.ToInt32(dictionary["pos"]), Phoneme = dictionary["pho"] as string, AutoEnvelope = Convert.ToBoolean(dictionary["autoenv"]), AutoRemapped = Convert.ToBoolean(dictionary["remap"]) }; if (!result.AutoEnvelope) { var env = dictionary["env"] as ArrayList; for (int i = 0; i < 10; i++) { if (i % 2 == 0) result.Envelope.Points[i / 2].X = Convert.ToDouble(env[i]); else result.Envelope.Points[i / 2].Y = Convert.ToDouble(env[i]); } } return result; }
private RenderItem BuildRenderItem(UPhoneme phoneme, UVoicePart part, UProject project) { USinger singer = project.Tracks[part.TrackNo].Singer; string rawfile = Lib.EncodingUtil.ConvertEncoding(singer.FileEncoding, singer.PathEncoding, phoneme.Oto.File); rawfile = Path.Combine(singer.Path, rawfile); double strechRatio = Math.Pow(2, 1.0 - (double)(int)phoneme.Parent.Expressions["velocity"].Data / 100); double length = phoneme.Oto.Preutter * strechRatio + phoneme.Envelope.Points[4].X; double requiredLength = Math.Ceiling(length / 50 + 1) * 50; double lengthAdjustment = phoneme.TailIntrude == 0 ? phoneme.Preutter : phoneme.Preutter - phoneme.TailIntrude + phoneme.TailOverlap; RenderItem item = new RenderItem() { // For resampler RawFile = rawfile, NoteNum = phoneme.Parent.NoteNum, Velocity = (int)phoneme.Parent.Expressions["velocity"].Data, Volume = (int)phoneme.Parent.Expressions["volume"].Data, StrFlags = phoneme.Parent.GetResamplerFlags(), PitchData = BuildPitchData(phoneme, part, project), RequiredLength = (int)requiredLength, Oto = phoneme.Oto, Tempo = project.BPM, // For connector SkipOver = phoneme.Oto.Preutter * strechRatio - phoneme.Preutter, PosMs = project.TickToMillisecond(part.PosTick + phoneme.Parent.PosTick + phoneme.PosTick) - phoneme.Preutter, DurMs = project.TickToMillisecond(phoneme.DurTick) + lengthAdjustment, Envelope = phoneme.Envelope.Points }; return item; }