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 DeletePitchPointCommand(UVoicePart part, UNote note, int index) { this.Part = part; this.Note = note; this.Index = index; this.Point = Note.pitch.data[Index]; }
public ChangeNoteLyricCommand(UVoicePart part, UNote note, string newLyric) { Part = part; Note = note; NewLyric = newLyric; OldLyric = note.Lyric; }
public static List <UNote> WriteNotes(UProject project, UVoicePart part, IEnumerable <UNote> notes, string filePath) { List <UNote> sequence = new List <UNote>(); using (var writer = new StreamWriter(filePath, false, ShiftJIS)) { WriteHeader(project, part, writer); int position = 0; foreach (var note in notes) { if (note.position != position) { writer.WriteLine($"[#{sequence.Count:D4}]"); var spacer = UNote.Create(); spacer.position = position; spacer.duration = note.position - position; spacer.lyric = "R"; spacer.tone = 60; sequence.Add(spacer); WriteNoteBody(project, spacer, writer); } writer.WriteLine($"[#{sequence.Count:D4}]"); WriteNoteBody(project, note, writer); position = note.End; sequence.Add(note); } WriteFooter(writer); } return(sequence); }
public RenderItem(UPhoneme phoneme, UVoicePart part, UProject project) { var singer = project.Tracks[part.TrackNo].Singer; SourceFile = phoneme.Oto.File; SourceFile = Path.Combine(PathManager.Inst.InstalledSingersPath, SourceFile); var strechRatio = Math.Pow(2, 1.0 - (double)(int)phoneme.Parent.Expressions["velocity"].Data / 100); var length = phoneme.Oto.Preutter * strechRatio + phoneme.Envelope.Points[4].X; var requiredLength = Math.Ceiling(length / 50 + 1) * 50; var lengthAdjustment = phoneme.TailIntrude == 0 ? phoneme.Preutter : phoneme.Preutter - phoneme.TailIntrude + phoneme.TailOverlap; 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; 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; phonemeName = phoneme.Phoneme; }
async Task <SequencingSampleProvider> RenderPartAsync(UVoicePart part, UProject project, string cacheDir) { var singer = project.Tracks[part.TrackNo].Singer; if (singer == null || !singer.Loaded) { return(null); } var tasks = new List <Task <RenderItem> >(); var progress = new Progress(part.Notes.Sum(note => note.Phonemes.Count)); progress.Clear(); foreach (var note in part.Notes) { foreach (var phoneme in note.Phonemes) { if (string.IsNullOrEmpty(phoneme.Oto.File)) { Log.Warning($"Cannot find phoneme in note {note.Lyric}"); continue; } var item = new RenderItem(phoneme, part, project); item.progress = progress; tasks.Add(Task <RenderItem> .Factory.StartNew(ResamplePhonemeAsync, item, cancellationTokenSource.Token)); } } await Task.WhenAll(tasks.ToArray()); progress.Clear(); return(new SequencingSampleProvider(tasks.Select(task => new RenderItemSampleProvider(task.Result)))); }
public static UProject Load(StreamReader reader, string file) { var project = new UProject() { resolution = 480, FilePath = file, Saved = false }; Ustx.AddDefaultExpressions(project); project.tracks.Add(new UTrack { TrackNo = 0, }); var part = new UVoicePart() { trackNo = 0, position = 0, name = Path.GetFileNameWithoutExtension(file), }; project.parts.Add(part); var blocks = ReadBlocks(reader, file); ParsePart(project, part, blocks); part.Duration = part.notes.Select(note => note.End).Max() + project.resolution; return(project); }
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); }
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); }
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 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 PhonemeOverlapCommand(UVoicePart part, UNote note, int index, float scale) : base(part, note) { this.note = note; this.index = index; var o = this.note.GetPhonemeOverride(index); oldScale = o.overlapScale ?? 1; newScale = scale; }
public PhonemeOffsetCommand(UVoicePart part, UNote note, int index, int offset) : base(part, note) { this.note = note; this.index = index; var o = this.note.GetPhonemeOverride(index); oldOffset = o.offset ?? 0; newOffset = offset; }
public ChangeNoteLyricCommand(UVoicePart part, UNote[] notes, string[] newLyrics) : base(part, notes) { if (notes.Length != newLyrics.Length) { throw new ArgumentException($"notes count {notes.Length} and lyrics count {newLyrics.Length} does not match."); } NewLyrics = newLyrics; OldLyrics = notes.Select(note => note.lyric).ToArray(); }
public void RenamePart(UVoicePart part, string name) { if (!string.IsNullOrWhiteSpace(name) && name != part.name) { DocManager.Inst.StartUndoGroup(); DocManager.Inst.ExecuteCmd(new RenamePartCommand(DocManager.Inst.Project, part, name)); DocManager.Inst.EndUndoGroup(); } }
IEnumerable <RenderItem> PreparePart(UVoicePart part, UTrack track, UProject project, int startTick) { return(part.notes .Where(note => !note.OverlapError) .SelectMany(note => note.phonemes) .Where(phoneme => !phoneme.Error) .Where(phoneme => part.position + phoneme.Parent.position + phoneme.End > startTick) .Select(phoneme => new RenderItem(phoneme, part, track, project, driver.GetInfo().Name))); }
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; if (phoneme.Overlap < 0) { phoneme.Overlap = -phoneme.Overlap; } phoneme.Overlap = Math.Max(phoneme.Overlap, phoneme.Oto.Overlap); phoneme.Preutter = Math.Max(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 void Show(UVoicePart part, UNote note, string text) { Part = part; Note = note; Visibility = Visibility.Visible; Text = text; Focus(); SelectAll(); UpdateSuggestion(); }
public void Show(UVoicePart part, UNote note, string text) { viewModel.Part = part; viewModel.Note = note; viewModel.Text = text; viewModel.IsVisible = true; box.SelectAll(); focusTimer = new DispatcherTimer(); focusTimer.Tick += FocusTimer_Tick; focusTimer.Start(); }
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; } }
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)); }
public static UProject Load(string file, Encoding encoding = null) { var 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 }); project.Tracks.Add(new UTrack { TrackNo = 0 }); var part = new UVoicePart() { TrackNo = 0, PosTick = 0 }; project.Parts.Add(part); var blocks = ReadBlocks(file, encoding ?? Encoding.GetEncoding("shift_jis")); ParsePart(project, part, blocks); part.DurTick = part.Notes.Select(note => note.EndTick).Max() + project.Resolution; return(project); }
private static void SnapPitchPoints(UVoicePart part) { UNote lastNote = null; foreach (var note in part.notes) { if (lastNote != null && note.position == lastNote.End) { note.pitch.snapFirst = true; } lastNote = note; } }
static void WriteHeader(UProject project, UVoicePart part, StreamWriter writer) { writer.WriteLine("[#SETTING]"); writer.WriteLine($"Tempo={project.bpm}"); writer.WriteLine("Tracks=1"); var singer = project.tracks[part.trackNo].Singer; if (singer?.Id != null) { writer.WriteLine($"VoiceDir=%VOICE%{singer.Id}"); } writer.WriteLine($"CacheDir={project.cacheDir}"); writer.WriteLine("Mode2=True"); }
private static void ParsePart(UProject project, UVoicePart part, List <List <UstLine> > blocks) { int tick = 0; foreach (var block in blocks) { string header = block[0].line; try { switch (header) { case "[#VERSION]": break; case "[#SETTING]": ParseSetting(project, block); break; case "[#TRACKEND]": break; default: if (int.TryParse(header.Substring(2, header.Length - 3), out int noteIndex)) { UNote note = project.CreateNote(); ParseNote(note, block, out var noteTempo); note.position = tick; tick += note.duration; if (note.lyric.ToLower() != "r") { part.notes.Add(note); } if (noteTempo != null && (project.bpm <= 0 || project.bpm > 1000)) { // Fix tempo=500k error. project.bpm = noteTempo.Value; } } else { throw new FileFormatException($"Unexpected header\n{block[0]}"); } break; } } catch (Exception e) when(!(e is FileFormatException)) { throw new FileFormatException($"Failed to parse block\n{block[0]}", e); } } SnapPitchPoints(part); }
public void UpdatePart(UVoicePart part) { if (part == null) { return; } CheckOverlappedNotes(part); UpdatePhonemeDurTick(part); UpdatePhonemeOto(part); UpdateOverlapAdjustment(part); UpdateEnvelope(part); UpdatePitchBend(part); DocManager.Inst.ExecuteCmd(new RedrawNotesNotification(), true); }
public void EndNoteEditing(bool edit = false) { string finalText = Text; if (edit && Note != null && finalText != Note.lyric) { DocManager.Inst.StartUndoGroup(); DocManager.Inst.ExecuteCmd(new ChangeNoteLyricCommand(Part, Note, finalText)); DocManager.Inst.EndUndoGroup(); } Part = null; Note = null; Visibility = Visibility.Hidden; Clear(); UpdateSuggestion(); }
public override UPart ReadJson(JsonReader reader, Type objectType, UPart existingValue, bool hasExistingValue, JsonSerializer serializer) { JObject jObj = JObject.Load(reader); UPart part; if (jObj.Property("notes") != null) { part = new UVoicePart(); } else { part = new UWavePart(); } serializer.Populate(jObj.CreateReader(), part); return(part); }
private List <RenderItem> RenderAsync(UVoicePart part, UProject project, IResamplerDriver engine, BackgroundWorker worker) { var renderItems = new List <RenderItem>(); var watch = new Stopwatch(); watch.Start(); Log.Information("Resampling start."); lock (part) { var cacheDir = PathManager.Inst.GetCachePath(project.FilePath); var cacheFiles = Directory.EnumerateFiles(cacheDir).ToArray(); int count = 0, i = 0; foreach (var note in part.Notes) { foreach (var phoneme in note.Phonemes) { count++; } } foreach (var note in part.Notes) { foreach (var phoneme in note.Phonemes) { if (string.IsNullOrEmpty(phoneme.Oto.File)) { Log.Warning($"Cannot find phoneme in note {note.Lyric}"); continue; } var item = new RenderItem(phoneme, part, project); //System.Diagnostics.Debug.WriteLine("Sound {0:x} resampling {1}", item.HashParameters(), item.GetResamplerExeArgs()); var engineArgs = DriverModels.CreateInputModel(item, 0); var output = engine.DoResampler(engineArgs); item.Sound = MemorySampleProvider.FromStream(output); output.Dispose(); renderItems.Add(item); worker.ReportProgress(100 * ++i / count, $"Resampling \"{phoneme.Phoneme}\" {i}/{count}"); } } } watch.Stop(); Log.Information($"Resampling end, total time {watch.Elapsed}"); return(renderItems); }
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; } }