コード例 #1
0
        private InstrumentTuning UpdateTuning(InstrumentTuning tuning, bool guitar)
        {
            if (string.IsNullOrEmpty(tuning.Name))
            {
                // Return default guitar/bass tuning
                return(guitar ? InstrumentTuning.Guitar_EStandard : InstrumentTuning.Bass_EStandard);
            }

            if (guitar)
            {
                switch (tuning.Name.Value.ToLower())
                {
                default:
                case "e standard":
                    return(InstrumentTuning.Guitar_EStandard);

                case "drop d":
                    return(InstrumentTuning.Guitar_DropD);

                case "e♭ standard":
                case "eb standard":
                    return(InstrumentTuning.Guitar_EbStandard);
                }
            }
            else // Bass
            {
                switch (tuning.Name.Value.ToLower())
                {
                default:
                case "e standard":
                    return(InstrumentTuning.Bass_EStandard);
                }
            }
        }
コード例 #2
0
        public static int GetMidiNote(this InstrumentTuning tuning, ArrangementType arrangementType, int stringNumber, int fret)
        {
            if (fret == -1)
            {
                return(-1);
            }
            var strNote = StandardMidiNotes[stringNumber] + tuning.GetOffsets()[stringNumber];

            strNote -= arrangementType == ArrangementType.Bass ? 12 : 0;

            return(strNote + fret);
        }
コード例 #3
0
        // COMPLETE
        private static void WriteSngFile(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);
                }
        }
コード例 #4
0
        public static IList <Int16> GetOffsets(this InstrumentTuning tuning)
        {
            switch (tuning)
            {
            case InstrumentTuning.Standard:
                return(StandardOffsets);

            case InstrumentTuning.DropD:
                return(DropDOffsets);

            case InstrumentTuning.EFlat:
                return(EFlatOffsets);

            case InstrumentTuning.OpenG:
                return(OpenGOffsets);

            default:
                throw new InvalidOperationException("Unexpected tuning value");
            }
        }
コード例 #5
0
ファイル: ChartImport.cs プロジェクト: PikminGuts92/BFForever
        public List <ZObject> ExportZObjects(HKey directory, InstrumentTuning leadGtr, InstrumentTuning rhythmGtr, InstrumentTuning bass)
        {
            List <ZObject> objects = new List <ZObject>();

            objects.AddRange(CreateInstrument(directory, "master", "", InstrumentTuning.Guitar_EStandard));
            objects.AddRange(CreateInstrument(directory, "vox", "", InstrumentTuning.Guitar_EStandard));

            // Guitar tracks
            objects.AddRange(CreateInstrument(directory, "guitar", "jam", rhythmGtr));
            objects.AddRange(CreateInstrument(directory, "guitar", "nov", rhythmGtr));
            objects.AddRange(CreateInstrument(directory, "guitar", "beg", rhythmGtr));
            objects.AddRange(CreateInstrument(directory, "guitar", "int", rhythmGtr));
            objects.AddRange(CreateInstrument(directory, "guitar", "rhy", rhythmGtr));
            objects.AddRange(CreateInstrument(directory, "guitar", "adv", leadGtr));

            // Bass tracks
            objects.AddRange(CreateInstrument(directory, "bass", "jam", bass));
            objects.AddRange(CreateInstrument(directory, "bass", "nov", bass));
            objects.AddRange(CreateInstrument(directory, "bass", "beg", bass));
            objects.AddRange(CreateInstrument(directory, "bass", "int", bass));
            objects.AddRange(CreateInstrument(directory, "bass", "adv", bass));

            return(objects);
        }
コード例 #6
0
        // COMPLETE
        private static void WriteRocksmithSngChordTemplates(EndianBinaryWriter w, SongChordTemplate[] chordTemplates, InstrumentTuning tuning, ArrangementType arrangementType)
        {
            // output header
            if (chordTemplates == null || chordTemplates.Length == 0)
            {
                w.Write(new byte[4]); // empty header
                return;
            }

            // output header count
            w.Write(chordTemplates.Length);

            // output chord templates
            foreach (SongChordTemplate chordTemplate in chordTemplates)
            {
                // fret numbers
                w.Write(chordTemplate.Fret0);
                w.Write(chordTemplate.Fret1);
                w.Write(chordTemplate.Fret2);
                w.Write(chordTemplate.Fret3);
                w.Write(chordTemplate.Fret4);
                w.Write(chordTemplate.Fret5);

                // finger positions
                w.Write(chordTemplate.Finger0);
                w.Write(chordTemplate.Finger1);
                w.Write(chordTemplate.Finger2);
                w.Write(chordTemplate.Finger3);
                w.Write(chordTemplate.Finger4);
                w.Write(chordTemplate.Finger5);

                // note values
                w.Write(tuning.GetMidiNote(arrangementType, 0, chordTemplate.Fret0));
                w.Write(tuning.GetMidiNote(arrangementType, 1, chordTemplate.Fret1));
                w.Write(tuning.GetMidiNote(arrangementType, 2, chordTemplate.Fret2));
                w.Write(tuning.GetMidiNote(arrangementType, 3, chordTemplate.Fret3));
                w.Write(tuning.GetMidiNote(arrangementType, 4, chordTemplate.Fret4));
                w.Write(tuning.GetMidiNote(arrangementType, 5, chordTemplate.Fret5));

                // chord name
                string name = chordTemplate.ChordName;
                if (name.Length > 32)
                {
                    name = name.Substring(0, 32);
                }
                foreach (char c in name)
                {
                    w.Write(Convert.ToByte(c));
                }
                // padding after name
                w.Write(new byte[32 - name.Length]);
            }
        }
コード例 #7
0
        // 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.Count(note => note.Time >= iteration.StartTime && note.Time < iteration.EndTime);
                }
                if (level.Chords != null)
                {
                    totalNotes += level.Chords.Count(chord => chord.Time >= iteration.StartTime && chord.Time < iteration.EndTime);
                }
            }
            // 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.ArtistName) ? "DUMMY" : s.ArtistName;

            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 phrase 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
        }
コード例 #8
0
        // 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
        }
コード例 #9
0
        // 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);
            }
        }
コード例 #10
0
        // COMPLETE
        private static void WriteRocksmithSngChordTemplates(EndianBinaryWriter w, SongChordTemplate[] chordTemplates, InstrumentTuning tuning, ArrangementType arrangementType)
        {
            // output header
            if (chordTemplates == null || chordTemplates.Length == 0)
            {
                w.Write(new byte[4]); // empty header
                return;
            }

            // output header count
            w.Write(chordTemplates.Length);

            // output chord templates
            foreach (SongChordTemplate chordTemplate in chordTemplates)
            {
                // fret numbers
                w.Write(chordTemplate.Fret0);
                w.Write(chordTemplate.Fret1);
                w.Write(chordTemplate.Fret2);
                w.Write(chordTemplate.Fret3);
                w.Write(chordTemplate.Fret4);
                w.Write(chordTemplate.Fret5);

                // finger positions
                w.Write(chordTemplate.Finger0);
                w.Write(chordTemplate.Finger1);
                w.Write(chordTemplate.Finger2);
                w.Write(chordTemplate.Finger3);
                w.Write(chordTemplate.Finger4);
                w.Write(chordTemplate.Finger5);

                // note values
                w.Write(tuning.GetMidiNote(arrangementType, 0, chordTemplate.Fret0));
                w.Write(tuning.GetMidiNote(arrangementType, 1, chordTemplate.Fret1));
                w.Write(tuning.GetMidiNote(arrangementType, 2, chordTemplate.Fret2));
                w.Write(tuning.GetMidiNote(arrangementType, 3, chordTemplate.Fret3));
                w.Write(tuning.GetMidiNote(arrangementType, 4, chordTemplate.Fret4));
                w.Write(tuning.GetMidiNote(arrangementType, 5, chordTemplate.Fret5));

                // chord name
                string name = chordTemplate.ChordName;
                if (name.Length > 32)
                {
                    name = name.Substring(0, 32);
                }
                foreach (char c in name)
                {
                    w.Write(Convert.ToByte(c));
                }
                // padding after name
                w.Write(new byte[32 - name.Length]);
            }
        }
コード例 #11
0
        public static void Write(string inputFile, string outputFile, ArrangementType arrangementType, GamePlatform platform, InstrumentTuning tuning)
        {
            using (var reader = new StreamReader(inputFile))
            {
                var bitConverter = platform == GamePlatform.Pc
                    ? (EndianBitConverter)EndianBitConverter.Little
                    : (EndianBitConverter)EndianBitConverter.Big;

                if (arrangementType == ArrangementType.Vocal)
                {
                    var serializer = new XmlSerializer(typeof(Vocals));
                    var vocals = (Vocals)serializer.Deserialize(reader);
                    WriteRocksmithVocalsFile(vocals, outputFile, bitConverter);
                }
                else
                {
                    var serializer = new XmlSerializer(typeof(Song));
                    var song = (Song)serializer.Deserialize(reader);
                    WriteRocksmithSngFile(song, tuning, arrangementType, outputFile, bitConverter);
                }
            }
        }
コード例 #12
0
        private void AddToCatalog(Song song, InstrumentTuning leadGtr, InstrumentTuning rhythmGtr, InstrumentTuning bass)
        {
            // Add song to catalog2 entries
            Catalog2 catalog = _packageManager["catalog2"] as Catalog2;

            Catalog2Entry entry = new Catalog2Entry()
            {
                Identifier = song.DirectoryPath + ".MediaEntry2",
                SongType   = 1,

                Title       = song.Title,
                Artist      = song.Artist,
                Album       = song.Album,
                Description = song.Description,
                LegendTag   = song.LegendTag,

                SongLength      = song.SongLength,
                GuitarIntensity = song.GuitarIntensity,
                BassIntensity   = song.BassIntensity,
                VoxIntensity    = song.VoxIntensity,

                EraTag = song.EraTag,
                Year   = song.Year,

                LeadGuitarTuning   = leadGtr,
                RhythmGuitarTuning = rhythmGtr,
                BassTuning         = bass,

                Labels      = song.Labels,
                SongPath    = song.FilePath,
                TexturePath = song.TexturePath,
                PreviewPath = song.PreviewPath,

                MetadataTags = song.MetadataTags,
                GenreTags    = song.GenreTags
            };

            // Removes previous entry and adds to pending change
            catalog.Entries.RemoveAll(x => x.Identifier == entry.Identifier);
            catalog.Entries.Add(entry);

            // Sorts alphabetically and ensures "ShredUs" entries are first
            catalog.Entries.Sort((x, y) =>
            {
                string a = x.Identifier, b = y.Identifier;
                if (a.StartsWith("ShredUs", StringComparison.CurrentCultureIgnoreCase) && b.StartsWith("ShredUs", StringComparison.CurrentCultureIgnoreCase))
                {
                    return(string.Compare(a, b));
                }
                else if (a.StartsWith("ShredUs", StringComparison.CurrentCultureIgnoreCase))
                {
                    return(-1);
                }
                else if (b.StartsWith("ShredUs", StringComparison.CurrentCultureIgnoreCase))
                {
                    return(1);
                }
                else
                {
                    return(string.Compare(a, b));
                }
            });

            _packageManager.AddZObjectAsPending(catalog);
        }
コード例 #13
0
ファイル: ChartImport.cs プロジェクト: PikminGuts92/BFForever
        private List <ZObject> CreateInstrument(HKey directoryPath, string instrumentType, string difficulty, InstrumentTuning tuning)
        {
            // Sets directory name
            if (instrumentType == "guitar" || instrumentType == "bass")
            {
                directoryPath += (instrumentType == "guitar" ? ".gtr_" : ".bss_") + difficulty;
            }
            else
            {
                directoryPath += "." + instrumentType;
            }

            // Creates instrument
            Instrument instrument = new Instrument(directoryPath + ".instrument", directoryPath);

            instrument.InstrumentType = instrumentType == "vox" ? "vocals" : instrumentType;

            // Sets difficulty + tuning
            if (instrumentType == "vox" || instrumentType == "master")
            {
                instrument.Difficulty = "";
                instrument.Tuning     = InstrumentTuning.Guitar_EStandard;
            }
            else
            {
                instrument.Difficulty = difficulty;
                instrument.Tuning     = tuning;
            }

            // Creates tracks for instrument
            List <ZObject> objects;

            switch (instrumentType.ToLower())
            {
            case "bass":
            case "guitar":
                objects = GetGuitarObjects(directoryPath);
                break;

            case "master":
                // event, measure, section, tempo, timesignature
                objects = GetMasterObjects(directoryPath);
                break;

            case "vox":
                // vox, voxpushphrase, voxspread
                objects = GetVoxObjects(directoryPath);
                break;

            default:
                // Shouldn't really return anything
                return(new List <ZObject>());
            }

            objects.ForEach(x => instrument.TrackPaths.Add(x.FilePath));
            objects.Add(instrument);
            return(objects);
        }