Пример #1
0
        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 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;
        }
Пример #5
0
 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);
            }
        }
Пример #23
0
        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
        }
Пример #25
0
        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();
        }
 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;
 }
        // 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;
        }