public void SetSinger(string singerName) { USinger singer = null; foreach (var pair in DocManager.Inst.Singers) { if (pair.Value.Name == singerName) { singer = pair.Value; } } if (singer == null) { return; } this.name.Text = singer.Name; this.avatar.Source = singer.Avatar; this.info.Text = "Author: " + singer.Author + "\nWeb: " + singer.Web + "\nLocation: " + singer.Location; this.otoview.Items.Clear(); foreach (var set in singer.OtoSets) { foreach (var oto in set.Otos.Values) { otoview.Items.Add(oto); } } }
public static Dictionary <string, USinger> FindAllSingers() { Dictionary <string, USinger> singers = new Dictionary <string, USinger>(); var singerSearchPaths = PathManager.Inst.GetSingerSearchPaths(); foreach (string searchPath in singerSearchPaths) { if (!Directory.Exists(searchPath)) { continue; } foreach (var dirpath in Directory.EnumerateDirectories(searchPath)) { if (File.Exists(Path.Combine(dirpath, "character.txt")) && File.Exists(Path.Combine(dirpath, "oto.ini"))) { USinger singer = null; try { singer = LoadSinger(dirpath); singers.Add(singer.Path, singer); } catch { } } } } return(singers); }
static USinger FromVoicebank(Voicebank voicebank) { var singer = new USinger(); singer.Name = voicebank.Name; singer.Author = voicebank.Author; singer.Website = voicebank.Web; singer.Path = Path.Combine(PathManager.Inst.InstalledSingersPath, Path.GetDirectoryName(voicebank.File)); var imagePath = Path.Combine(singer.Path, voicebank.Image); singer.Avatar = LoadAvatar(imagePath); singer.Loaded = true; singer.PitchMap = voicebank.PrefixMap.Map; foreach (var otoSet in voicebank.OtoSets) { var otoDir = Path.Combine(Path.GetDirectoryName(otoSet.File)); foreach (var oto in otoSet.Otos) { if (!singer.AliasMap.ContainsKey(oto.Name)) { singer.AliasMap.Add(oto.Name, new UOto { Alias = oto.Name, File = Path.Combine(otoDir, oto.Wav), Offset = oto.Offset, Consonant = oto.Consonant, Cutoff = oto.Cutoff, Preutter = oto.Preutter, Overlap = oto.Overlap, }); } } } return(singer); }
static void LoadPrefixMap(USinger singer) { string path = singer.Path; if (File.Exists(Path.Combine(path, "prefix.map"))) { string[] lines; try { lines = File.ReadAllLines(Path.Combine(path, "prefix.map")); } catch { throw new Exception("Prefix map exists but cannot be opened for read."); } foreach (string line in lines) { var s = line.Trim().Split(new char[0], StringSplitOptions.RemoveEmptyEntries); if (s.Count() == 2) { string source = s[0]; string target = s[1]; singer.PitchMap.Add(source, target); } } } }
public TrackChangeSingerCommand(UProject project, UTrack track, USinger newSinger) { this.project = project; this.track = track; this.newSinger = newSinger; this.oldSinger = track.Singer; }
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 override object Deserialize(IDictionary <string, object> dictionary, Type type, JavaScriptSerializer serializer) { if (type == typeof(IntExpression)) { IntExpression result = new IntExpression(null, "", dictionary["abbr"] as string) { Data = dictionary["data"], Min = Convert.ToInt32(dictionary["min"]), Max = Convert.ToInt32(dictionary["max"]), }; return(result); } else if (type == typeof(UTrack)) { UTrack result = new UTrack() { Name = dictionary["name"] as string, Comment = dictionary["comment"] as string, TrackNo = Convert.ToInt32(dictionary["trackno"]), Singer = new USinger(dictionary["singer"] as string), }; return(result); } else if (type == typeof(USinger)) { USinger result = new USinger(dictionary["name"] as string); return(result); } else { return(null); } }
/// <summary> /// Utility method to map a phoneme alias to proper pitch using prefixmap. /// For example, MapPhoneme("あ", 72, singer) may return "あC5". /// </summary> /// <param name="phoneme">Alias before pitch mapping.</param> /// <param name="tone">Music tone of note. C4 = 60.</param> /// <param name="singer">The singer.</param> /// <returns>Mapped alias.</returns> public static string MapPhoneme(string phoneme, int tone, USinger singer) { var toneName = MusicMath.GetToneName(tone); if (singer.PrefixMap.TryGetValue(toneName, out var prefix)) { var phonemeMapped = prefix.Item1 + phoneme + prefix.Item2; if (singer.FindOto(phonemeMapped) != null) { phoneme = phonemeMapped; } } return(phoneme); }
/// <summary> /// Utility method to tone-map phonemes. /// Uses phoneme positions to find the most overlapped note, and tone-map based on it. /// </summary> public static void MapPhonemes(Note[] notes, Phoneme[] phonemes, USinger singer) { int endPosition = 0; int index = 0; foreach (var note in notes) { endPosition += note.duration; while (index < phonemes.Length && phonemes[index].position < endPosition) { phonemes[index].phoneme = MapPhoneme(phonemes[index].phoneme, note.tone, singer); index++; } } }
static void LoadOto(string dirpath, string path, USinger singer) { string file = Path.Combine(dirpath, "oto.ini"); string relativeDir = dirpath.Replace(path, ""); while (relativeDir.StartsWith("\\")) { relativeDir = relativeDir.Substring(1); } string[] lines = File.ReadAllLines(file, singer.FileEncoding); List <string> errorLines = new List <string>(); foreach (var line in lines) { var s = line.Split(new[] { '=' }); if (s.Count() == 2) { string wavfile = s[0]; var args = s[1].Split(new[] { ',' }); if (singer.AliasMap.ContainsKey(args[0])) { continue; } try { singer.AliasMap.Add(args[0], new UOto() { File = Path.Combine(relativeDir, wavfile), Alias = args[0], Offset = double.Parse(args[1]), Consonant = double.Parse(args[2]), Cutoff = double.Parse(args[3]), Preutter = double.Parse(args[4]), Overlap = double.Parse(args[5]) }); } catch { errorLines.Add(line); } } } if (errorLines.Count > 0) { System.Diagnostics.Debug.WriteLine(string.Format( "Oto file {0} has following errors:\n{1}", file, string.Join("\n", errorLines.ToArray()))); } }
static void LoadOtos(USinger singer) { string path = singer.Path; if (File.Exists(Path.Combine(path, "oto.ini"))) { LoadOto(path, path, singer); } foreach (var dirpath in Directory.EnumerateDirectories(path)) { if (File.Exists(Path.Combine(dirpath, "oto.ini"))) { LoadOto(dirpath, path, singer); } } }
private static void ParseSetting(UProject project, List <UstLine> ustBlock) { const string format = "<param>=<value>"; for (int i = 1; i < ustBlock.Count; i++) { string line = ustBlock[i].line; var parts = line.Split('='); if (parts.Length != 2) { throw new FileFormatException($"Line does not match format {format}.\n{ustBlock[i]}"); } string param = parts[0].Trim(); switch (param) { case "Tempo": if (double.TryParse(parts[1], out double temp)) { project.BPM = temp; } break; case "ProjectName": project.Name = parts[1].Trim(); break; case "VoiceDir": var singerpath = parts[1].Trim(); var singer = DocManager.Inst.GetSinger(singerpath); if (singer == null) { singer = new USinger(""); } project.Singers.Add(singer); project.Tracks[0].Singer = singer; break; } } }
private static void ParseSetting(UProject project, List <UstLine> ustBlock) { const string format = "<param>=<value>"; for (int i = 1; i < ustBlock.Count; i++) { string line = ustBlock[i].line; var parts = line.Split('='); if (parts.Length != 2) { throw new FileFormatException($"Line does not match format {format}.\n{ustBlock[i]}"); } string param = parts[0].Trim(); switch (param) { case "Tempo": if (ParseFloat(parts[1], out float temp)) { project.bpm = temp; } break; case "ProjectName": project.name = parts[1].Trim(); break; case "VoiceDir": var singerpath = parts[1].Trim(); var singer = DocManager.Inst.GetSinger(singerpath); if (singer == null) { singer = new USinger(Path.GetFileName(singerpath.Replace("%DATA%", "").Replace("%VOICE%", ""))); } project.tracks[0].Singer = singer; break; } } }
public void SetSinger(string singerName) { USinger singer = null; foreach (var pair in DocManager.Inst.Singers) { if (pair.Value.Name == singerName) { singer = pair.Value; } } if (singer == null) { return; } this.name.Text = singer.Name; this.avatar.Source = singer.Avatar; this.info.Text = "作者: " + singer.Author + "\n网站: " + singer.Website + "\n路径: " + singer.Path; this.otoview.Items.Clear(); foreach (var pair in singer.AliasMap) { this.otoview.Items.Add(pair.Value); } }
public override void SetSinger(USinger singer) { }
public static UProject Load(string file, Encoding encoding = null) { var currentNoteIndex = 0; var version = UstVersion.Early; var currentBlock = UstBlock.None; string[] lines; try { if (encoding == null) { lines = File.ReadAllLines(file, FileEncoding.DetectFileEncoding(file)); } else { lines = File.ReadAllLines(file, encoding); } } catch (Exception e) { DocManager.Inst.ExecuteCmd(new UserMessageNotification(e.GetType().ToString() + "\n" + e.Message)); return(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 }); var _track = new UTrack(); project.Tracks.Add(_track); _track.TrackNo = 0; var part = new UVoicePart() { TrackNo = 0, PosTick = 0 }; project.Parts.Add(part); var currentLines = new List <string>(); var currentTick = 0; UNote currentNote = null; foreach (var 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("[#", string.Empty).Replace("]", string.Empty)); } 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", string.Empty).Replace("r", string.Empty).Equals(string.Empty)) { part.Notes.Add(currentNote); } currentTick += currentNote.DurTick; currentLines.Clear(); } } } else { if (currentBlock == UstBlock.Version) { if (line.StartsWith("UST Version")) { var v = line.Trim().Replace("UST Version", string.Empty); switch (v) { case "1.0": version = UstVersion.V1_0; break; case "1.1": version = UstVersion.V1_1; break; case "1.2": version = UstVersion.V1_2; break; default: version = UstVersion.Unknown; break; } } } if (currentBlock == UstBlock.Setting) { if (line.StartsWith("Tempo=")) { project.BPM = double.Parse(line.Trim().Replace("Tempo=", string.Empty)); if (project.BPM == 0) { project.BPM = 120; } } if (line.StartsWith("ProjectName=")) { project.Name = line.Trim().Replace("ProjectName=", string.Empty); } if (line.StartsWith("VoiceDir=")) { var singerpath = line.Trim().Replace("VoiceDir=", string.Empty); var singer = DocManager.Inst.GetSinger(singerpath); 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); }
// Simply stores the singer in a field. public override void SetSinger(USinger singer) => this.singer = singer;
// Simply stores the singer in a field. public override void SetSinger(USinger singer) { this.singer = singer; LoadSingerDict(); mergedG2p = new G2pFallbacks(new IG2p[] { pluginDict, singerDict, cmudict }.OfType <IG2p>().ToArray()); }
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); }
static USinger LoadSinger(string path) { if (!Directory.Exists(path) || !File.Exists(Path.Combine(path, "character.txt")) || !File.Exists(Path.Combine(path, "oto.ini"))) { return(null); } USinger singer = new USinger(); singer.Path = path; singer.FileEncoding = EncodingUtil.DetectFileEncoding(Path.Combine(singer.Path, "oto.ini"), Encoding.Default); singer.PathEncoding = Encoding.Default; string[] lines = File.ReadAllLines(Path.Combine(singer.Path, "oto.ini"), singer.FileEncoding); int i = 0; while (i < 16 && i < lines.Count()) { if (lines[i].Contains("=")) { string filename = lines[i].Split(new[] { '=' })[0]; var detected = DetectPathEncoding(filename, singer.Path, singer.FileEncoding); if (singer.PathEncoding == Encoding.Default) { singer.PathEncoding = detected; } i++; } } if (singer.PathEncoding == null) { return(null); } LoadOtos(singer); try { lines = File.ReadAllLines(Path.Combine(singer.Path, "character.txt"), singer.FileEncoding); } catch { return(null); } foreach (var line in lines) { if (line.StartsWith("name=")) { singer.Name = line.Trim().Replace("name=", ""); } if (line.StartsWith("image=")) { string imagePath = line.Trim().Replace("image=", ""); Uri imagepath = new Uri(Path.Combine(singer.Path, EncodingUtil.ConvertEncoding(singer.FileEncoding, singer.PathEncoding, imagePath))); singer.Avatar = new System.Windows.Media.Imaging.BitmapImage(imagepath); singer.Avatar.Freeze(); } if (line.StartsWith("author=")) { singer.Author = line.Trim().Replace("author=", ""); } if (line.StartsWith("web=")) { singer.Website = line.Trim().Replace("web=", ""); } } LoadPrefixMap(singer); singer.Loaded = true; return(singer); }
public static UProject Load(string file) { XmlDocument vsqx = new XmlDocument(); vsqx.Load(file); XmlNamespaceManager nsmanager = new XmlNamespaceManager(vsqx.NameTable); nsmanager.AddNamespace("v3", vsq3NameSpace); nsmanager.AddNamespace("v4", vsq4NameSpace); XmlNode root; string nsPrefix; // Detect vsqx version if ((root = vsqx.SelectSingleNode("v3:vsq3", nsmanager)) != null) { nsPrefix = "v3:"; } else if ((root = vsqx.SelectSingleNode("v4:vsq4", nsmanager)) != null) { nsPrefix = "v4:"; } else { throw new FileFormatException("Unrecognizable VSQx file format."); } UProject uproject = new UProject(); Ustx.AddDefaultExpressions(uproject); uproject.RegisterExpression(new UExpressionDescriptor("opening", "ope", 0, 100, 100)); string bpmPath = $"{nsPrefix}masterTrack/{nsPrefix}tempo/{nsPrefix}{(nsPrefix == "v3:" ? "bpm" : "v")}"; string beatperbarPath = $"{nsPrefix}masterTrack/{nsPrefix}timeSig/{nsPrefix}{(nsPrefix == "v3:" ? "nume" : "nu")}"; string beatunitPath = $"{nsPrefix}masterTrack/{nsPrefix}timeSig/{nsPrefix}{(nsPrefix == "v3:" ? "denomi" : "de")}"; string premeasurePath = $"{nsPrefix}masterTrack/{nsPrefix}preMeasure"; string resolutionPath = $"{nsPrefix}masterTrack/{nsPrefix}resolution"; string projectnamePath = $"{nsPrefix}masterTrack/{nsPrefix}seqName"; string projectcommentPath = $"{nsPrefix}masterTrack/{nsPrefix}comment"; string trackPath = $"{nsPrefix}vsTrack"; string tracknamePath = $"{nsPrefix}{(nsPrefix == "v3:" ? "trackName" : "name")}"; string trackcommentPath = $"{nsPrefix}comment"; string tracknoPath = $"{nsPrefix}{(nsPrefix == "v3:" ? "vsTrackNo" : "tNo")}"; string partPath = $"{nsPrefix}{(nsPrefix == "v3:" ? "musicalPart" : "vsPart")}"; string partnamePath = $"{nsPrefix}{(nsPrefix == "v3:" ? "partName" : "name")}"; string partcommentPath = $"{nsPrefix}comment"; string notePath = $"{nsPrefix}note"; string postickPath = $"{nsPrefix}{(nsPrefix == "v3:" ? "posTick" : "t")}"; string durtickPath = $"{nsPrefix}{(nsPrefix == "v3:" ? "durTick" : "dur")}"; string notenumPath = $"{nsPrefix}{(nsPrefix == "v3:" ? "noteNum" : "n")}"; string velocityPath = $"{nsPrefix}{(nsPrefix == "v3:" ? "velocity" : "v")}"; string lyricPath = $"{nsPrefix}{(nsPrefix == "v3:" ? "lyric" : "y")}"; string phonemePath = $"{nsPrefix}{(nsPrefix == "v3:" ? "phnms" : "p")}"; string playtimePath = $"{nsPrefix}playTime"; string partstyleattrPath = $"{nsPrefix}{(nsPrefix == "v3:" ? "partStyle" : "pStyle")}/{nsPrefix}{(nsPrefix == "v3:" ? "attr" : "v")}"; string notestyleattrPath = $"{nsPrefix}{(nsPrefix == "v3:" ? "noteStyle" : "nStyle")}/{nsPrefix}{(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(""); 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.position = int.Parse(part.SelectSingleNode(postickPath, nsmanager).InnerText) + partPosTickShift; upart.Duration = int.Parse(part.SelectSingleNode(playtimePath, nsmanager).InnerText); upart.trackNo = utrack.TrackNo; foreach (XmlNode note in part.SelectNodes(notePath, nsmanager)) { UNote unote = uproject.CreateNote(); unote.position = int.Parse(note.SelectSingleNode(postickPath, nsmanager).InnerText); unote.duration = int.Parse(note.SelectSingleNode(durtickPath, nsmanager).InnerText); unote.tone = int.Parse(note.SelectSingleNode(notenumPath, nsmanager).InnerText); unote.lyric = note.SelectSingleNode(lyricPath, nsmanager).InnerText; if (unote.lyric == "-") { unote.lyric = "..."; } unote.phonemeExpressions.Add(new UExpression("vel") { index = 0, value = int.Parse(note.SelectSingleNode(velocityPath, nsmanager).InnerText) * 100 / 64, }); foreach (XmlNode notestyle in note.SelectNodes(notestyleattrPath, nsmanager)) { if (notestyle.Attributes["id"].Value == "opening") { unote.phonemeExpressions.Add(new UExpression("ope") { index = 0, value = int.Parse(notestyle.InnerText) * 100 / 127, }); } else if (notestyle.Attributes["id"].Value == "accent") { unote.phonemeExpressions.Add(new UExpression("atk") { index = 0, value = int.Parse(notestyle.InnerText) * 2, }); } else if (notestyle.Attributes["id"].Value == "decay") { unote.phonemeExpressions.Add(new UExpression("dec") { index = 0, // V4 default is 50. Translate it to no effect in OU. V4 dec 100 roughly maps to OU 50. value = Math.Max(0, int.Parse(notestyle.InnerText) - 50), }); } } unote.pitch.data[0].X = -(float)uproject.TickToMillisecond(Math.Min(15, unote.duration / 3)); unote.pitch.data[1].X = -unote.pitch.data[0].X; upart.notes.Add(unote); } } } uproject.AfterLoad(); uproject.Validate(); return(uproject); }
/// <summary> /// Sets the current singer. Called by OpenUtau when user changes the singer. /// /// In addition to using data in the USinger class, /// a phonemizer can also use this method to load singer-specific resource, /// such as a custom dictionary file in the singer directory. /// Use singer.Location to access the singer directory. /// /// Do not modify the singer. /// </summary> /// <param name="singer"></param> public abstract void SetSinger(USinger singer);