public void Convert(string inputFileName, string outputFileName) { var deser = new XmlSerializer(typeof(Song)); Song zigSong; using (FileStream stream = new FileStream(inputFileName, FileMode.Open)) { zigSong = (Song)deser.Deserialize(stream); } var guitarTrack = GetTrack(zigSong); if (guitarTrack == null) { throw new Exception("Couldn't find a guitar track"); } var rsSong = new RsSong(); AddSongMetadata(rsSong, zigSong); AddEbeats(rsSong, zigSong); AddNotes(rsSong, zigSong); deser = new XmlSerializer(typeof(RsSong)); using (FileStream stream = new FileStream(outputFileName, FileMode.Create)) { deser.Serialize(stream, rsSong); } }
public Song Song2014ToSong(Song2014 rs2014Song) { var rs1Song = new Song(); AddSongMetadata(rs2014Song, rs1Song); AddElements(rs2014Song, rs1Song); AddDifferences(rs2014Song, rs1Song); return rs1Song; }
public float AverageBPM(Song rsSong) { // a rough approximation of BPM based on ebeats and time float beats = rsSong.Ebeats.Length; float endTimeMins = rsSong.Ebeats[rsSong.Ebeats.Length - 1].Time / 60; // float endTimeMins = rsSong.SongLength / 60; float avgBPM = (float)Math.Round(beats / endTimeMins, 1); return avgBPM; }
private void AddSongMetadata(RsSong rsSong, Song zigSong) { rsSong.Arrangement = "Combo"; rsSong.Artist = "Unknown Artist"; rsSong.Title = zigSong.Name; rsSong.Offset = 0; rsSong.Part = 1; rsSong.LastConversionDateTime = DateTime.Now.ToString(); rsSong.SongLength = zigSong.Length; }
/// <summary> /// Converts RS1 Song Object to *.sng File /// </summary> /// <param name="rs1Song"></param> /// <param name="outputPath"></param> /// <returns>Path to binary *.sng file</returns> public string SongToSngFilePath(Song rs1Song, string outputPath) { string rs1XmlPath; using (var obj = new Rs1Converter()) rs1XmlPath = obj.SongToXml(rs1Song, outputPath, true); ArrangementType arrangementType; if (rs1Song.Arrangement.ToLower() == "bass") arrangementType = ArrangementType.Bass; else arrangementType = ArrangementType.Guitar; var sngFilePath = Path.ChangeExtension(rs1XmlPath, ".sng"); SngFileWriter.Write(rs1XmlPath, sngFilePath, arrangementType, new Platform(GamePlatform.Pc, GameVersion.None)); if (File.Exists(rs1XmlPath)) File.Delete(rs1XmlPath); return sngFilePath; }
/// <summary> /// Convert RS1 Song Object to XML file /// </summary> /// <param name="rsSong"></param> /// <param name="outputPath"></param> /// <param name="overWrite"></param> /// <returns>RS Song XML file path</returns> public string SongToXml(Song rsSong, string outputPath, bool overWrite) { if (File.Exists(outputPath) && overWrite) File.Delete(outputPath); else { var outputDir = Path.GetDirectoryName(outputPath); var outputFile = String.Format("{0}_{1}", rsSong.Title, rsSong.Arrangement); outputFile = String.Format("{0}{1}", outputFile.GetValidName(false, true).ToLower(), "_rs1.xml"); outputPath = Path.Combine(outputDir, outputFile); } using (var stream = File.OpenWrite(outputPath)) { rsSong.Serialize(stream, false); } return outputPath; }
private void AddSongMetadata(Song2014 rs2014Song, Song rs1Song) { // for consistency apply old naming method ;( rs1Song.Title = String.Format("{0} - {1}", rs2014Song.Title, rs2014Song.Arrangement); if (rs2014Song.Part > 1) rs1Song.Title = String.Format("{0} {1}", rs1Song.Title, rs2014Song.Part); rs1Song.Arrangement = rs2014Song.Arrangement; rs1Song.Part = rs2014Song.Part; rs1Song.Offset = rs2014Song.Offset; rs1Song.SongLength = rs2014Song.SongLength; rs1Song.StartBeat = rs2014Song.StartBeat; rs1Song.AverageTempo = rs2014Song.AverageTempo; rs1Song.Tuning = rs2014Song.Tuning; rs1Song.Artist = rs2014Song.ArtistName; rs1Song.AlbumName = rs2014Song.AlbumName; rs1Song.AlbumYear = rs2014Song.AlbumYear; // use correct LastConversionDateTime format rs1Song.LastConversionDateTime = DateTime.Now.ToString("MM-dd-yy HH:mm"); }
public Tone2014 ToneToTone2014(Tone rs1Tone, Song rs1Song) { Tone2014 tone2014 = new Tone2014(); Pedal2014 amp = new Pedal2014(); Pedal2014 cabinet = new Pedal2014(); Pedal2014 prepedal1 = new Pedal2014(); Pedal2014 rack1 = new Pedal2014(); Pedal2014 rack2 = new Pedal2014(); tone2014.ToneDescriptors = new List<string>(); // use Tone Key for better conversion tone2014.Name = rs1Tone.Name ?? "Default"; tone2014.Key = rs1Tone.Key ?? "DEFAULT"; tone2014.Volume = rs1Tone.Volume; tone2014.IsCustom = true; tone2014.NameSeparator = " - "; tone2014.SortOrder = 0; // setup some possible tone approximation conversions // no direct mapping for RS1 -> RS2 Tones // look here IEnumerable<ToneDescriptor> List() // TODO: figure out better method for tone mapping if (tone2014.Key.ToUpper().Contains("COMBO")) tone2014.Key = "Combo_OD"; if (tone2014.Key.ToUpper().Contains("OD")) { tone2014.ToneDescriptors.Add("$[35716]OVERDRIVE"); amp.Type = "Amps"; amp.Category = "Amp"; amp.PedalKey = "Amp_MarshallJTM45"; cabinet.Type = "Cabinets"; cabinet.Category = "Dynamic_Cone"; cabinet.PedalKey = "Cab_Marshall1936_57_Cone"; rack1.Type = "Racks"; rack1.Category = "Filter"; rack1.PedalKey = "Rack_StudioEQ"; rack2.Type = "Racks"; rack2.Category = "Reverb"; rack2.PedalKey = "Rack_StudioVerb"; prepedal1.Type = "Pedals"; prepedal1.Category = "Distortion"; prepedal1.PedalKey = "Pedal_SuperDrive"; tone2014.GearList = new Gear2014() { Amp = amp, Cabinet = cabinet, Rack1 = rack1, Rack2 = rack2, PrePedal1 = prepedal1 }; } else if (tone2014.Key.ToUpper().Contains("LEAD")) { tone2014.ToneDescriptors.Add("$[35724]LEAD"); amp.Type = "Amps"; amp.Category = "Amp"; amp.PedalKey = "Amp_AT120"; cabinet.Type = "Cabinets"; cabinet.Category = "Dynamic_Cone"; cabinet.PedalKey = "Cab_OrangePPC412_57_Cone"; rack1.Type = "Racks"; rack1.Category = "Filter"; rack1.PedalKey = "Rack_StudioEQ"; prepedal1.Type = "Pedals"; prepedal1.Category = "Distortion"; prepedal1.PedalKey = "Pedal_GermaniumDrive"; tone2014.GearList = new Gear2014() { Amp = amp, Cabinet = cabinet, Rack1 = rack1, PrePedal1 = prepedal1 }; } else if (tone2014.Key.ToUpper().Contains("DIS")) { tone2014.ToneDescriptors.Add("$[35722]DISTORTION"); amp.Type = "Amps"; amp.Category = "Amp"; amp.PedalKey = "Amp_GB100"; cabinet.Type = "Cabinets"; cabinet.Category = "Dynamic_Cone"; cabinet.PedalKey = "Cab_GB412CMKIII_57_Cone"; rack1.Type = "Racks"; rack1.Category = "Filter"; rack1.PedalKey = "Rack_StudioEQ"; rack2.Type = "Racks"; rack2.Category = "Reverb"; rack2.PedalKey = "Rack_StudioVerb"; prepedal1.Type = "Pedals"; prepedal1.Category = "Distortion"; prepedal1.PedalKey = "Pedal_GermaniumDrive"; tone2014.GearList = new Gear2014() { Amp = amp, Cabinet = cabinet, Rack1 = rack1, Rack2 = rack2, PrePedal1 = prepedal1 }; } else if (tone2014.Key.ToUpper().Contains("CLEAN")) { tone2014.ToneDescriptors.Add("$[35720]CLEAN"); amp.Type = "Amps"; amp.Category = "Amp"; amp.PedalKey = "Amp_TW40"; cabinet.Type = "Cabinets"; cabinet.Category = "Dynamic_Cone"; cabinet.PedalKey = "Cab_TW112C_57_Cone"; rack1.Type = "Racks"; rack1.Category = "Filter"; rack1.PedalKey = "Rack_StudioEQ"; tone2014.GearList = new Gear2014() { Amp = amp, Cabinet = cabinet, Rack1 = rack1 }; } else if (tone2014.Key.ToUpper().Contains("ACOU")) { tone2014.ToneDescriptors.Add("$[35721]ACOUSTIC"); amp.Type = "Amps"; amp.Category = "Amp"; amp.PedalKey = "Amp_TW40"; cabinet.Type = "Cabinets"; cabinet.Category = "Dynamic_Cone"; cabinet.PedalKey = "Cab_GB412CMKIII_57_Cone"; rack1.Type = "Racks"; rack1.Category = "Filter"; rack1.PedalKey = "Rack_StudioEQ"; rack2.Type = "Racks"; rack2.Category = "Dynamics"; rack2.PedalKey = "Rack_StudioCompressor"; prepedal1.Type = "Pedals"; prepedal1.Category = "Filter"; prepedal1.PedalKey = "Pedal_AcousticEmulator"; tone2014.GearList = new Gear2014() { Amp = amp, Cabinet = cabinet, Rack1 = rack1, Rack2 = rack2, PrePedal1 = prepedal1 }; } else if (tone2014.Key.ToUpper().Contains("BASS")) { tone2014.ToneDescriptors.Add("$[35715]BASS"); amp.Type = "Amps"; amp.Category = "Amp"; amp.PedalKey = "Bass_Amp_CH300B"; cabinet.Type = "Cabinets"; cabinet.Category = "Dynamic_Cone"; cabinet.PedalKey = "Bass_Cab_BT410BC_57_Cone"; rack1.Type = "Racks"; rack1.Category = "Filter"; rack1.PedalKey = "Rack_StudioEQ"; tone2014.GearList = new Gear2014() { Amp = amp, Cabinet = cabinet, Rack1 = rack1 }; } else // default acoustic is better than nothing { // this is fix for bad RS1 CDLC tones tone2014.Key = "DEFAULT"; // tone2014.ToneDescriptors.Add("$[35721]ACOUSTIC"); amp.Type = "Amps"; amp.Category = "Amp"; amp.PedalKey = "Amp_TW40"; cabinet.Type = "Cabinets"; cabinet.Category = "Dynamic_Cone"; cabinet.PedalKey = "Cab_GB412CMKIII_57_Cone"; rack1.Type = "Racks"; rack1.Category = "Filter"; rack1.PedalKey = "Rack_StudioEQ"; rack2.Type = "Racks"; rack2.Category = "Dynamics"; rack2.PedalKey = "Rack_StudioCompressor"; prepedal1.Type = "Pedals"; prepedal1.Category = "Filter"; prepedal1.PedalKey = "Pedal_AcousticEmulator"; tone2014.GearList = new Gear2014() { Amp = amp, Cabinet = cabinet, Rack1 = rack1, Rack2 = rack2, PrePedal1 = prepedal1 }; } return tone2014; }
private void GeneratePhraseIterationsData(Attributes attribute, Song song) { if (song.PhraseIterations == null) { return; } for (int i = 0; i < song.PhraseIterations.Length; i++) { var phraseIteration = song.PhraseIterations[i]; var phrase = song.Phrases[phraseIteration.PhraseId]; var endTime = i >= song.PhraseIterations.Length - 1 ? song.SongLength : song.PhraseIterations[i + 1].Time; var phraseIt = new PhraseIteration { StartTime = phraseIteration.Time, EndTime = endTime, PhraseIndex = phraseIteration.PhraseId, Name = phrase.Name, MaxDifficulty = phrase.MaxDifficulty, MaxScorePerDifficulty = new List<float>() }; attribute.PhraseIterations.Add(phraseIt); } var noteCnt = 0; foreach (var y in attribute.PhraseIterations) { if (song.Levels[y.MaxDifficulty].Notes != null) { noteCnt += GetNoteCount(y.StartTime, y.EndTime, song.Levels[y.MaxDifficulty].Notes); } if (song.Levels[y.MaxDifficulty].Chords != null ) { noteCnt += GetChordCount(y.StartTime, y.EndTime, song.Levels[y.MaxDifficulty].Chords); } } attribute.Score_MaxNotes = noteCnt; attribute.Score_PNV = ((float)attribute.TargetScore) / noteCnt; foreach (var y in attribute.PhraseIterations) { var phrase = song.Phrases[y.PhraseIndex]; for (int o = 0; o <= phrase.MaxDifficulty; o++) { var multiplier = ((float)(o + 1)) / (phrase.MaxDifficulty + 1); var pnv = attribute.Score_PNV; var noteCount = 0; if (song.Levels[o].Chords != null) { noteCount += GetNoteCount(y.StartTime, y.EndTime, song.Levels[o].Notes); } if (song.Levels[o].Chords != null) { noteCount += GetChordCount(y.StartTime, y.EndTime, song.Levels[o].Chords); } var score = pnv * noteCount * multiplier; y.MaxScorePerDifficulty.Add(score); } } }
private void AddNotes(RsSong rsSong, Song zigSong) { int spread = 3; var notes = new Dictionary<string, List<SongNote>>(); var chords = new Dictionary<string, List<SongChord>>(); var anchors = new Dictionary<string, List<SongAnchor>>(); var handShapes = new Dictionary<string, List<SongHandShape>>(); var chordTemps = new Dictionary<string, Tuple<int, SongChordTemplate>>(); var guitarTrack = GetTrack(zigSong); foreach (var group in guitarTrack.Chords.GroupBy(chord => chord.Difficulty)) { var gNotes = notes[group.Key] = new List<SongNote>(); var gChords = chords[group.Key] = new List<SongChord>(); var gAnchors = anchors[group.Key] = new List<SongAnchor>(); var gHandShapes = handShapes[group.Key] = new List<SongHandShape>(); var zChords = group.OrderBy(chord => chord.StartTime).ToList(); var lastMeasure = 0; int highFret = -1; //bool lastWasChord = false; SongAnchor curAnchor = null; for (int i = 0; i < zChords.Count; i++) { var zChord = zChords[i]; if (zChord.Notes.Count > 1) { Tuple<int, SongChordTemplate> val = GetChordTemplate(zChord, chordTemps); int minCFret = Math.Min(DeZero(val.Item2.Fret0), Math.Min(DeZero(val.Item2.Fret1), Math.Min(DeZero(val.Item2.Fret2), Math.Min(DeZero(val.Item2.Fret3), Math.Min(DeZero(val.Item2.Fret4), DeZero(val.Item2.Fret5)))))); if (minCFret != int.MaxValue) { if (curAnchor == null) { if (gAnchors.Count == 0 || gAnchors[gAnchors.Count - 1].Fret != minCFret) { gAnchors.Add(new SongAnchor { Fret = Math.Min(19, minCFret), Time = zChord.StartTime }); } } else { if (minCFret + spread <= highFret) { curAnchor.Fret = minCFret; } gAnchors.Add(curAnchor); if (curAnchor.Fret != minCFret) { gAnchors.Add(new SongAnchor { Fret = Math.Min(19, minCFret), Time = zChord.StartTime }); } curAnchor = null; } } SongHandShape handShape = new SongHandShape { ChordId = val.Item1, StartTime = zChord.StartTime }; do { SongChord chord = new SongChord(); chord.Time = zChord.StartTime; chord.ChordId = val.Item1; var measure = rsSong.Ebeats.FirstOrDefault(ebeat => ebeat.Time >= chord.Time); if (measure == null || measure.Measure > lastMeasure) { lastMeasure = measure == null ? lastMeasure : measure.Measure; chord.HighDensity = 0; } else if (gChords.Count == 0 || gChords[gChords.Count - 1].ChordId != chord.ChordId) { chord.HighDensity = 0; } else { chord.HighDensity = 1; } gChords.Add(chord); if (i + 1 < zChords.Count) { zChord = zChords[i + 1]; } } while (i + 1 < zChords.Count && zChord.Notes.Count > 1 && val.Item1 == GetChordTemplate(zChord, chordTemps).Item1 && ++i != -1); handShape.EndTime = zChord.StartTime; if (handShape.EndTime > handShape.StartTime) { handShape.EndTime -= (handShape.EndTime - zChords[i].EndTime) / 2; } gHandShapes.Add(handShape); } else { var note = GetNote(zChord, i == zChords.Count - 1 ? null : zChords[i + 1]); if (note.Fret > 0) { if (curAnchor == null) { curAnchor = new SongAnchor { Fret = Math.Min(19, (int)note.Fret), Time = note.Time }; highFret = note.Fret; } else if (note.Fret < curAnchor.Fret) { if (note.Fret + spread >= highFret) { curAnchor.Fret = note.Fret; } else { gAnchors.Add(curAnchor); curAnchor = new SongAnchor { Fret = Math.Min(19, (int)note.Fret), Time = note.Time }; highFret = note.Fret; } } else if (note.Fret > highFret) { if (note.Fret - spread <= curAnchor.Fret) { highFret = note.Fret; } else { gAnchors.Add(curAnchor); curAnchor = new SongAnchor { Fret = Math.Min(19, (int)note.Fret), Time = note.Time }; highFret = note.Fret; } } } gNotes.Add(note); } } if (curAnchor != null) { gAnchors.Add(curAnchor); } } rsSong.Levels = new SongLevel[] { new SongLevel { Difficulty=0, Notes = notes["Easy"].ToArray() , Chords = chords["Easy"].ToArray() , Anchors = anchors["Easy"].ToArray() , HandShapes = handShapes["Easy"].ToArray() }, new SongLevel { Difficulty=1, Notes = notes["Medium"].ToArray() , Chords = chords["Medium"].ToArray() , Anchors = anchors["Medium"].ToArray() , HandShapes = handShapes["Medium"].ToArray() }, new SongLevel { Difficulty=2, Notes = notes["Hard"].ToArray(), Chords = chords["Hard"].ToArray(), Anchors = anchors["Hard"].ToArray() , HandShapes = handShapes["Hard"].ToArray() }, new SongLevel { Difficulty=3, Notes = notes["Expert"].ToArray() , Chords = chords["Expert"].ToArray() , Anchors = anchors["Expert"].ToArray() , HandShapes = handShapes["Expert"].ToArray() } }; rsSong.ChordTemplates = chordTemps.Values.OrderBy(v => v.Item1).Select(v => v.Item2).ToArray(); }
private static void GenerateChordTemplateData(Attributes attribute, Song song) { var ind = 0; if (song.ChordTemplates == null) { return; } foreach (var y in song.ChordTemplates) attribute.ChordTemplates.Add(new ChordTemplate { ChordId = ind++, ChordName = y.ChordName, Fingers = new List<int> { y.Finger0, y.Finger1, y.Finger2, y.Finger3, y.Finger4, y.Finger5 }, Frets = new List<int> { y.Fret0, y.Fret1, y.Fret2, y.Fret3, y.Fret4, y.Fret5 } }); }
private Song2014 ConvertLevels(Song rsSong, Song2014 rsSong2014) { // add levels elements var levels = new List<SongLevel2014>(); foreach (var songLevel in rsSong.Levels) { var anchors = new List<SongAnchor2014>(); var notes = new List<SongNote2014>(); var chords = new List<SongChord2014>(); var handShapes = new List<SongHandShape>(); for (int anchorIndex = 0; anchorIndex < songLevel.Anchors.Length; anchorIndex++) { var anchor = songLevel.Anchors[anchorIndex]; anchors.Add(new SongAnchor2014 { Fret = anchor.Fret, Time = anchor.Time, Width = 4 }); } for (int noteIndex = 0; noteIndex < songLevel.Notes.Length; noteIndex++) { var songNote = songLevel.Notes[noteIndex]; notes.Add(GetNoteInfo(songNote)); } for (int chordIndex = 0; chordIndex < songLevel.Chords.Length; chordIndex++) { // RS1 does not contain chordNotes so need to make them from chordtemplate List<SongNote2014> chordNotes = new List<SongNote2014>(); var zChord = songLevel.Chords[chordIndex]; var zChordId = zChord.ChordId; var zChordTemplate = rsSong.ChordTemplates[zChordId]; // this is ok no code crash //if (String.IsNullOrEmpty(zChordTemplate.ChordName)) // continue; if (zChordTemplate.Finger0 != -1) // finger > -1 is a string played chordNotes.Add(DecodeChordTemplate(zChord, 0, zChordTemplate.Fret0)); if (zChordTemplate.Finger1 != -1) chordNotes.Add(DecodeChordTemplate(zChord, 1, zChordTemplate.Fret1)); if (zChordTemplate.Finger2 != -1) chordNotes.Add(DecodeChordTemplate(zChord, 2, zChordTemplate.Fret2)); if (zChordTemplate.Finger3 != -1) chordNotes.Add(DecodeChordTemplate(zChord, 3, zChordTemplate.Fret3)); if (zChordTemplate.Finger4 != -1) chordNotes.Add(DecodeChordTemplate(zChord, 4, zChordTemplate.Fret4)); if (zChordTemplate.Finger5 != -1) chordNotes.Add(DecodeChordTemplate(zChord, 5, zChordTemplate.Fret5)); if (chordNotes.Any()) { chords.Add(new SongChord2014 { ChordId = zChord.ChordId, ChordNotes = chordNotes.ToArray(), HighDensity = zChord.HighDensity, Ignore = zChord.Ignore, Strum = zChord.Strum, Time = zChord.Time }); // add chordNotes to songNotes for compatibility notes.AddRange(chordNotes); } } // tested ... not the source of game hangs // get rid of duplicate notes if any // notes = notes.Distinct().ToList(); for (int shapeIndex = 0; shapeIndex < songLevel.HandShapes.Length; shapeIndex++) { var handshape = songLevel.HandShapes[shapeIndex]; handShapes.Add(new SongHandShape { ChordId = handshape.ChordId, EndTime = handshape.EndTime, StartTime = handshape.StartTime }); } levels.Add(new SongLevel2014 { Anchors = anchors.ToArray(), Chords = chords.ToArray(), Difficulty = songLevel.Difficulty, HandShapes = handShapes.ToArray(), Notes = notes.ToArray() }); } rsSong2014.Levels = levels.ToArray(); return rsSong2014; }
private void AddElements(Song2014 rs2014Song, Song rs1Song) { // these elements have direct mapping rs1Song.Phrases = rs2014Song.Phrases; rs1Song.LinkedDiffs = rs2014Song.LinkedDiffs; rs1Song.PhraseProperties = rs2014Song.PhraseProperties; rs1Song.FretHandMuteTemplates = rs2014Song.FretHandMuteTemplates; rs1Song.Ebeats = rs2014Song.Ebeats; rs1Song.Sections = rs2014Song.Sections; rs1Song.Events = rs2014Song.Events; }
private void AddDifferences(Song2014 rs2014Song, Song rs1Song) { // there are slight mapping differences to account for in some elements for (var i = 0; i < rs2014Song.PhraseProperties.Count(); i++) { // TODO: Verify this element accuracy if (rs2014Song.PhraseProperties[i].Redundant == 256) // there may be a second phraseProperties[].redudant rs1Song.PhraseProperties[i].Redundant = 0; } // add sufficient elements for phraseIterations var phrases = new List<SongPhraseIteration>(); for (var i = 0; i < rs2014Song.PhraseIterations.Count(); i++) { phrases.Add(new SongPhraseIteration { PhraseId = i, Time = 0 }); } if (rs2014Song.PhraseIterations.Count() > 0) // pop phraseIterations { rs1Song.PhraseIterations = phrases.ToArray(); for (var i = 0; i < rs2014Song.PhraseIterations.Count(); i++) { rs1Song.PhraseIterations[i].PhraseId = rs2014Song.PhraseIterations[i].PhraseId; rs1Song.PhraseIterations[i].Time = rs2014Song.PhraseIterations[i].Time; } } // add sufficient elements for chordTemplates var chordTemplate = new List<SongChordTemplate>(); for (var i = 0; i < rs2014Song.ChordTemplates.Count(); i++) { chordTemplate.Add(new SongChordTemplate { ChordName = "C", Finger0 = 0, Finger1 = 0, Finger2 = 0, Finger3 = 0, Finger4 = 0, Finger5 = 0, Fret0 = 0, Fret1 = 0, Fret2 = 0, Fret3 = 0, Fret4 = 0, Fret5 = 0 }); } if (rs2014Song.ChordTemplates.Count() > 0) // pop chordTemplates { rs1Song.ChordTemplates = chordTemplate.ToArray(); for (var i = 0; i < rs2014Song.ChordTemplates.Count(); i++) { rs1Song.ChordTemplates[i].ChordName = rs2014Song.ChordTemplates[i].ChordName; rs1Song.ChordTemplates[i].Finger0 = rs2014Song.ChordTemplates[i].Finger0; rs1Song.ChordTemplates[i].Finger1 = rs2014Song.ChordTemplates[i].Finger1; rs1Song.ChordTemplates[i].Finger2 = rs2014Song.ChordTemplates[i].Finger2; rs1Song.ChordTemplates[i].Finger3 = rs2014Song.ChordTemplates[i].Finger3; rs1Song.ChordTemplates[i].Finger4 = rs2014Song.ChordTemplates[i].Finger4; rs1Song.ChordTemplates[i].Finger5 = rs2014Song.ChordTemplates[i].Finger5; rs1Song.ChordTemplates[i].Fret0 = rs2014Song.ChordTemplates[i].Fret0; rs1Song.ChordTemplates[i].Fret1 = rs2014Song.ChordTemplates[i].Fret1; rs1Song.ChordTemplates[i].Fret2 = rs2014Song.ChordTemplates[i].Fret2; rs1Song.ChordTemplates[i].Fret3 = rs2014Song.ChordTemplates[i].Fret3; rs1Song.ChordTemplates[i].Fret4 = rs2014Song.ChordTemplates[i].Fret4; rs1Song.ChordTemplates[i].Fret5 = rs2014Song.ChordTemplates[i].Fret5; } } // add sufficient elements for levels var levels = new List<SongLevel>(); for (var i = 0; i < rs2014Song.Levels.Count(); i++) { levels.Add(new SongLevel { Anchors = new SongAnchor[rs2014Song.Levels[i].Anchors.Length], Chords = new SongChord[rs2014Song.Levels[i].Chords.Length], Difficulty = i, HandShapes = new SongHandShape[rs2014Song.Levels[i].HandShapes.Length], Notes = new SongNote[rs2014Song.Levels[i].Notes.Length] }); } if (rs2014Song.Levels.Count() > 0) { rs1Song.Levels = levels.ToArray(); var anchors = new List<SongAnchor>(); for (var i = 0; i < rs2014Song.Levels.Count(); i++) { for (var j = 0; j < rs2014Song.Levels[i].Anchors.Count(); j++) { anchors.Add(new SongAnchor { Fret = 0, Time = 0 }); } rs1Song.Levels[i].Anchors = anchors.ToArray(); anchors.Clear(); } } var chords = new List<SongChord>(); for (var i = 0; i < rs2014Song.Levels.Count(); i++) { for (var j = 0; j < rs2014Song.Levels[i].Chords.Count(); j++) { chords.Add(new SongChord { Time = 0, HighDensity = 0x00, Ignore = 0x00, Strum = "down" }); } if (rs2014Song.Levels[i].Chords.Count() > 0) { rs1Song.Levels[i].Chords = chords.ToArray(); chords.Clear(); } } var handShape = new List<SongHandShape>(); for (var i = 0; i < rs2014Song.Levels.Count(); i++) { for (var j = 0; j < rs2014Song.Levels[i].HandShapes.Count(); j++) { handShape.Add(new SongHandShape { ChordId = 0, StartTime = 0, EndTime = 0 }); } if (rs2014Song.Levels[i].HandShapes.Count() > 0) { rs1Song.Levels[i].HandShapes = handShape.ToArray(); handShape.Clear(); } } var notes = new List<SongNote>(); for (var i = 0; i < rs2014Song.Levels.Count(); i++) { for (var j = 0; j < rs2014Song.Levels[i].Notes.Count(); j++) { notes.Add(new SongNote { Time = 0, Bend = 0, Fret = 0, HammerOn = 0x00, Harmonic = 0x00, Hopo = 0x00, Ignore = 0x00, PalmMute = 0x00, Pluck = 0, PullOff = 0x00, Slap = 0x00, SlideTo = 0, String = 0, Sustain = 0x00, Tremolo = 0x00 }); } if (rs2014Song.Levels[i].Notes.Count() > 0) { rs1Song.Levels[i].Notes = notes.ToArray(); notes.Clear(); } } // populate elements for (var i = 0; i < rs2014Song.Levels.Count(); i++) { rs1Song.Levels[i].Difficulty = rs2014Song.Levels[i].Difficulty; for (var j = 0; j < rs2014Song.Levels[i].Anchors.Count(); j++) { rs1Song.Levels[i].Anchors[j].Time = rs2014Song.Levels[i].Anchors[j].Time; rs1Song.Levels[i].Anchors[j].Fret = rs2014Song.Levels[i].Anchors[j].Fret; } for (var j = 0; j < rs2014Song.Levels[i].Chords.Count(); j++) { rs1Song.Levels[i].Chords[j].Time = rs2014Song.Levels[i].Chords[j].Time; rs1Song.Levels[i].Chords[j].ChordId = rs2014Song.Levels[i].Chords[j].ChordId; rs1Song.Levels[i].Chords[j].HighDensity = rs2014Song.Levels[i].Chords[j].HighDensity; rs1Song.Levels[i].Chords[j].Ignore = rs2014Song.Levels[i].Chords[j].Ignore; rs1Song.Levels[i].Chords[j].Strum = rs2014Song.Levels[i].Chords[j].Strum; } for (var j = 0; j < rs2014Song.Levels[i].HandShapes.Count(); j++) { rs1Song.Levels[i].HandShapes[j].ChordId = rs2014Song.Levels[i].HandShapes[j].ChordId; rs1Song.Levels[i].HandShapes[j].StartTime = rs2014Song.Levels[i].HandShapes[j].StartTime; rs1Song.Levels[i].HandShapes[j].EndTime = rs2014Song.Levels[i].HandShapes[j].EndTime; } for (var j = 0; j < rs2014Song.Levels[i].Notes.Count(); j++) { rs1Song.Levels[i].Notes[j].Time = rs2014Song.Levels[i].Notes[j].Time; rs1Song.Levels[i].Notes[j].Bend = (int)rs2014Song.Levels[i].Notes[j].Bend; rs1Song.Levels[i].Notes[j].Fret = rs2014Song.Levels[i].Notes[j].Fret; rs1Song.Levels[i].Notes[j].HammerOn = rs2014Song.Levels[i].Notes[j].HammerOn; rs1Song.Levels[i].Notes[j].Harmonic = rs2014Song.Levels[i].Notes[j].Harmonic; rs1Song.Levels[i].Notes[j].Hopo = rs2014Song.Levels[i].Notes[j].Hopo; rs1Song.Levels[i].Notes[j].Ignore = rs2014Song.Levels[i].Notes[j].Ignore; rs1Song.Levels[i].Notes[j].PalmMute = rs2014Song.Levels[i].Notes[j].PalmMute; rs1Song.Levels[i].Notes[j].Pluck = rs2014Song.Levels[i].Notes[j].Pluck; rs1Song.Levels[i].Notes[j].PullOff = rs2014Song.Levels[i].Notes[j].PullOff; rs1Song.Levels[i].Notes[j].Slap = rs2014Song.Levels[i].Notes[j].Slap; rs1Song.Levels[i].Notes[j].SlideTo = rs2014Song.Levels[i].Notes[j].SlideTo; rs1Song.Levels[i].Notes[j].String = rs2014Song.Levels[i].Notes[j].String; rs1Song.Levels[i].Notes[j].Sustain = rs2014Song.Levels[i].Notes[j].Sustain; rs1Song.Levels[i].Notes[j].Tremolo = rs2014Song.Levels[i].Notes[j].Tremolo; } } }
private int PhraseIterationCount(Song song, int ind) { return song.PhraseIterations.Count(z => z.PhraseId == ind); }
private void GenerateSectionData(Attributes attribute, Song song) { if (song.Sections == null) { return; } for (int i = 0; i < song.Sections.Length; i++) { var section = song.Sections[i]; var sect = new Section { Name = section.Name, Number = section.Number, StartTime = section.StartTime, EndTime = (i >= song.Sections.Length - 1) ? song.SongLength : song.Sections[i + 1].StartTime, UIName = String.Format("$[6007] {0} [1]", section.Name) }; var sep = sect.Name.Split(new string[1] { " " }, StringSplitOptions.RemoveEmptyEntries); if (sep.Length == 1) { string uiName; if (SectionUINames.TryGetValue(sep[0], out uiName)) sect.UIName = uiName; } else { string uiName; if (SectionUINames.TryGetValue(sep[0], out uiName)) { try { if (Convert.ToInt32(sep[1]) != 0 || Convert.ToInt32(sep[1]) != 1) uiName += String.Format("|{0}", sep[1]); } catch { } sect.UIName = uiName; } } var phraseIterStart = -1; var phraseIterEnd = 0; var isSolo = false; if (song.PhraseIterations != null) { for (int o = 0; o < song.PhraseIterations.Length; o++) { var phraseIter = song.PhraseIterations[o]; if (phraseIterStart == -1 && phraseIter.Time >= sect.StartTime) phraseIterStart = o; if (phraseIter.Time >= sect.EndTime) break; phraseIterEnd = o; if (song.Phrases[phraseIter.PhraseId].Solo > 0) isSolo = true; } } sect.StartPhraseIterationIndex = phraseIterStart; sect.EndPhraseIterationIndex = phraseIterEnd; sect.IsSolo = isSolo; attribute.Sections.Add(sect); } }
private Song2014 ConvertChordTemplates(Song rsSong, Song2014 rsSong2014) { // add chordTemplates elements var chordTemplate = new List<SongChordTemplate2014>(); foreach (var songChordTemplate in rsSong.ChordTemplates) { // tested ... not the source of game hangs //if (String.IsNullOrEmpty(songChordTemplate.ChordName)) // continue; chordTemplate.Add(new SongChordTemplate2014 { ChordName = songChordTemplate.ChordName, DisplayName = songChordTemplate.ChordName, Finger0 = (sbyte)songChordTemplate.Finger0, Finger1 = (sbyte)songChordTemplate.Finger1, Finger2 = (sbyte)songChordTemplate.Finger2, Finger3 = (sbyte)songChordTemplate.Finger3, Finger4 = (sbyte)songChordTemplate.Finger4, Finger5 = (sbyte)songChordTemplate.Finger5, Fret0 = (sbyte)songChordTemplate.Fret0, Fret1 = (sbyte)songChordTemplate.Fret1, Fret2 = (sbyte)songChordTemplate.Fret2, Fret3 = (sbyte)songChordTemplate.Fret3, Fret4 = (sbyte)songChordTemplate.Fret4, Fret5 = (sbyte)songChordTemplate.Fret5 }); } // tested ... not the source of game hangs // get rid of duplicate chords if any // chordTemplate = chordTemplate.Distinct().ToList(); // tested ... could be source of game hangs if (rsSong.ChordTemplates == null) { Console.WriteLine("Applied fix to RS1->RS2 ChordTemplates conversion"); rsSong2014.ChordTemplates = new SongChordTemplate2014[0]; } else rsSong2014.ChordTemplates = chordTemplate.ToArray(); return rsSong2014; }
/// <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; }
private static List<PhraseIterationInfo> CreatePhraseIterationInfo(Song rocksmithSong) { List<PhraseIterationInfo> info = new List<PhraseIterationInfo>(rocksmithSong.PhraseIterations.Length); for (int i = 0; i < rocksmithSong.PhraseIterations.Length; i++) { var iteration = rocksmithSong.PhraseIterations[i]; var phrase = rocksmithSong.Phrases[iteration.PhraseId]; var endTime = rocksmithSong.SongLength; if (i + 1 < rocksmithSong.PhraseIterations.Length) { endTime = rocksmithSong.PhraseIterations[i + 1].Time; } info.Add(new PhraseIterationInfo { IterationId = i, PhraseId = iteration.PhraseId, MaxDifficulty = phrase.MaxDifficulty, StartTime = iteration.Time, EndTime = endTime }); } return info; }
private Song2014 ConvertPhraseIterations(Song rsSong, Song2014 rsSong2014) { var phraseIterations = new List<SongPhraseIteration2014>(); foreach (var songPhraseIteration in rsSong.PhraseIterations) { // HeroLevels set to null -> prevent some hangs phraseIterations.Add(new SongPhraseIteration2014 { PhraseId = songPhraseIteration.PhraseId, HeroLevels = null, Time = songPhraseIteration.Time }); } rsSong2014.PhraseIterations = phraseIterations.ToArray(); return rsSong2014; }
// COMPLETE private static void WriteRocksmithSngFile(Song rocksmithSong, InstrumentTuning tuning, ArrangementType arrangementType, string outputFile, EndianBitConverter bitConverter) { var iterationInfo = CreatePhraseIterationInfo(rocksmithSong); // WRITE THE .SNG FILE using (FileStream fs = new FileStream(outputFile, FileMode.Create)) using (EndianBinaryWriter w = new EndianBinaryWriter(bitConverter, fs)) { // HEADER WriteRocksmithSngHeader(w, arrangementType); // EBEATS DATA WriteRocksmithSngEbeats(w, rocksmithSong.Ebeats); // PHRASES WriteRocksmithSngPhrases(w, rocksmithSong.Phrases, rocksmithSong.PhraseIterations); // CHORD TEMPLATES WriteRocksmithSngChordTemplates(w, rocksmithSong.ChordTemplates, tuning, arrangementType); // FRET HAND MUTE TEMPLATE WriteRocksmithSngFretHandMuteTemplates(w, rocksmithSong.FretHandMuteTemplates); // VOCALS TEMPLATE w.Write(new byte[4]); // not used on song file // PHRASE ITERATIONS WriteRocksmithSngPhraseIterations(w, rocksmithSong.PhraseIterations, rocksmithSong.SongLength); // PHRASE PROPERTIES WriteRocksmithSngPhraseProperties(w, rocksmithSong.PhraseProperties); // LINKED DIFFS WriteRocksmithSngLinkedDiffs(w, rocksmithSong.LinkedDiffs); // CONTROLS WriteRocksmithSngControls(w, rocksmithSong.Controls); // EVENTS WriteRocksmithSngEvents(w, rocksmithSong.Events); // SECTIONS WriteRocksmithSngSections(w, rocksmithSong.Sections, rocksmithSong.PhraseIterations, rocksmithSong.SongLength); // LEVELS WriteRocksmithSngLevels(w, rocksmithSong.Levels, rocksmithSong.SongLength, iterationInfo, arrangementType); // SONG META DATA WriteRocksmithSngMetaDetails(w, rocksmithSong, tuning, iterationInfo); } }
private void AddNotes(RsSong rsSong, Song zigSong) { int spread = 3; var notes = new Dictionary <string, List <SongNote> >(); var chords = new Dictionary <string, List <SongChord> >(); var anchors = new Dictionary <string, List <SongAnchor> >(); var handShapes = new Dictionary <string, List <SongHandShape> >(); var chordTemps = new Dictionary <string, Tuple <int, SongChordTemplate> >(); var guitarTrack = GetTrack(zigSong); foreach (var group in guitarTrack.Chords.GroupBy(chord => chord.Difficulty)) { var gNotes = notes[group.Key] = new List <SongNote>(); var gChords = chords[group.Key] = new List <SongChord>(); var gAnchors = anchors[group.Key] = new List <SongAnchor>(); var gHandShapes = handShapes[group.Key] = new List <SongHandShape>(); var zChords = group.OrderBy(chord => chord.StartTime).ToList(); var lastMeasure = 0; int highFret = -1; //bool lastWasChord = false; SongAnchor curAnchor = null; for (int i = 0; i < zChords.Count; i++) { var zChord = zChords[i]; if (zChord.Notes.Count > 1) { Tuple <int, SongChordTemplate> val = GetChordTemplate(zChord, chordTemps); int minCFret = Math.Min(DeZero(val.Item2.Fret0), Math.Min(DeZero(val.Item2.Fret1), Math.Min(DeZero(val.Item2.Fret2), Math.Min(DeZero(val.Item2.Fret3), Math.Min(DeZero(val.Item2.Fret4), DeZero(val.Item2.Fret5)))))); if (minCFret != int.MaxValue) { if (curAnchor == null) { if (gAnchors.Count == 0 || gAnchors[gAnchors.Count - 1].Fret != minCFret) { gAnchors.Add(new SongAnchor { Fret = Math.Min(19, minCFret), Time = zChord.StartTime }); } } else { if (minCFret + spread <= highFret) { curAnchor.Fret = minCFret; } gAnchors.Add(curAnchor); if (curAnchor.Fret != minCFret) { gAnchors.Add(new SongAnchor { Fret = Math.Min(19, minCFret), Time = zChord.StartTime }); } curAnchor = null; } } SongHandShape handShape = new SongHandShape { ChordId = val.Item1, StartTime = zChord.StartTime }; do { SongChord chord = new SongChord(); chord.Time = zChord.StartTime; chord.ChordId = val.Item1; var measure = rsSong.Ebeats.FirstOrDefault(ebeat => ebeat.Time >= chord.Time); if (measure == null || measure.Measure > lastMeasure) { lastMeasure = measure == null ? lastMeasure : measure.Measure; chord.HighDensity = 0; } else if (gChords.Count == 0 || gChords[gChords.Count - 1].ChordId != chord.ChordId) { chord.HighDensity = 0; } else { chord.HighDensity = 1; } gChords.Add(chord); if (i + 1 < zChords.Count) { zChord = zChords[i + 1]; } } while (i + 1 < zChords.Count && zChord.Notes.Count > 1 && val.Item1 == GetChordTemplate(zChord, chordTemps).Item1&& ++i != -1); handShape.EndTime = zChord.StartTime; if (handShape.EndTime > handShape.StartTime) { handShape.EndTime -= (handShape.EndTime - zChords[i].EndTime) / 2; } gHandShapes.Add(handShape); } else { var note = GetNote(zChord, i == zChords.Count - 1 ? null : zChords[i + 1]); if (note.Fret > 0) { if (curAnchor == null) { curAnchor = new SongAnchor { Fret = Math.Min(19, (int)note.Fret), Time = note.Time }; highFret = note.Fret; } else if (note.Fret < curAnchor.Fret) { if (note.Fret + spread >= highFret) { curAnchor.Fret = note.Fret; } else { gAnchors.Add(curAnchor); curAnchor = new SongAnchor { Fret = Math.Min(19, (int)note.Fret), Time = note.Time }; highFret = note.Fret; } } else if (note.Fret > highFret) { if (note.Fret - spread <= curAnchor.Fret) { highFret = note.Fret; } else { gAnchors.Add(curAnchor); curAnchor = new SongAnchor { Fret = Math.Min(19, (int)note.Fret), Time = note.Time }; highFret = note.Fret; } } } gNotes.Add(note); } } if (curAnchor != null) { gAnchors.Add(curAnchor); } } rsSong.Levels = new SongLevel[] { new SongLevel { Difficulty = 0, Notes = notes["Easy"].ToArray(), Chords = chords["Easy"].ToArray(), Anchors = anchors["Easy"].ToArray(), HandShapes = handShapes["Easy"].ToArray() }, new SongLevel { Difficulty = 1, Notes = notes["Medium"].ToArray(), Chords = chords["Medium"].ToArray(), Anchors = anchors["Medium"].ToArray(), HandShapes = handShapes["Medium"].ToArray() }, new SongLevel { Difficulty = 2, Notes = notes["Hard"].ToArray(), Chords = chords["Hard"].ToArray(), Anchors = anchors["Hard"].ToArray(), HandShapes = handShapes["Hard"].ToArray() }, new SongLevel { Difficulty = 3, Notes = notes["Expert"].ToArray(), Chords = chords["Expert"].ToArray(), Anchors = anchors["Expert"].ToArray(), HandShapes = handShapes["Expert"].ToArray() } }; rsSong.ChordTemplates = chordTemps.Values.OrderBy(v => v.Item1).Select(v => v.Item2).ToArray(); }
// INCOMPLETE private static void WriteRocksmithSngMetaDetails(EndianBinaryWriter w, Song s, InstrumentTuning tuning, List<PhraseIterationInfo> iterationInfo) { // Max score when fully leveled (minus bonuses - always 100000). Or possible Master mode unlock score w.Write((double)100000); //This needs to be calculated to take real charts into account. double totalNotes = 0; foreach (var iteration in iterationInfo) { if (s.Levels.Length <= iteration.MaxDifficulty) { throw new Exception("There is a phrase defined with maxDifficulty=" + iteration.MaxDifficulty + ", but the highest difficulty level is " + (s.Levels.Length - 1)); } var level = s.Levels[iteration.MaxDifficulty]; if (level.Notes != null) { totalNotes += level.Notes.Where(note => note.Time >= iteration.StartTime && note.Time < iteration.EndTime).Count(); } if (level.Chords != null) { totalNotes += level.Chords.Where(chord => chord.Time >= iteration.StartTime && chord.Time < iteration.EndTime).Count(); } } // Total notes when fully leveled w.Write(totalNotes); // points per note w.Write((double)((float)(100000f / (float)totalNotes))); // song beat timing if (s.Ebeats.Length < 2) throw new InvalidDataException("Song must contain at least 2 beats"); // this is not 100% accurate unless all beats are evenly spaced in a song; // still trying to determine exactly how Rocksmith is deriving this time value w.Write(s.Ebeats[1].Time - s.Ebeats[0].Time); // first beat time(?); confirmed as not first phraseIteration time and not first section time w.Write(s.Ebeats[0].Time); // song conversion date var lastConvertDate = s.LastConversionDateTime; if (lastConvertDate.Length > 32) { lastConvertDate = lastConvertDate.Substring(0, 32); } foreach (char c in lastConvertDate) { w.Write(Convert.ToByte(c)); } w.Write(new byte[32 - lastConvertDate.Length]); //pad to 32 bytes // song title var title = s.Title; if (title.Length > 64) { title = title.Substring(0, 64); } foreach (char c in title) { w.Write(Convert.ToByte(c)); } w.Write(new byte[64 -title.Length]); // pad to 64 bytes // arrangement var arrangement = s.Arrangement; if (arrangement.Length > 32) { arrangement = arrangement.Substring(0, 32); } foreach (char c in arrangement) { w.Write(Convert.ToByte(c)); } w.Write(new byte[32 - arrangement.Length]); //pad to 32 bytes // artist string artistValue = string.IsNullOrEmpty(s.Artist) ? "DUMMY" : s.Artist; if (artistValue.Length > 32) { artistValue = artistValue.Substring(0, 32); } foreach (char c in artistValue) { w.Write(Convert.ToByte(c)); } w.Write(new byte[32 - artistValue.Length]); //pad to 32 bytes // song part w.Write(s.Part); // song length w.Write(s.SongLength); // tuning w.Write((Int32)tuning); //Song difficulty float difficulty = (float)iterationInfo.Average(it => it.MaxDifficulty); w.Write(difficulty); // float with 10.2927 in NumberThirteen_Lead.sng // unknown // from 6AMSalvation_Combo.xml value = 11.525 // which does not match any pharse iteration start time // and does not match first ebeat time // and does not match any section start time // does match first event time of E3 (although this is not a match in other files) // does not match any note times on 1st difficulty level // nor an anchor time on 1st difficulty level //It appears to be the time of the first note. float firstNote = s.Levels.Min(level => level.Notes == null || level.Notes.Length == 0 ? float.MaxValue : level.Notes.Min(note => note.Time)); float firstChord = s.Levels.Min(level => level.Chords == null || level.Chords.Length == 0 ? float.MaxValue : level.Chords.Min(chord => chord.Time)); float first = Math.Min(firstChord, firstNote); w.Write(first); w.Write(first); // max difficulty int maxDifficulty = s.Levels.Length-1; w.Write(maxDifficulty); // unknown section w.Write(new byte[4]); // header with repeating array; song works in game if array is defaulted to 0 count so will leave this alone for now // unknown section // There seems to be 1 entry per letter in the chord templates, although there are songs with chord templates that don't have this section. w.Write(new byte[4]); // header with repeating array - only populated in limited songs }
private void AddEbeats(RsSong rsSong, Song zigSong) { var ebeats = new List <SongEbeat>(); var phrases = new List <SongPhraseIteration>(); var tempoTrack = zigSong.Tracks.Single(tr => "Tempo".Equals(tr.Name)); var tempoIndex = 0; var tsIndex = 0; var tempo = tempoTrack.Tempos[0]; var signature = tempoTrack.TimeSignatures[0]; float time = 0; int beat = 1; short measure = 1; float secondsPerQuarter = tempo.SecondsPerBar / signature.Numerator; var end = tempoTrack.MetaEvents.Single(ev => "EndOfTrack".Equals(ev.MetaType)).StartTime; while (time < end) { ebeats.Add(new SongEbeat { Measure = (beat == 1) ? measure : (short)-1, Time = time }); var delta = secondsPerQuarter * ((float)4 / signature.Denominator); time += delta; var changed = false; if (tsIndex + 1 != tempoTrack.TimeSignatures.Count && time + delta / 2 >= tempoTrack.TimeSignatures[tsIndex + 1].StartTime) { signature = tempoTrack.TimeSignatures[++tsIndex]; time = signature.StartTime; changed = true; } if (tempoIndex + 1 != tempoTrack.Tempos.Count && time + delta / 2 >= tempoTrack.Tempos[tempoIndex + 1].StartTime) { changed = true; tempo = tempoTrack.Tempos[++tempoIndex]; time = tempo.StartTime; secondsPerQuarter = tempo.SecondsPerBar / signature.Numerator; } if (changed || ++beat > signature.Numerator) { beat = 1; ++measure; } } rsSong.Ebeats = ebeats.ToArray(); var guitarTrack = GetTrack(zigSong); var firstNote = guitarTrack.Chords.Min(c => c.StartTime); var lastNote = guitarTrack.Chords.Max(c => c.EndTime); int measOffset = ebeats.Where(eb => eb.Measure != -1 && eb.Time <= firstNote).Last().Measure, phraseId = 0; measure = (short)measOffset; SongEbeat ebeat = null; //count in phrases.Add(new SongPhraseIteration { PhraseId = phraseId++, Time = 0 }); while (null != (ebeat = ebeats.FirstOrDefault(eb => eb.Measure == measure))) { if (ebeat.Time >= lastNote) { break; } phrases.Add(new SongPhraseIteration { PhraseId = phraseId++, Time = ebeat.Time }); measure += 12; } //end phrases.Add(new SongPhraseIteration { PhraseId = phraseId++, Time = lastNote + .001f }); rsSong.PhraseIterations = phrases.ToArray(); rsSong.Phrases = phrases.Select(it => new SongPhrase { MaxDifficulty = it.PhraseId == 0 || it.PhraseId == phrases.Count - 1 ? 0:3, Name = it.PhraseId == 0 ? "COUNT" : it.PhraseId == phrases.Count - 1 ? "END" : it.PhraseId.ToString() }).ToArray(); phrases.RemoveAt(0); phrases.RemoveAt(phrases.Count - 1); rsSong.Sections = phrases.Select(it => new SongSection { Name = "verse", Number = 1, StartTime = it.Time }).ToArray(); }
// Load RS1 CDLC into PackageCreator public static DLCPackageData RS1LoadFromFolder(string unpackedDir, Platform targetPlatform, bool convert) { var data = new DLCPackageData(); data.Arrangements = new List<Arrangement>(); data.TonesRS2014 = new List<Tone2014>(); data.Tones = new List<Tone>(); data.GameVersion = (convert ? GameVersion.RS2014 : GameVersion.RS2012); data.SignatureType = PackageMagic.CON; // set default volumes data.Volume = -6.5F; // default maybe too quite data.PreviewVolume = data.Volume; //Load song manifest var songsManifestJson = Directory.GetFiles(unpackedDir, "songs.manifest.json", SearchOption.AllDirectories); if (songsManifestJson.Length < 1) throw new DataException("No songs.manifest.json file found."); if (songsManifestJson.Length > 1) throw new DataException("More than one songs.manifest.json file found."); var attr = new List<Attributes>(); var songsManifest = Manifest.Manifest.LoadFromFile(songsManifestJson[0]).Entries.ToArray(); for (int smIndex = 0; smIndex < songsManifest.Count(); smIndex++) { var smData = songsManifest[smIndex].Value.ToArray()[0].Value; attr.Add(smData); } if (attr.FirstOrDefault() == null) throw new DataException("songs.manifest.json file did not parse correctly."); // Fill SongInfo data.SongInfo = new SongInfo(); data.SongInfo.SongDisplayName = attr.FirstOrDefault().SongName; data.SongInfo.SongDisplayNameSort = attr.FirstOrDefault().SongNameSort; data.SongInfo.Album = attr.FirstOrDefault().AlbumName; data.SongInfo.SongYear = (attr.FirstOrDefault().SongYear == 0 ? 2012 : attr.FirstOrDefault().SongYear); data.SongInfo.Artist = attr.FirstOrDefault().ArtistName; data.SongInfo.ArtistSort = attr.FirstOrDefault().ArtistNameSort; data.Name = attr.FirstOrDefault().SongKey; //Load tone manifest, even poorly formed tone_bass.manifest.json var toneManifestJson = Directory.GetFiles(unpackedDir, "*tone*.manifest.json", SearchOption.AllDirectories); if (toneManifestJson.Length < 1) throw new DataException("No tone.manifest.json file found."); // toolkit produces multiple tone.manifest.json files when packing RS1 CDLC files // rather than change toolkit behavior just merge manifest files for now if (toneManifestJson.Length > 1) { var mergeSettings = new JsonMergeSettings { MergeArrayHandling = MergeArrayHandling.Union }; JObject toneObject1 = new JObject(); foreach (var tone in toneManifestJson) { JObject toneObject2 = JObject.Parse(File.ReadAllText(tone)); //(toneObject1.SelectToken("Entries") as JArray).Merge(toneObject2.SelectToken("Entries")); toneObject1.Merge(toneObject2, mergeSettings); } toneManifestJson = new string[1]; toneManifestJson[0] = Path.Combine(unpackedDir, "merged.tone.manifest.json"); string json = JsonConvert.SerializeObject(toneObject1, Formatting.Indented); File.WriteAllText(toneManifestJson[0], json); } var tones2014 = new List<Tone2014>(); var tones = new List<Tone>(); var toneManifest = Manifest.Tone.Manifest.LoadFromFile(toneManifestJson[0]); for (int tmIndex = 0; tmIndex < toneManifest.Entries.Count(); tmIndex++) { var tmData = toneManifest.Entries[tmIndex]; tones.Add(tmData); } data.Tones = tones; // Load AggregateGraph.nt var songDir = Path.Combine(unpackedDir, data.Name); if (targetPlatform.platform == GamePlatform.XBox360) songDir = Path.Combine(unpackedDir, "Root", data.Name); var aggFile = Directory.GetFiles(songDir, "*.nt", SearchOption.TopDirectoryOnly)[0]; var aggGraphData = AggregateGraph.AggregateGraph.ReadFromFile(aggFile); // Load Exports\Songs\*.xblock var xblockDir = Path.Combine(songDir, "Exports\\Songs"); var xblockFile = Directory.GetFiles(xblockDir, "*.xblock", SearchOption.TopDirectoryOnly)[0]; // xblockFile = "D:\\Temp\\Mapping\\songs.xblock"; var songsXblock = XblockX.LoadFromFile(xblockFile); // create project map for cross referencing arrangements with tones var projectMap = AggregateGraph.AggregateGraph.ProjectMap(aggGraphData, songsXblock, toneManifest); // Load xml arrangements var xmlFiles = Directory.GetFiles(unpackedDir, "*.xml", SearchOption.AllDirectories); if (xmlFiles.Length <= 0) throw new DataException("Can not find any XML arrangement files"); foreach (var xmlFile in xmlFiles) { if (xmlFile.ToLower().Contains("metadata")) // skip DeadFox file continue; // some poorly formed RS1 CDLC use just "vocal" if (xmlFile.ToLower().Contains("vocal")) { // Add Vocal Arrangement data.Arrangements.Add(new Arrangement { Name = ArrangementName.Vocals, ArrangementType = ArrangementType.Vocal, ScrollSpeed = 20, SongXml = new SongXML { File = xmlFile }, SongFile = new SongFile { File = "" }, CustomFont = false }); } else { var attr2014 = new Attributes2014(); var rsSong = new Song(); var rsSong2014 = new Song2014(); // optimized tone matching effort using project mapping algo var result = projectMap.First(m => String.Equals(Path.GetFileName(m.SongXmlPath), Path.GetFileName(xmlFile), StringComparison.CurrentCultureIgnoreCase)); if (result.Tones.Count != 1) throw new DataException("Invalid RS1 CDLC Tones Data"); var arrangement = attr.First(s => s.SongXml.ToLower().Contains(result.LLID)); var tone = tones.First(t => t.Key == result.Tones[0]); using (var obj1 = new Rs1Converter()) { rsSong = obj1.XmlToSong(xmlFile); data.SongInfo.AverageTempo = (int)obj1.AverageBPM(rsSong); } if (arrangement.Tuning == "E Standard") rsSong.Tuning = new TuningStrings { String0 = 0, String1 = 0, String2 = 0, String3 = 0, String4 = 0, String5 = 0 }; else if (arrangement.Tuning == "DropD") rsSong.Tuning = new TuningStrings { String0 = -2, String1 = 0, String2 = 0, String3 = 0, String4 = 0, String5 = 0 }; else if (arrangement.Tuning == "OpenG") rsSong.Tuning = new TuningStrings { String0 = -2, String1 = -2, String2 = 0, String3 = 0, String4 = 0, String5 = -2 }; else if (arrangement.Tuning == "EFlat") rsSong.Tuning = new TuningStrings { String0 = -1, String1 = -1, String2 = -1, String3 = -1, String4 = -1, String5 = -1 }; else // default to standard tuning { arrangement.Tuning = "E Standard"; rsSong.Tuning = new TuningStrings { String0 = 0, String1 = 0, String2 = 0, String3 = 0, String4 = 0, String5 = 0 }; } // save/write the changes to xml file using (var obj1 = new Rs1Converter()) obj1.SongToXml(rsSong, xmlFile, true); if (convert) using (var obj1 = new Rs1Converter()) tones2014.Add(obj1.ToneToTone2014(tone, rsSong)); // load attr2014 with RS1 mapped values for use by Arrangement() attr2014.Tone_Base = tone.Name; attr2014.ArrangementName = arrangement.ArrangementName; attr2014.CentOffset = 0; attr2014.DynamicVisualDensity = new List<float>() { 2 }; attr2014.SongPartition = arrangement.SongPartition; attr2014.PersistentID = IdGenerator.Guid().ToString(); attr2014.MasterID_RDV = RandomGenerator.NextInt(); attr2014.ArrangementProperties = new SongArrangementProperties2014(); // processing order is important - CAREFUL // RouteMask None = 0, Lead = 1, Rhythm = 2, Any = 3, Bass = 4 // XML file names are usually meaningless to arrangement determination if (arrangement.ArrangementName.ToLower().Contains("lead") || rsSong.Arrangement.ToLower().Contains("lead")) { attr2014.ArrangementName = "Lead"; attr2014.ArrangementType = (int)ArrangementType.Guitar; attr2014.ArrangementProperties.RouteMask = (int)RouteMask.Lead; attr2014.ArrangementProperties.PathLead = 1; attr2014.ArrangementProperties.PathRhythm = 0; attr2014.ArrangementProperties.PathBass = 0; } else if (arrangement.ArrangementName.ToLower().Contains("rhythm") || rsSong.Arrangement.ToLower().Contains("rhythm")) // || rsSong.Arrangement.ToLower().Contains("guitar")) { attr2014.ArrangementName = "Rhythm"; attr2014.ArrangementType = (int)ArrangementType.Guitar; attr2014.ArrangementProperties.RouteMask = (int)RouteMask.Rhythm; attr2014.ArrangementProperties.PathLead = 0; attr2014.ArrangementProperties.PathRhythm = 1; attr2014.ArrangementProperties.PathBass = 0; } else if (arrangement.ArrangementName.ToLower().Contains("combo") || rsSong.Arrangement.ToLower().Contains("combo")) { attr2014.ArrangementName = "Combo"; attr2014.ArrangementType = (int)ArrangementType.Guitar; attr2014.ArrangementProperties.RouteMask = arrangement.EffectChainName.ToLower().Contains("lead") ? (int)RouteMask.Lead : (int)RouteMask.Rhythm; attr2014.ArrangementProperties.PathLead = arrangement.EffectChainName.ToLower().Contains("lead") ? 1 : 0; attr2014.ArrangementProperties.PathRhythm = arrangement.EffectChainName.ToLower().Contains("lead") ? 0 : 1; attr2014.ArrangementProperties.PathBass = 0; } else if (arrangement.ArrangementName.ToLower().Contains("bass") || rsSong.Arrangement.ToLower().Contains("bass")) { attr2014.ArrangementName = "Bass"; attr2014.ArrangementType = (int)ArrangementType.Bass; attr2014.ArrangementProperties.RouteMask = (int)RouteMask.Bass; attr2014.ArrangementProperties.PathLead = 0; attr2014.ArrangementProperties.PathRhythm = 0; attr2014.ArrangementProperties.PathBass = 1; } else { // default to Lead arrangment attr2014.ArrangementName = "Lead"; attr2014.ArrangementType = (int)ArrangementType.Guitar; attr2014.ArrangementProperties.RouteMask = (int)RouteMask.Lead; attr2014.ArrangementProperties.PathLead = 1; attr2014.ArrangementProperties.PathRhythm = 0; attr2014.ArrangementProperties.PathBass = 0; Console.WriteLine("RS1->RS2 CDLC Conversion defaulted to 'Lead' arrangment"); } if (convert) // RS1 -> RS2 magic { using (var obj1 = new Rs1Converter()) rsSong2014 = obj1.SongToSong2014(rsSong); // update ArrangementProperties rsSong2014.ArrangementProperties.RouteMask = attr2014.ArrangementProperties.RouteMask; rsSong2014.ArrangementProperties.PathLead = attr2014.ArrangementProperties.PathLead; rsSong2014.ArrangementProperties.PathRhythm = attr2014.ArrangementProperties.PathRhythm; rsSong2014.ArrangementProperties.PathBass = attr2014.ArrangementProperties.PathBass; rsSong2014.ArrangementProperties.StandardTuning = (arrangement.Tuning == "E Standard" ? 1 : 0); // <note time="58.366" linkNext="0" accent="0" bend="0" fret="7" hammerOn="0" harmonic="0" hopo="0" ignore="0" leftHand="-1" mute="0" palmMute="0" pluck="-1" pullOff="0" slap="-1" slideTo="-1" string="3" sustain="0.108" tremolo="0" harmonicPinch="0" pickDirection="0" rightHand="-1" slideUnpitchTo="-1" tap="0" vibrato="0" /> if (rsSong2014.Levels.Any(sl => sl.Notes.Any(sln => sln.Bend != 0))) rsSong2014.ArrangementProperties.Bends = 1; if (rsSong2014.Levels.Any(sl => sl.Notes.Any(sln => sln.Hopo != 0))) rsSong2014.ArrangementProperties.Hopo = 1; if (rsSong2014.Levels.Any(sl => sl.Notes.Any(sln => sln.SlideTo != -1))) rsSong2014.ArrangementProperties.Slides = 1; if (rsSong2014.Levels.Any(sl => sl.Notes.Any(sln => sln.Sustain > 0))) rsSong2014.ArrangementProperties.Sustain = 1; // fixing times that are off var lastEbeatsTime = rsSong2014.Ebeats[rsSong2014.Ebeats.Length - 1].Time; var lastPhraseIterationsTime = rsSong2014.PhraseIterations[rsSong2014.PhraseIterations.Length - 1].Time; // tested ... not source of in game hangs // confirm last PhraseIterations time is less than last Ebeats time if (lastPhraseIterationsTime > lastEbeatsTime) { rsSong2014.PhraseIterations[rsSong2014.PhraseIterations.Length - 1].Time = lastEbeatsTime; rsSong2014.Sections[rsSong2014.Sections.Length - 1].StartTime = lastEbeatsTime; } // tested ... not source of in game hangs // confirm SongLength at least equals last Ebeats time if (rsSong2014.SongLength < lastEbeatsTime) rsSong2014.SongLength = lastEbeatsTime; using (var obj2 = new Rs2014Converter()) obj2.Song2014ToXml(rsSong2014, xmlFile, true); } // Adding Song Arrangement try { data.Arrangements.Add(new Arrangement(attr2014, xmlFile)); } catch (Exception ex) { // mainly for the benifit of convert2012 CLI users Console.WriteLine(@"This CDLC could not be auto converted." + Environment.NewLine + "You can still try manually adding the arrangements and assests." + Environment.NewLine + ex.Message); } } } if (convert) { // get rid of duplicate tone names tones2014 = tones2014.Where(p => p.Name != null) .GroupBy(p => p.Name).Select(g => g.First()).ToList(); data.TonesRS2014 = tones2014; } //Get Album Artwork DDS Files var artFiles = Directory.GetFiles(unpackedDir, "*.dds", SearchOption.AllDirectories); if (artFiles.Length < 1) throw new DataException("No Album Artwork file found."); if (artFiles.Length > 1) throw new DataException("More than one Album Artwork file found."); var targetArtFiles = new List<DDSConvertedFile>(); data.AlbumArtPath = artFiles[0]; targetArtFiles.Add(new DDSConvertedFile() { sizeX = 256, sizeY = 256, sourceFile = artFiles[0], destinationFile = artFiles[0].CopyToTempFile(".dds") }); data.ArtFiles = targetArtFiles; //Audio files var targetAudioFiles = new List<string>(); var audioFiles = Directory.GetFiles(unpackedDir, "*.ogg", SearchOption.AllDirectories); if (audioFiles.Length < 1) throw new DataException("No Audio file found."); if (audioFiles.Length > 2) throw new DataException("Too many Audio files found."); int i; for (i = 0; i < audioFiles.Length; i++) { if (convert && audioFiles[i].Contains("_fixed.ogg")) // use it break; if (!convert && !audioFiles[i].Contains("_fixed.ogg")) break; } // FIXME: platform specific decode is broken var sourcePlatform = unpackedDir.GetPlatform(); if (targetPlatform.IsConsole != (sourcePlatform = audioFiles[i].GetAudioPlatform()).IsConsole) { var newFile = Path.Combine(Path.GetDirectoryName(audioFiles[i]), String.Format("{0}_cap.ogg", Path.GetFileNameWithoutExtension(audioFiles[i]))); OggFile.ConvertAudioPlatform(audioFiles[i], newFile); audioFiles[i] = newFile; } targetAudioFiles.Add(audioFiles[i]); if (!targetAudioFiles.Any()) throw new DataException("Audio file not found."); var a = new FileInfo(audioFiles[i]); data.OggPath = a.FullName; //AppID if (!sourcePlatform.IsConsole) { if (!convert) { var appidFile = Directory.GetFiles(unpackedDir, "*APP_ID*", SearchOption.AllDirectories); if (appidFile.Length > 0) data.AppId = File.ReadAllText(appidFile[0]); } else data.AppId = "248750"; } try {//TODO: validate that rs1 songs have no this file //Package version var versionFile = Directory.GetFiles(unpackedDir, "toolkit.version", SearchOption.AllDirectories); if (versionFile.Length > 0) data.PackageVersion = GeneralExtensions.ReadPackageVersion(versionFile[0]); else data.PackageVersion = "1"; } catch {} if (convert) data.Tones = null; return data; }
private static void GeneratePhraseData(Attributes attribute, Song song) { if (song.Phrases == null) { return; } var ind = 0; foreach (var y in song.Phrases) { int itcount = song.PhraseIterations.Count(z => z.PhraseId == ind); attribute.Phrases.Add(new Phrase { IterationCount = itcount, MaxDifficulty = y.MaxDifficulty, Name = y.Name }); ind++; } }
private void AddEbeats(RsSong rsSong, Song zigSong) { var ebeats = new List<SongEbeat>(); var phrases = new List<SongPhraseIteration>(); var tempoTrack = zigSong.Tracks.Single(tr => "Tempo".Equals(tr.Name)); var tempoIndex = 0; var tsIndex = 0; var tempo = tempoTrack.Tempos[0]; var signature = tempoTrack.TimeSignatures[0]; float time = 0; int beat = 1; short measure = 1; float secondsPerQuarter = tempo.SecondsPerBar / signature.Numerator; var end = tempoTrack.MetaEvents.Single(ev => "EndOfTrack".Equals(ev.MetaType)).StartTime; while (time < end) { ebeats.Add(new SongEbeat { Measure = (beat == 1) ? measure : (short)-1, Time = time }); var delta = secondsPerQuarter * ((float)4 / signature.Denominator); time += delta; var changed = false; if (tsIndex + 1 != tempoTrack.TimeSignatures.Count && time + delta / 2 >= tempoTrack.TimeSignatures[tsIndex + 1].StartTime) { signature = tempoTrack.TimeSignatures[++tsIndex]; time = signature.StartTime; changed = true; } if (tempoIndex + 1 != tempoTrack.Tempos.Count && time + delta / 2 >= tempoTrack.Tempos[tempoIndex + 1].StartTime) { changed = true; tempo = tempoTrack.Tempos[++tempoIndex]; time = tempo.StartTime; secondsPerQuarter = tempo.SecondsPerBar / signature.Numerator; } if (changed || ++beat > signature.Numerator) { beat = 1; ++measure; } } rsSong.Ebeats = ebeats.ToArray(); var guitarTrack = GetTrack(zigSong); var firstNote = guitarTrack.Chords.Min(c => c.StartTime); var lastNote = guitarTrack.Chords.Max(c => c.EndTime); int measOffset = ebeats.Where(eb => eb.Measure != -1 && eb.Time <= firstNote).Last().Measure, phraseId = 0; measure = (short)measOffset; SongEbeat ebeat = null; //count in phrases.Add(new SongPhraseIteration { PhraseId = phraseId++, Time = 0 }); while (null != (ebeat = ebeats.FirstOrDefault(eb => eb.Measure == measure))) { if (ebeat.Time >= lastNote) { break; } phrases.Add(new SongPhraseIteration { PhraseId = phraseId++, Time = ebeat.Time }); measure += 12; } //end phrases.Add(new SongPhraseIteration { PhraseId = phraseId++, Time = lastNote + .001f }); rsSong.PhraseIterations = phrases.ToArray(); rsSong.Phrases = phrases.Select(it => new SongPhrase { MaxDifficulty = it.PhraseId == 0 || it.PhraseId == phrases.Count - 1 ? 0:3, Name = it.PhraseId == 0 ? "COUNT" : it.PhraseId == phrases.Count - 1 ? "END" : it.PhraseId.ToString() }).ToArray(); phrases.RemoveAt(0); phrases.RemoveAt(phrases.Count - 1); rsSong.Sections = phrases.Select(it => new SongSection { Name = "verse", Number = 1, StartTime = it.Time }).ToArray(); }
/// <summary> /// Convert RS1 Song Object to RS2 Song2014 Object /// RS1 to RS2014 Mapping Method /// </summary> /// <param name="rsSong"></param> /// <param name="srcPath"></param> /// <returns>Song2014</returns> public Song2014 SongToSong2014(Song rsSong) { // Song to Song2014 Mapping Song2014 rsSong2014 = new Song2014(); // song info parsed and loaded later from // RS1 song.manifest.json file by RS1LoadFromFolder rsSong2014.Version = "7"; rsSong2014.Title = rsSong.Title; rsSong2014.Arrangement = rsSong.Arrangement; rsSong2014.Part = rsSong.Part; rsSong2014.Offset = rsSong.Offset; rsSong2014.CentOffset = "0"; rsSong2014.SongLength = rsSong.SongLength; rsSong2014.LastConversionDateTime = DateTime.Now.ToString("MM-dd-yy HH:mm"); rsSong2014.StartBeat = rsSong.Ebeats[0].Time; // if RS1 CDLC Song XML originates from EOF it may // already contain AverageTempo otherwise it gets calculated rsSong2014.AverageTempo = rsSong.AverageTempo == 0 ? AverageBPM(rsSong) : rsSong.AverageTempo; // tuning parsed from RS1 song.manifest.json file by RS1LoadFromFolder rsSong2014.Tuning = rsSong.Tuning == null ? new TuningStrings { String0 = 0, String1 = 0, String2 = 0, String3 = 0, String4 = 0, String5 = 0 } : rsSong.Tuning; rsSong2014.Capo = 0; rsSong2014.ArtistName = rsSong.ArtistName; rsSong2014.AlbumName = rsSong.AlbumName; rsSong2014.AlbumYear = rsSong.AlbumYear; rsSong2014.CrowdSpeed = "1"; // initialize arrangement properties rsSong2014.ArrangementProperties = new SongArrangementProperties2014 { Represent = 1, StandardTuning = 1, NonStandardChords = 0, BarreChords = 0, PowerChords = 0, DropDPower = 0, OpenChords = 0, FingerPicking = 0, PickDirection = 0, DoubleStops = 0, PalmMutes = 0, Harmonics = 0, PinchHarmonics = 0, Hopo = 0, Tremolo = 0, Slides = 0, UnpitchedSlides = 0, Bends = 0, Tapping = 0, Vibrato = 0, FretHandMutes = 0, SlapPop = 0, TwoFingerPicking = 0, FifthsAndOctaves = 0, Syncopation = 0, BassPick = 0, Sustain = 0, BonusArr = 0, RouteMask = 0, PathLead = 0, PathRhythm = 0, PathBass = 0 }; // initial SWAG based on RS1 arrangement element rsSong2014.ArrangementProperties.RouteMask = rsSong.Arrangement.ToLower().Contains("lead") ? 1 : (rsSong.Arrangement.ToLower().Contains("rhythm") ? 2 : (rsSong.Arrangement.ToLower().Contains("combo") ? 2 // may not always be true : (rsSong.Arrangement.ToLower().Contains("bass") ? 4 : 1))); // but ok for now rsSong2014.ArrangementProperties.PathLead = rsSong2014.ArrangementProperties.RouteMask == 1 ? 1 : 0; rsSong2014.ArrangementProperties.PathRhythm = rsSong2014.ArrangementProperties.RouteMask == 1 ? 1 : 0; rsSong2014.ArrangementProperties.PathBass = rsSong2014.ArrangementProperties.RouteMask == 1 ? 1 : 0; // set tone defaults used to produce RS2014 CDLC rsSong2014.ToneBase = "Default"; rsSong2014.ToneA = ""; rsSong2014.ToneB = ""; rsSong2014.ToneC = ""; rsSong2014.ToneD = ""; // these elements have direct mappings rsSong2014.Phrases = rsSong.Phrases; rsSong2014.FretHandMuteTemplates = rsSong.FretHandMuteTemplates; rsSong2014.Ebeats = rsSong.Ebeats; rsSong2014.Sections = rsSong.Sections; rsSong2014.Events = rsSong.Events; // these prevent in game hanging rsSong2014.LinkedDiffs = new SongLinkedDiff[0]; rsSong2014.PhraseProperties = new SongPhraseProperty[0]; // these elements have no direct mapping, processing order is important rsSong2014 = ConvertChordTemplates(rsSong, rsSong2014); rsSong2014 = ConvertLevels(rsSong, rsSong2014); rsSong2014 = ConvertPhraseIterations(rsSong, rsSong2014); // these prevent in game hanging rsSong2014.Tones = new SongTone2014[0]; rsSong2014.NewLinkedDiff = new SongNewLinkedDiff[0]; // tested ... not the source of in game hangs // rsSong2014.TranscriptionTrack = TranscriptionTrack2014.GetDefault(); // tested ... confirmed this is a source of in game hangs // check alignment of Sections time with Ebeats first beat of measure time // TODO: use LINQ float fbomTime = 0; float nfbomTime = 0; foreach (var section in rsSong2014.Sections) { foreach (var ebeat in rsSong2014.Ebeats) { // save Ebeats first beat of measure time if (ebeat.Measure != -1) fbomTime = ebeat.Time; else nfbomTime = ebeat.Time; if (section.Name.ToLower().Contains("noguitar") && Math.Abs(ebeat.Time - section.StartTime) < 0.001) { // CRITICAL - fix Section noguitar time (matches EOF output) if (ebeat.Measure != -1) { section.StartTime = nfbomTime; Console.WriteLine("Applied fix to RS1->RS2 Section StartTime for: " + section.Name); } break; } // found a valid Section time if (ebeat.Measure != -1 && Math.Abs(ebeat.Time - section.StartTime) < 0.001) break; // fix invalid Section time if (ebeat.Measure == -1 && ebeat.Time > section.StartTime) { section.StartTime = fbomTime; Console.WriteLine("Applied fix to RS1->RS2 Section StartTime for: " + section.Name); break; } } } return rsSong2014; }