private void Convert(string inputFile, string savePath, bool all) { SngFile sngFile = new SngFile(inputFile); if (String.IsNullOrEmpty(sngFile.Metadata.Arrangement)) return; // Vocal int maxDifficulty = Common.getMaxDifficulty(sngFile); int[] difficulties; if (all) difficulties = Enumerable.Range(0, maxDifficulty + 1).ToArray(); else // if (max) difficulties = new int[] { maxDifficulty }; foreach (int d in difficulties) { TabFile tabFile = new TabFile(sngFile, d); var outputFileName = (sngFile != null && sngFile.Metadata != null) ? String.Format("{0} - ", sngFile.Metadata.SongTitle) : ""; outputFileName += Path.GetFileNameWithoutExtension(inputFile); outputFileName += (difficulties.Length != 1) ? String.Format(" (level {0:00}).txt", d) : ".txt"; var outputFilePath = Path.Combine(savePath, outputFileName); using (TextWriter tw = new StreamWriter(outputFilePath)) { tw.Write(tabFile.ToString()); } } }
public TabHeader(TabFile tabFile, SngFile sngFile) { TabFile = tabFile; Title = sngFile.Metadata.SongTitle; Artist = sngFile.Metadata.Artist; Length = Common.TimeToString(sngFile.Metadata.Length); TuningInfo = tabFile.TuningInfos[(Tuning)sngFile.Metadata.Tuning]; }
public void PhraseIterationsInOrder(SngFile song) { foreach (var pi in song.PhraseIterations) { Assert.LessOrEqual(pi.StartTime, pi.EndTime); Assert.Less(pi.StartTime, 2000); Assert.GreaterOrEqual(pi.StartTime, 0); Assert.Less(pi.EndTime, 2000); Assert.GreaterOrEqual(pi.EndTime, 0); } }
public void VocalsInOrder(SngFile song) { Vocal lastVocal = null; foreach (var vocal in song._vocals) { if (lastVocal != null) { Assert.Less(lastVocal.Time, vocal.Time); } lastVocal = vocal; } }
public TabChord(TabFile tabFile, Note note, SngFile sngFile) : base(tabFile, note) { ChordTemplate chord = sngFile.ChordTemplates[note.ChordId]; ChordName = chord.Name; Frets = new int[TabFile.StringCount]; Frets[0] = chord.Fret0; Frets[1] = chord.Fret1; Frets[2] = chord.Fret2; Frets[3] = chord.Fret3; Frets[4] = chord.Fret4; Frets[5] = chord.Fret5; }
public void ControlsValid(SngFile song) { foreach (var control in song.Controls) { // These times can jump around (ex: TCAnchorZoneIntro_Lead) /* if (lastControl != null) { Assert.LessOrEqual(lastControl.Time, control.Time); } * */ ValidString(control.Code); Assert.Less(control.Time, 2000); Assert.GreaterOrEqual(control.Time, 0); } }
public void SongEventsValid(SngFile song) { SongEvent lastSongEvent = null; foreach (var songEvent in song.SongEvents) { if (lastSongEvent != null) { Assert.LessOrEqual(lastSongEvent.Time, songEvent.Time); } //Just make sure the time is sane Assert.Less(songEvent.Time, 2000); Assert.GreaterOrEqual(songEvent.Time, 0); ValidString(songEvent.Code); lastSongEvent = songEvent; } }
public void BeatsInOrder(SngFile song) { Ebeat lastBeat = null; foreach (var beat in song.Beats) { if (lastBeat != null) { Assert.IsTrue(lastBeat.Time < beat.Time); if (lastBeat.Measure == beat.Measure) { Assert.AreEqual(lastBeat.Beat + 1, beat.Beat); } else { Assert.AreEqual(beat.Beat, 0); Assert.LessOrEqual(lastBeat.Measure + 1, beat.Measure); } } lastBeat = beat; } }
public void Convert(string sngFilePath, string outputDir, bool allDif) { SngFile sngFile = new SngFile(sngFilePath); if (String.IsNullOrEmpty(sngFile.Metadata.Arrangement)) return; // Vocal int maxDifficulty = Common.getMaxDifficulty(sngFile); int[] difficulties; if (allDif) difficulties = Enumerable.Range(0, maxDifficulty + 1).ToArray(); else // if (max) // difficulties = new int[] { maxDifficulty }; difficulties = new int[] { 255 }; foreach (int d in difficulties) { TabFile tabFile = new TabFile(sngFile, d); var outputFileName = String.Empty; if (sngFile != null && sngFile.Metadata != null) if (sngFile.Metadata.Artist == "DUMMY") outputFileName = String.Format("{0}", sngFile.Metadata.SongTitle); else outputFileName = String.Format("{0} - {1}", sngFile.Metadata.Artist, sngFile.Metadata.SongTitle); else outputFileName = String.Format("{0}", "Unknown Song"); outputFileName += (difficulties.Length != 1) ? String.Format(" (level {0:D2})", d) : ""; outputFileName = outputFileName.GetValidName(true); var outputFilePath = Path.Combine(outputDir, outputFileName + ".txt"); using (TextWriter tw = new StreamWriter(outputFilePath)) { tw.Write(tabFile.ToString()); } } }
public TabFile(SngFile sngFile, int maxDifficulty) { StringCount = 6; _measureQueue = new List<TabMeasure>(); _currentMeasure = null; Lines = new List<string>(); // holds text stream // Create the tuning information table TuningInfos = new Dictionary<Tuning, TuningInfo>(); TuningInfos[Tuning.Standard] = new TuningInfo(this, Tuning.Standard, "Standard", new string[] { "e", "B", "G", "D", "A", "E" }); TuningInfos[Tuning.DropD] = new TuningInfo(this, Tuning.DropD, "Drop D", new string[] { "e", "B", "G", "D", "A", "D" }); TuningInfos[Tuning.EFlat] = new TuningInfo(this, Tuning.EFlat, "E Flat", new string[] { "eb", "Bb", "Gb", "Db", "Ab", "Eb" }); TuningInfos[Tuning.OpenG] = new TuningInfo(this, Tuning.OpenG, "Open G", new string[] { "D", "B", "D", "G", "D", "G" }); TuningInfo = TuningInfos[(Tuning)sngFile.Metadata.Tuning]; // Start assembling the tab TabHeader header = new TabHeader(this, sngFile); /* Tab Entities are the parts that together make up a tab, i.e. notes, chords, measures and sections. * Since the notes and chords are all contained in a single array without any measure or section data, * the measure and section data needs to be merged with notes and chords so that all of that data can be * iterated over in the correct order. Entities get sorted by time index (the SortedList key). * Multiple entities (of different types) can have the same time index and need to be processed in the * correct order, i.e. sections before measures and measures before notes/chords. */ SortedList<float, LinkedList<TabEntity>> entities = new SortedList<float, LinkedList<TabEntity>>(); // Add SECTION entities foreach (SongSection s in sngFile.SongSections) addEntity(new TabSection(this, s), entities); // Add MEASURE entities float lastTime = sngFile.Beats[0].Time; int beatCount = 1; int lastMeasure = sngFile.Beats[0].Measure; for (int i = 1; i < sngFile.Beats.Length; i++) { Ebeat b = sngFile.Beats[i]; // To indicate that the current beat is simply the next beat in the current measure and does not define // a new measure, either set b.Measure to -1 or to the same value as the beat before if (b.Measure == -1 || b.Measure == lastMeasure) beatCount++; else { addEntity(new TabMeasure(this, lastTime, b.Time, beatCount), entities); lastTime = b.Time; beatCount = 1; lastMeasure = b.Measure; } } // Don't forget the final measure TabMeasure finalMeasure = new TabMeasure(this, lastTime, sngFile.Beats[sngFile.Beats.Length - 1].Time, beatCount); addEntity(finalMeasure, entities); MaxDifficulty = 0; // Add NOTE / CHORD entities foreach (PhraseIteration pi in sngFile.PhraseIterations) { Phrase p = sngFile.Phrases[pi.Id]; if (MaxDifficulty < p.MaxDifficulty) MaxDifficulty = p.MaxDifficulty; int level = Math.Min(maxDifficulty, p.MaxDifficulty); List<Note> notes = new List<Note>(); foreach (Note n in sngFile.SongLevels[level].Notes) { if (n.Time < pi.StartTime || n.Time > pi.EndTime) continue; if (n.ChordId != -1) addEntity(new TabChord(this, n, sngFile), entities); else addEntity(new TabNote(this, n), entities); } } // Now that the entity list has been build, iterate over it and Apply every single entity to this TabFile, // which will format the entity's data and add it to the TabFile's output buffer. header.Apply(this, maxDifficulty); foreach (LinkedList<TabEntity> lle in entities.Values) { foreach (TabEntity e in lle) e.Apply(this); // "this" contains a stream to make the tablature text } flushMeasureQueue(); // Don't forget, otherwise the last section's measures will be missing }
public void SngGenerationControlsMatch(SngFile rsSng) { TestSngGeneration(rsSng, (toolkitSng, sb) => AssertEx.PropertyValuesAreEqual("Controls", toolkitSng.Controls, rsSng.Controls, sb) ); }
private void TestSngGeneration(SngFile rsSng, Action<SngFile, StringBuilder> func) { var songKey = rsSng.Metadata.SongTitle + rsSng.Metadata.Arrangement + rsSng.Metadata.SongPart; if (songKey == "0") { return; } string xmlName = null, xmlLocation = null; if (rsXmlMappings.ContainsKey(songKey)) { xmlName = rsXmlMappings[songKey]; if (xmlName == null) { return; } xmlLocation = Path.Combine(@"C:\Projects\RS\RS XML Clean", Path.ChangeExtension(xmlName, "xml")); } if (!File.Exists(xmlLocation)) { xmlName = rsSng.Metadata.SongTitle + " - " + rsSng.Metadata.Arrangement; xmlLocation = Path.Combine(@"C:\Projects\RS\RS XML Clean", Path.ChangeExtension(xmlName, "xml")); } if (!File.Exists(xmlLocation)) { Assert.Fail("Couldn't find XML file for SNG: {0}", songKey); } var tmpSngLocation = Path.GetTempFileName(); var arrangement = rsSng.Metadata.Arrangement == "Bass" ? ArrangementType.Bass : ArrangementType.Guitar; SngFileWriter.Write(xmlLocation, tmpSngLocation, arrangement, new Platform(GamePlatform.Pc, GameVersion.None)); SngFile toolkitSng = new SngFile(tmpSngLocation); StringBuilder sb = new StringBuilder(); func(toolkitSng, sb); try { File.Delete(tmpSngLocation); } catch { } if (sb.Length > 0) { Assert.Fail(sb.ToString()); } }
public void KnownVersion(SngFile song) { Assert.IsTrue(song.Version == 49 || song.Version == 51); }
public void SngGenerationSongSectionsMatch(SngFile rsSng) { TestSngGeneration(rsSng, (toolkitSng, sb) => AssertEx.PropertyValuesAreEqual("SongSections", toolkitSng.SongSections, rsSng.SongSections, sb) ); }
public void SongSectionsInOrder(SngFile song) { foreach (var songSection in song.SongSections) { Assert.LessOrEqual(songSection.StartTime, songSection.EndTime); } }
public void SngGenerationPhrasesMatch(SngFile rsSng) { TestSngGeneration(rsSng, (toolkitSng, sb) => AssertEx.PropertyValuesAreEqual("Phrases", toolkitSng.Phrases, rsSng.Phrases, sb) ); }
public void SngGenerationMetadataMatch(SngFile rsSng) { TestSngGeneration(rsSng, (toolkitSng, sb) => AssertEx.PropertyValuesAreEqual("Metadata", toolkitSng.Metadata, rsSng.Metadata, sb) ); }
static void Main(string[] args) { if (args.Length == 0) { Console.Out.WriteLine("Syntax: sngtotab.exe [files]"); return; } int difficulty = Common.MAX_DIFFICULTY_ONLY; try { foreach (string filename in args) { if (filename.StartsWith("-l")) { string difficultyString = filename.Substring(2); if (difficultyString.Equals("a", StringComparison.Ordinal)) difficulty = Common.ALL_DIFFICULTIES; else if (difficultyString.Equals("m", StringComparison.Ordinal)) difficulty = Common.MAX_DIFFICULTY_ONLY; else difficulty = int.Parse(difficultyString); continue; } SngFile sngFile = new SngFile(filename); int maxDifficulty = Common.getMaxDifficulty(sngFile); int[] difficulties; switch (difficulty) { case Common.MAX_DIFFICULTY_ONLY: difficulties = new int[] { maxDifficulty }; break; case Common.ALL_DIFFICULTIES: difficulties = Enumerable.Range(0, maxDifficulty + 1).ToArray(); break; default: difficulties = new int[] { difficulty }; break; } foreach (int d in difficulties) { TabFile tabFile = new TabFile(sngFile, d); string outputFilename; if (filename.EndsWith(".sng")) outputFilename = filename.Substring(0, filename.Length - 4) + "." + d + ".txt"; else outputFilename = filename + "." + d + ".txt"; TextWriter tw = new StreamWriter(outputFilename); tw.Write(tabFile.ToString()); tw.Close(); } } Console.WriteLine("The conversion is complete."); } catch (Exception ex){ Console.WriteLine("Error ocurred: " + ex.Message + Environment.NewLine + ex.InnerException); } }
/// <summary> /// Converts RS1 Song Object to RS1 SngFile Object /// </summary> /// <param name="rs1Song"></param> /// <returns>SngFile</returns> public SngFile Song2SngFile(Song rs1Song, string outputDir) { var rs1SngPath = SongToSngFilePath(rs1Song, outputDir); SngFile sngFile = new SngFile(rs1SngPath); return sngFile; }
public void NotesInOrder(SngFile song) { foreach (var level in song.SongLevels) { Note lastNote = null; foreach (var note in level.Notes) { if (lastNote != null) { Assert.LessOrEqual(lastNote.Time, note.Time); } lastNote = note; } } }
public static int getMaxDifficulty(SngFile sngFile) { int maxDifficulty = 0; foreach (PhraseIteration pi in sngFile.PhraseIterations) { Phrase p = sngFile.Phrases[pi.Id]; if (p.MaxDifficulty > maxDifficulty) maxDifficulty = p.MaxDifficulty; } return maxDifficulty; }
public void SngGenerationEbeatsMatch(SngFile rsSng) { TestSngGeneration(rsSng, (toolkitSng, sb) => AssertEx.PropertyValuesAreEqual("Ebeats", toolkitSng.Beats, rsSng.Beats, sb) ); }