public MoveNoteCommand(UVoicePart part, List<UNote> notes, int deltaPos, int deltaNoteNum) { this.Part = part; this.Notes = notes.ToArray(); this.DeltaPos = deltaPos; this.DeltaNoteNum = deltaNoteNum; }
public MoveNoteCommand(UVoicePart part, UNote note, int deltaPos, int deltaNoteNum) { this.Part = part; this.Notes = new UNote[] { note }; this.DeltaPos = deltaPos; this.DeltaNoteNum = deltaNoteNum; }
public DeletePitchPointCommand(UVoicePart part, UNote note, int index) { this.Part = part; this.Note = note; this.Index = index; this.Point = Note.PitchBend.Points[Index]; }
public SetIntExpCommand(UVoicePart part, UNote note, string key, int newValue) { this.Part = part; this.Note = note; this.Key = key; this.NewValue = newValue; this.OldValue = (int)Note.Expressions[Key].Data; }
public void ResamplePart(UVoicePart part, UProject project, IResamplerDriver engine, Action<SequencingSampleProvider> resampleDoneCallback) { this.resampleDoneCallback = resampleDoneCallback; BackgroundWorker worker = new BackgroundWorker(); worker.WorkerReportsProgress = true; worker.DoWork += worker_DoWork; worker.RunWorkerCompleted += worker_RunWorkerCompleted; worker.ProgressChanged += worker_ProgressChanged; worker.RunWorkerAsync(new Tuple<UVoicePart, UProject, IResamplerDriver>(part, project, engine)); }
private List<RenderItem> RenderAsync(UVoicePart part, UProject project, IResamplerDriver engine, BackgroundWorker worker) { List<RenderItem> renderItems = new List<RenderItem>(); System.Diagnostics.Stopwatch watch = new Stopwatch(); watch.Start(); System.Diagnostics.Debug.WriteLine("Resampling start"); lock (part) { string cacheDir = PathManager.Inst.GetCachePath(project.FilePath); string[] cacheFiles = Directory.EnumerateFiles(cacheDir).ToArray(); int count = 0, i = 0; foreach (UNote note in part.Notes) foreach (UPhoneme phoneme in note.Phonemes) count++; foreach (UNote note in part.Notes) { foreach (UPhoneme phoneme in note.Phonemes) { RenderItem item = BuildRenderItem(phoneme, part, project); var sound = RenderCache.Inst.Get(item.HashParameters()); if (sound == null) { string cachefile = Path.Combine(cacheDir, string.Format("{0:x}.wav", item.HashParameters())); if (!cacheFiles.Contains(cachefile)) { System.Diagnostics.Debug.WriteLine("Sound {0:x} resampling {1}", item.HashParameters(), item.GetResamplerExeArgs()); DriverModels.EngineInput engineArgs = DriverModels.CreateInputModel(item, 0); System.IO.Stream output = engine.DoResampler(engineArgs); sound = new CachedSound(output); } else { System.Diagnostics.Debug.WriteLine("Sound {0:x} found on disk {1}", item.HashParameters(), item.GetResamplerExeArgs()); sound = new CachedSound(cachefile); } RenderCache.Inst.Put(item.HashParameters(), sound, engine.GetInfo().ToString()); } else System.Diagnostics.Debug.WriteLine("Sound {0} found in cache {1}", item.HashParameters(), item.GetResamplerExeArgs()); item.Sound = sound; renderItems.Add(item); worker.ReportProgress(100 * ++i / count, string.Format("Resampling \"{0}\" {1}/{2}", phoneme.Phoneme, i, count)); } } } watch.Stop(); System.Diagnostics.Debug.WriteLine("Resampling end"); System.Diagnostics.Debug.WriteLine("Total cache size {0:n0} bytes", RenderCache.Inst.TotalMemSize); System.Diagnostics.Debug.WriteLine("Total time {0} ms", watch.Elapsed.TotalMilliseconds); return renderItems; }
public void ResnapPitchBend(UVoicePart part) { UNote lastNote = null; foreach (UNote note in part.Notes) { if (!note.PitchBend.SnapFirst) { if (note.Phonemes.Count > 0 && note.Phonemes[0].Overlapped && lastNote != null) if (note.PitchBend.Points[0].Y == (lastNote.NoteNum - note.NoteNum) * 10) note.PitchBend.SnapFirst = true; } lastNote = note; } }
public void UpdatePart(UVoicePart part) { lock (part) { if (part == null) return; CheckOverlappedNotes(part); UpdatePhonemeDurTick(part); UpdatePhonemeOto(part); UpdateOverlapAdjustment(part); UpdateEnvelope(part); UpdatePitchBend(part); DocManager.Inst.ExecuteCmd(new RedrawNotesNotification(), true); } }
private void UpdatePitchBend(UVoicePart part) { UNote lastNote = null; foreach (UNote note in part.Notes) { if (note.PitchBend.SnapFirst) { if (note.Phonemes.Count > 0 && lastNote != null && (note.Phonemes[0].Overlapped || note.PosTick == lastNote.EndTick)) note.PitchBend.Points[0].Y = (lastNote.NoteNum - note.NoteNum) * 10; else note.PitchBend.Points[0].Y = 0; } lastNote = note; } }
private void UpdateEnvelope(UVoicePart part) { foreach (UNote note in part.Notes) { foreach (UPhoneme phoneme in note.Phonemes) { phoneme.Envelope.Points[0].X = -phoneme.Preutter; phoneme.Envelope.Points[1].X = phoneme.Envelope.Points[0].X + (phoneme.Overlapped ? phoneme.Overlap : 5); phoneme.Envelope.Points[2].X = Math.Max(0, phoneme.Envelope.Points[1].X); phoneme.Envelope.Points[3].X = DocManager.Inst.Project.TickToMillisecond(phoneme.DurTick) - phoneme.TailIntrude; phoneme.Envelope.Points[4].X = phoneme.Envelope.Points[3].X + phoneme.TailOverlap; phoneme.Envelope.Points[1].Y = (int)phoneme.Parent.Expressions["volume"].Data; phoneme.Envelope.Points[1].X = phoneme.Envelope.Points[0].X + (phoneme.Overlapped ? phoneme.Overlap : 5) * (int)phoneme.Parent.Expressions["accent"].Data / 100.0; phoneme.Envelope.Points[1].Y = (int)phoneme.Parent.Expressions["accent"].Data * (int)phoneme.Parent.Expressions["volume"].Data / 100; phoneme.Envelope.Points[2].Y = (int)phoneme.Parent.Expressions["volume"].Data; phoneme.Envelope.Points[3].Y = (int)phoneme.Parent.Expressions["volume"].Data; phoneme.Envelope.Points[3].X -= (phoneme.Envelope.Points[3].X - phoneme.Envelope.Points[2].X) * (int)phoneme.Parent.Expressions["decay"].Data / 500; phoneme.Envelope.Points[3].Y *= 1.0 - (int)phoneme.Parent.Expressions["decay"].Data / 100.0; } } }
public ChangeNoteLyricCommand(UVoicePart part, UNote note, string newLyric) { this.Part = part; this.Note = note; this.NewLyric = newLyric; this.OldLyric = note.Lyric; }
public ResizeNoteCommand(UVoicePart part, UNote note, int deltaDur) { this.Part = part; this.Notes = new UNote[] { note }; this.DeltaDur = deltaDur; }
public ResizeNoteCommand(UVoicePart part, List<UNote> notes, int deltaDur) { this.Part = part; this.Notes = notes.ToArray(); this.DeltaDur = deltaDur; }
private void UpdatePhonemeDurTick(UVoicePart part) { UNote lastNote = null; UPhoneme lastPhoneme = null; foreach (UNote note in part.Notes) { foreach(UPhoneme phoneme in note.Phonemes) { phoneme.DurTick = phoneme.Parent.DurTick - phoneme.PosTick; if (lastPhoneme != null) if (lastPhoneme.Parent == phoneme.Parent) lastPhoneme.DurTick = phoneme.PosTick - lastPhoneme.PosTick; lastPhoneme = phoneme; } lastNote = note; } }
private void CheckOverlappedNotes(UVoicePart part) { UNote lastNote = null; foreach (UNote note in part.Notes) { if (lastNote != null && lastNote.EndTick > note.PosTick) { lastNote.Error = true; note.Error = true; } else note.Error = false; lastNote = note; } }
public RemoveNoteCommand(UVoicePart part, List<UNote> notes) { this.Part = part; this.Notes = notes.ToArray(); }
private void BuildVoicePartAudio(UVoicePart part, UProject project,IResamplerDriver engine) { ResamplerInterface ri = new ResamplerInterface(); ri.ResamplePart(part, project, engine, (o) => { this.BuildVoicePartDone(o, part, project); }); }
private void UpdateOverlapAdjustment(UVoicePart part) { UPhoneme lastPhoneme = null; UNote lastNote = null; foreach (UNote note in part.Notes) { foreach (UPhoneme phoneme in note.Phonemes) { if (lastPhoneme != null) { int gapTick = phoneme.Parent.PosTick + phoneme.PosTick - lastPhoneme.Parent.PosTick - lastPhoneme.EndTick; double gapMs = DocManager.Inst.Project.TickToMillisecond(gapTick); if (gapMs < phoneme.Preutter) { phoneme.Overlapped = true; double lastDurMs = DocManager.Inst.Project.TickToMillisecond(lastPhoneme.DurTick); double correctionRatio = (lastDurMs + Math.Min(0, gapMs)) / 2 / (phoneme.Preutter - phoneme.Overlap); if (phoneme.Preutter - phoneme.Overlap > gapMs + lastDurMs / 2) { phoneme.OverlapCorrection = true; phoneme.Preutter = gapMs + (phoneme.Preutter - gapMs) * correctionRatio; phoneme.Overlap *= correctionRatio; } else if (phoneme.Preutter > gapMs + lastDurMs) { phoneme.OverlapCorrection = true; phoneme.Overlap *= correctionRatio; phoneme.Preutter = gapMs + lastDurMs; } else phoneme.OverlapCorrection = false; lastPhoneme.TailIntrude = phoneme.Preutter - gapMs; lastPhoneme.TailOverlap = phoneme.Overlap; } else { phoneme.Overlapped = false; lastPhoneme.TailIntrude = 0; lastPhoneme.TailOverlap = 0; } } else phoneme.Overlapped = false; lastPhoneme = phoneme; } lastNote = note; } }
private void trackCanvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) { Point mousePos = e.GetPosition((UIElement)sender); var hit = VisualTreeHelper.HitTest(trackCanvas, mousePos).VisualHit; System.Diagnostics.Debug.WriteLine("Mouse hit " + hit.ToString()); if (Keyboard.Modifiers == ModifierKeys.Control || Keyboard.Modifiers == (ModifierKeys.Control | ModifierKeys.Shift)) { selectionStart = new Point(trackVM.CanvasToQuarter(mousePos.X), trackVM.CanvasToTrack(mousePos.Y)); if (Keyboard.IsKeyUp(Key.LeftShift) && Keyboard.IsKeyUp(Key.RightShift)) trackVM.DeselectAll(); if (selectionBox == null) { selectionBox = new Rectangle() { Stroke = Brushes.Black, StrokeThickness = 2, Fill = ThemeManager.BarNumberBrush, Width = 0, Height = 0, Opacity = 0.5, RadiusX = 8, RadiusY = 8, IsHitTestVisible = false }; trackCanvas.Children.Add(selectionBox); Canvas.SetZIndex(selectionBox, 1000); selectionBox.Visibility = System.Windows.Visibility.Visible; } else { selectionBox.Width = 0; selectionBox.Height = 0; Canvas.SetZIndex(selectionBox, 1000); selectionBox.Visibility = System.Windows.Visibility.Visible; } Mouse.OverrideCursor = Cursors.Cross; } else if (hit is DrawingVisual) { PartElement partEl = ((DrawingVisual)hit).Parent as PartElement; _hitPartElement = partEl; if (!trackVM.SelectedParts.Contains(_hitPartElement.Part)) trackVM.DeselectAll(); if (e.ClickCount == 2) { if (partEl is VoicePartElement) // load part into midi window { if (midiWindow == null) midiWindow = new MidiWindow(); DocManager.Inst.ExecuteCmd(new LoadPartNotification(partEl.Part, trackVM.Project)); midiWindow.Show(); midiWindow.Focus(); } } else if (mousePos.X > partEl.X + partEl.VisualWidth - UIConstants.ResizeMargin && partEl is VoicePartElement) // resize { _resizePartElement = true; _resizeMinDurTick = trackVM.GetPartMinDurTick(_hitPartElement.Part); Mouse.OverrideCursor = Cursors.SizeWE; if (trackVM.SelectedParts.Count > 0) { _partResizeShortest = _hitPartElement.Part; foreach (UPart part in trackVM.SelectedParts) { if (part.DurTick - part.GetMinDurTick(trackVM.Project) < _partResizeShortest.DurTick - _partResizeShortest.GetMinDurTick(trackVM.Project)) _partResizeShortest = part; } _resizeMinDurTick = _partResizeShortest.GetMinDurTick(trackVM.Project); } DocManager.Inst.StartUndoGroup(); } else // move { _movePartElement = true; _partMoveRelativeTick = trackVM.CanvasToSnappedTick(mousePos.X) - _hitPartElement.Part.PosTick; _partMoveStartTick = partEl.Part.PosTick; Mouse.OverrideCursor = Cursors.SizeAll; if (trackVM.SelectedParts.Count > 0) { _partMovePartLeft = _partMovePartMin = _partMovePartMax = _hitPartElement.Part; foreach (UPart part in trackVM.SelectedParts) { if (part.PosTick < _partMovePartLeft.PosTick) _partMovePartLeft = part; if (part.TrackNo < _partMovePartMin.TrackNo) _partMovePartMin = part; if (part.TrackNo > _partMovePartMax.TrackNo) _partMovePartMax = part; } } DocManager.Inst.StartUndoGroup(); } } else { if (trackVM.CanvasToTrack(mousePos.Y) > trackVM.Project.Tracks.Count - 1) return; UVoicePart part = new UVoicePart() { PosTick = trackVM.CanvasToSnappedTick(mousePos.X), TrackNo = trackVM.CanvasToTrack(mousePos.Y), DurTick = trackVM.Project.Resolution * 4 / trackVM.Project.BeatUnit * trackVM.Project.BeatPerBar }; DocManager.Inst.StartUndoGroup(); DocManager.Inst.ExecuteCmd(new AddPartCommand(trackVM.Project, part)); DocManager.Inst.EndUndoGroup(); // Enable drag trackVM.DeselectAll(); _movePartElement = true; _hitPartElement = trackVM.GetPartElement(part); _partMoveRelativeTick = 0; _partMoveStartTick = part.PosTick; } ((UIElement)sender).CaptureMouse(); }
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; }
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; }
private void UpdatePhonemeOto(UVoicePart part) { var singer = DocManager.Inst.Project.Tracks[part.TrackNo].Singer; if (singer == null || !singer.Loaded) return; foreach (UNote note in part.Notes) { foreach (UPhoneme phoneme in note.Phonemes) { if (phoneme.AutoRemapped) { if (phoneme.Phoneme.StartsWith("?")) { phoneme.Phoneme = phoneme.Phoneme.Substring(1); phoneme.AutoRemapped = false; } else { string noteString = MusicMath.GetNoteString(note.NoteNum); if (singer.PitchMap.ContainsKey(noteString)) phoneme.RemappedBank = singer.PitchMap[noteString]; } } if (singer.AliasMap.ContainsKey(phoneme.PhonemeRemapped)) { phoneme.Oto = singer.AliasMap[phoneme.PhonemeRemapped]; phoneme.PhonemeError = false; phoneme.Overlap = phoneme.Oto.Overlap; phoneme.Preutter = phoneme.Oto.Preutter; int vel = (int)phoneme.Parent.Expressions["velocity"].Data; if (vel != 100) { double stretchRatio = Math.Pow(2, 1.0 - (double)vel / 100); phoneme.Overlap *= stretchRatio; phoneme.Preutter *= stretchRatio; } } else { phoneme.PhonemeError = true; phoneme.Overlap = 0; phoneme.Preutter = 0; } } } }
public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer) { UPart result = null; if (dictionary.ContainsKey("notes")) { result = new UVoicePart(); var _result = result as UVoicePart; var notes = dictionary["notes"] as ArrayList; foreach (var note in notes) { _result.Notes.Add(serializer.ConvertToType<UNote>(note)); } } else if (dictionary.ContainsKey("path")) result = Wave.CreatePart(dictionary["path"] as string); if (result != null) { result.Name = dictionary["name"] as string; result.Comment = dictionary["comment"] as string; result.TrackNo = Convert.ToInt32(dictionary["trackno"]); result.PosTick = Convert.ToInt32(dictionary["pos"]); result.DurTick = Convert.ToInt32(dictionary["dur"]); } return result; }
public RemoveNoteCommand(UVoicePart part, UNote note) { this.Part = part; this.Notes = new UNote[] { note }; }
static public UProject Load(string file, Encoding encoding = null) { int currentNoteIndex = 0; UstVersion version = UstVersion.Early; UstBlock currentBlock = UstBlock.None; string[] lines; try { if (encoding == null) lines = File.ReadAllLines(file, EncodingUtil.DetectFileEncoding(file)); else lines = File.ReadAllLines(file, encoding); } catch (Exception e) { DocManager.Inst.ExecuteCmd(new UserMessageNotification(e.GetType().ToString() + "\n" + e.Message)); return null; } UProject project = new UProject() { Resolution = 480, FilePath = file, Saved = false }; project.RegisterExpression(new IntExpression(null, "velocity","VEL") { Data = 100, Min = 0, Max = 200}); project.RegisterExpression(new IntExpression(null, "volume","VOL") { Data = 100, Min = 0, Max = 200}); project.RegisterExpression(new IntExpression(null, "gender","GEN") { Data = 0, Min = -100, Max = 100}); project.RegisterExpression(new IntExpression(null, "lowpass","LPF") { Data = 0, Min = 0, Max = 100}); project.RegisterExpression(new IntExpression(null, "highpass", "HPF") { Data = 0, Min = 0, Max = 100 }); project.RegisterExpression(new IntExpression(null, "accent", "ACC") { Data = 100, Min = 0, Max = 200 }); project.RegisterExpression(new IntExpression(null, "decay", "DEC") { Data = 0, Min = 0, Max = 100 }); var _track = new UTrack(); project.Tracks.Add(_track); _track.TrackNo = 0; UVoicePart part = new UVoicePart() { TrackNo = 0, PosTick = 0 }; project.Parts.Add(part); List<string> currentLines = new List<string>(); int currentTick = 0; UNote currentNote = null; foreach (string line in lines) { if (line.Trim().StartsWith(@"[#") && line.Trim().EndsWith(@"]")) { if (line.Equals(versionTag)) currentBlock = UstBlock.Version; else if (line.Equals(settingTag)) currentBlock = UstBlock.Setting; else { if (line.Equals(endTag)) currentBlock = UstBlock.Trackend; else { try { currentNoteIndex = int.Parse(line.Replace("[#", "").Replace("]", "")); } catch { DocManager.Inst.ExecuteCmd(new UserMessageNotification("Unknown ust format")); return null; } currentBlock = UstBlock.Note; } if (currentLines.Count != 0) { currentNote = NoteFromUst(project.CreateNote(), currentLines, version); currentNote.PosTick = currentTick; if (!currentNote.Lyric.Replace("R", "").Replace("r", "").Equals("")) part.Notes.Add(currentNote); currentTick += currentNote.DurTick; currentLines.Clear(); } } } else { if (currentBlock == UstBlock.Version) { if (line.StartsWith("UST Version")) { string v = line.Trim().Replace("UST Version", ""); if (v == "1.0") version = UstVersion.V1_0; else if (v == "1.1") version = UstVersion.V1_1; else if (v == "1.2") version = UstVersion.V1_2; else version = UstVersion.Unknown; } } if (currentBlock == UstBlock.Setting) { if (line.StartsWith("Tempo=")) { project.BPM = double.Parse(line.Trim().Replace("Tempo=", "")); if (project.BPM == 0) project.BPM = 120; } if (line.StartsWith("ProjectName=")) project.Name = line.Trim().Replace("ProjectName=", ""); if (line.StartsWith("VoiceDir=")) { string singerpath = line.Trim().Replace("VoiceDir=", ""); var singer = UtauSoundbank.GetSinger(singerpath, EncodingUtil.DetectFileEncoding(file), DocManager.Inst.Singers); if (singer == null) singer = new USinger() { Name = "", Path = singerpath }; project.Singers.Add(singer); project.Tracks[0].Singer = singer; } } else if (currentBlock == UstBlock.Note) { currentLines.Add(line); } else if (currentBlock == UstBlock.Trackend) { break; } } } if (currentBlock != UstBlock.Trackend) DocManager.Inst.ExecuteCmd(new UserMessageNotification("Unexpected ust file end")); part.DurTick = currentTick; return project; }
static public UProject Load(string file) { XmlDocument vsqx = new XmlDocument(); try { vsqx.Load(file); } catch (Exception e) { System.Windows.MessageBox.Show(e.GetType().ToString() + "\n" + e.Message); return null; } XmlNamespaceManager nsmanager = new XmlNamespaceManager(vsqx.NameTable); nsmanager.AddNamespace("v3", vsq3NameSpace); nsmanager.AddNamespace("v4", vsq4NameSpace); XmlNode root; string nsPrefix; // Detect vsqx version root = vsqx.SelectSingleNode("v3:vsq3", nsmanager); if (root != null) nsPrefix = "v3:"; else { root = vsqx.SelectSingleNode("v4:vsq4", nsmanager); if (root != null) nsPrefix = "v4:"; else { System.Windows.MessageBox.Show("Unrecognizable VSQx file format."); return null; } } UProject uproject = new UProject(); uproject.RegisterExpression(new IntExpression(null, "velocity", "VEL") { Data = 64, Min = 0, Max = 127 }); uproject.RegisterExpression(new IntExpression(null, "volume", "VOL") { Data = 100, Min = 0, Max = 200 }); uproject.RegisterExpression(new IntExpression(null, "opening", "OPE") { Data = 127, Min = 0, Max = 127 }); uproject.RegisterExpression(new IntExpression(null, "accent", "ACC") { Data = 50, Min = 0, Max = 100 }); uproject.RegisterExpression(new IntExpression(null, "decay", "DEC") { Data = 50, Min = 0, Max = 100 }); string bpmPath = string.Format("{0}masterTrack/{0}tempo/{0}{1}", nsPrefix, nsPrefix == "v3:" ? "bpm" : "v"); string beatperbarPath = string.Format("{0}masterTrack/{0}timeSig/{0}{1}", nsPrefix, nsPrefix == "v3:" ? "nume" : "nu"); string beatunitPath = string.Format("{0}masterTrack/{0}timeSig/{0}{1}", nsPrefix, nsPrefix == "v3:" ? "denomi" : "de"); string premeasurePath = string.Format("{0}masterTrack/{0}preMeasure", nsPrefix); string resolutionPath = string.Format("{0}masterTrack/{0}resolution", nsPrefix); string projectnamePath = string.Format("{0}masterTrack/{0}seqName", nsPrefix); string projectcommentPath = string.Format("{0}masterTrack/{0}comment", nsPrefix); string trackPath = string.Format("{0}vsTrack", nsPrefix); string tracknamePath = string.Format("{0}{1}", nsPrefix, nsPrefix == "v3:" ? "trackName" : "name"); string trackcommentPath = string.Format("{0}comment", nsPrefix); string tracknoPath = string.Format("{0}{1}", nsPrefix, nsPrefix == "v3:" ? "vsTrackNo" : "tNo"); string partPath = string.Format("{0}{1}", nsPrefix, nsPrefix == "v3:" ? "musicalPart" : "vsPart"); string partnamePath = string.Format("{0}{1}", nsPrefix, nsPrefix == "v3:" ? "partName" : "name"); string partcommentPath = string.Format("{0}comment", nsPrefix); string notePath = string.Format("{0}note", nsPrefix); string postickPath = string.Format("{0}{1}", nsPrefix, nsPrefix == "v3:" ? "posTick" : "t"); string durtickPath = string.Format("{0}{1}", nsPrefix, nsPrefix == "v3:" ? "durTick" : "dur"); string notenumPath = string.Format("{0}{1}", nsPrefix, nsPrefix == "v3:" ? "noteNum" : "n"); string velocityPath = string.Format("{0}{1}", nsPrefix, nsPrefix == "v3:" ? "velocity" : "v"); string lyricPath = string.Format("{0}{1}", nsPrefix, nsPrefix == "v3:" ? "lyric" : "y"); string phonemePath = string.Format("{0}{1}", nsPrefix, nsPrefix == "v3:" ? "phnms" : "p"); string playtimePath = string.Format("{0}playTime", nsPrefix); string partstyleattrPath = string.Format("{0}{1}/{0}{2}", nsPrefix, nsPrefix == "v3:" ? "partStyle" : "pStyle", nsPrefix == "v3:" ? "attr" : "v"); string notestyleattrPath = string.Format("{0}{1}/{0}{2}", nsPrefix, nsPrefix == "v3:" ? "noteStyle" : "nStyle", nsPrefix == "v3:" ? "attr" : "v"); uproject.BPM = Convert.ToDouble(root.SelectSingleNode(bpmPath, nsmanager).InnerText) / 100; uproject.BeatPerBar = int.Parse(root.SelectSingleNode(beatperbarPath, nsmanager).InnerText); uproject.BeatUnit = int.Parse(root.SelectSingleNode(beatunitPath, nsmanager).InnerText); uproject.Resolution = int.Parse(root.SelectSingleNode(resolutionPath, nsmanager).InnerText); uproject.FilePath = file; uproject.Name = root.SelectSingleNode(projectnamePath, nsmanager).InnerText; uproject.Comment = root.SelectSingleNode(projectcommentPath, nsmanager).InnerText; int preMeasure = int.Parse(root.SelectSingleNode(premeasurePath, nsmanager).InnerText); int partPosTickShift = -preMeasure * uproject.Resolution * uproject.BeatPerBar * 4 / uproject.BeatUnit; USinger usinger = new USinger(); uproject.Singers.Add(usinger); foreach (XmlNode track in root.SelectNodes(trackPath, nsmanager)) // track { UTrack utrack = new UTrack() { Singer = usinger, TrackNo = uproject.Tracks.Count }; uproject.Tracks.Add(utrack); utrack.Name = track.SelectSingleNode(tracknamePath, nsmanager).InnerText; utrack.Comment = track.SelectSingleNode(trackcommentPath, nsmanager).InnerText; utrack.TrackNo = int.Parse(track.SelectSingleNode(tracknoPath, nsmanager).InnerText); foreach (XmlNode part in track.SelectNodes(partPath, nsmanager)) // musical part { UVoicePart upart = new UVoicePart(); uproject.Parts.Add(upart); upart.Name = part.SelectSingleNode(partnamePath, nsmanager).InnerText; upart.Comment = part.SelectSingleNode(partcommentPath, nsmanager).InnerText; upart.PosTick = int.Parse(part.SelectSingleNode(postickPath, nsmanager).InnerText) + partPosTickShift; upart.DurTick = int.Parse(part.SelectSingleNode(playtimePath, nsmanager).InnerText); upart.TrackNo = utrack.TrackNo; foreach (XmlNode note in part.SelectNodes(notePath, nsmanager)) { UNote unote = uproject.CreateNote(); unote.PosTick = int.Parse(note.SelectSingleNode(postickPath, nsmanager).InnerText); unote.DurTick = int.Parse(note.SelectSingleNode(durtickPath, nsmanager).InnerText); unote.NoteNum = int.Parse(note.SelectSingleNode(notenumPath, nsmanager).InnerText); unote.Lyric = note.SelectSingleNode(lyricPath, nsmanager).InnerText; unote.Phonemes[0].Phoneme = note.SelectSingleNode(phonemePath, nsmanager).InnerText; unote.Expressions["velocity"].Data = int.Parse(note.SelectSingleNode(velocityPath, nsmanager).InnerText); foreach (XmlNode notestyle in note.SelectNodes(notestyleattrPath, nsmanager)) { if (notestyle.Attributes["id"].Value == "opening") unote.Expressions["opening"].Data = int.Parse(notestyle.InnerText); else if (notestyle.Attributes["id"].Value == "accent") unote.Expressions["accent"].Data = int.Parse(notestyle.InnerText); else if (notestyle.Attributes["id"].Value == "decay") unote.Expressions["decay"].Data = int.Parse(notestyle.InnerText); } unote.PitchBend.Points[0].X = -uproject.TickToMillisecond(Math.Min(15, unote.DurTick / 3)); unote.PitchBend.Points[1].X = -unote.PitchBend.Points[0].X; upart.Notes.Add(unote); } } } return uproject; }