Beispiel #1
0
        public AudioFormat DecodeFormat(FormatData data)
        {
            Stream stream = GetFormatStream(data);

            if (stream == null)
            {
                return(NeversoftMetadata.GetAudioFormat(data) ?? HarmonixMetadata.GetAudioFormat(data.Song));
            }
            AudioFormat format = AudioFormat.Create(stream);

            data.CloseStream(stream);
            return(format);
        }
        public override PlatformData Create(string path, Game game, ProgressIndicator progress)
        {
            PlatformData data = new PlatformData(this, game);

            DirectoryNode dir = data.GetDirectoryStructure(path);

            data.Game = Platform.DetermineGame(data);

            FileNode qbpak = dir.Navigate("pak/qb.pak.ngc") as FileNode;

            if (qbpak == null)
            {
                Exceptions.Error("Couldn't find qb.pak.ngc on Guitar Hero 3 Wii disc.");
            }

            try {
                Pak          qb           = new Pak(new EndianReader(qbpak.Data, Endianness.BigEndian));
                FileNode     songlistfile = qb.Root.Find("songlist.qb.ngc", SearchOption.AllDirectories) as FileNode;
                FileNode     albumfile    = dir.Navigate("pak/album_covers/album_covers.pak.ngc", false, true) as FileNode;
                QbFile       songlist     = new QbFile(songlistfile.Data, PakFormat);
                QbItemStruct list         = songlist.FindItem(QbKey.Create(NeversoftMetadata.SonglistKeys[0]), true) as QbItemStruct;

                data.Session["rootdir"] = dir;
                data.Session["rootqb"]  = qb;

                if (albumfile != null)
                {
                    data.Session["albumpak"] = new Pak(new EndianReader(albumfile.Data, Endianness.BigEndian));
                }

                var items = list.Items;
                progress.NewTask(items.Count);
                foreach (QbItemStruct item in items)
                {
                    SongData song = NeversoftMetadata.GetSongData(data, item);

                    try {
                        AddSong(data, song, progress);
                    } catch (Exception exception) {
                        Exceptions.Warning(exception, "Unable to properly parse " + song.Name);
                    }

                    progress.Progress();
                }
                progress.EndTask();
            } catch (Exception exception) {
                Exceptions.Error(exception, "An error occurred while parsing the Guitar Hero 3 Wii disc.");
            }

            return(data);
        }
        public override bool AddSong(PlatformData data, SongData song, ProgressIndicator progress)
        {
            int index = int.Parse(song.ID.Substring(3));
            //song.ID = "dlc" + ImportMap.GetShortName(song.Name);

            FormatData formatdata = new TemporaryFormatData(song, data);

            NeversoftMetadata.SaveSongItem(formatdata);

            DirectoryNode dir = data.Session["rootdir"] as DirectoryNode;

            FileNode binfile = dir.Navigate(Util.Pad(index.ToString(), 3) + ".bin") as FileNode;

            if (binfile == null)
            {
                return(false);
            }
            DlcBin bin = new DlcBin(binfile.Data);
            U8     u8  = new U8(bin.Data);

            FileNode chartpak = u8.Root.Find(song.ID + "_song.pak.ngc", SearchOption.AllDirectories) as FileNode;
            FileNode textpak  = u8.Root.Find(song.ID + "_text.pak.ngc", SearchOption.AllDirectories) as FileNode;

            FileNode audiofile = u8.Root.Find(song.ID + ".bik", SearchOption.AllDirectories) as FileNode;

            if (chartpak == null || textpak == null || audiofile == null)
            {
                return(false);
            }

            ChartFormatGH4.Instance.Create(formatdata, new Stream[] { chartpak.Data, textpak.Data }, PlatformGH5WiiDisc.ImportExpertPlus);

            if (audiofile != null)
            {
                AudioFormatBink.Instance.Create(formatdata, audiofile.Data, null, null);
            }

            data.AddSong(formatdata);

            chartpak.Data.Close();

            return(true);
        }
Beispiel #4
0
        public static void Initialise()
        {
            Formats = new List <IFormat>();

            //PlatformDJHWiiDisc.Initialise();
            PlatformFretsOnFire.Initialise();
            PlatformGH2PS2Disc.Initialise();
            PlatformGH3WiiDisc.Initialise();
            PlatformGH4WiiDLC.Initialise();
            PlatformGH5WiiDisc.Initialise();
            //PlatformGH5WiiDLC.Initialise();
            PlatformLocalStorage.Initialise();
            PlatformRawkFile.Initialise();
            //PlatformRB2360Disc.Initialise();
            //PlatformRB2360DLC.Initialise();
            PlatformRB2360RBN.Initialise();
            PlatformRB2WiiCustomDLC.Initialise();
            PlatformRB2WiiDisc.Initialise();
            //PlatformRB2WiiDLC.Initialise();

            //ChartFormatChart.Initialise();
            //ChartFormatFsgMub.Initialise();
            ChartFormatGH1.Initialise();
            ChartFormatGH2.Initialise();
            ChartFormatGH3.Initialise();
            ChartFormatGH4.Initialise();
            ChartFormatGH5.Initialise();
            ChartFormatRB.Initialise();

            AudioFormatBeatlesBink.Initialise();
            AudioFormatBink.Initialise();
            AudioFormatFFmpeg.Initialise();
            AudioFormatGH3WiiFSB.Initialise();
            AudioFormatMogg.Initialise();
            //AudioFormatMp3.Initialise();
            AudioFormatOgg.Initialise();
            AudioFormatRB2Bink.Initialise();
            AudioFormatRB2Mogg.Initialise();
            AudioFormatVGS.Initialise();

            NeversoftMetadata.Initialise();
        }
Beispiel #5
0
        public override AudioFormat DecodeAudio(FormatData data, ProgressIndicator progress)
        {
            AudioFormat format = DecodeFormat(data);
            Stream      audio  = data.GetStream(this, AudioName);
            uint        magic  = new EndianReader(audio, Endianness.BigEndian).ReadUInt32();

            if (magic != 0x5241574b && (magic & 0xFFFFFF00) != 0x42494b00)
            {
                throw new FormatException();                 // Must start with "RAWK" or "BIK", this is to prevent encrypted biks from being decoded
            }
            audio.Position = 0;
            Stream preview = null;

            format.Decoder = new RawkAudio.Decoder(audio, RawkAudio.Decoder.AudioFormat.BinkAudio);
            if (data.HasStream(this, PreviewName))
            {
                preview          = data.GetStream(this, PreviewName);
                magic            = new EndianReader(preview, Endianness.BigEndian).ReadUInt32();
                preview.Position = 0;
                if (magic != 0x5241574b && (magic & 0xFFFFFF00) != 0x42494b00)
                {
                    throw new FormatException();
                }
                IDecoder     decoder = new RawkAudio.Decoder(preview, RawkAudio.Decoder.AudioFormat.BinkAudio);
                MultiDecoder multi   = new MultiDecoder(RawkAudio.Decoder.BufferSize);
                multi.AddDecoder(format.Decoder);
                multi.AddDecoder(decoder);
                format.Decoder = multi;
            }

            format.SetDisposeStreams(data, new Stream[] { audio, preview });

            Game game = data.Song.Game;

            if (NeversoftMetadata.IsGuitarHero4(game) || NeversoftMetadata.IsGuitarHero5(game))
            {
                format.Decoder = new AmplifyDecoder(format.Decoder, 1.30f);
            }

            return(format);
        }
Beispiel #6
0
        public override bool AddSong(PlatformData data, SongData song, ProgressIndicator progress)
        {
            FormatData formatdata = new TemporaryFormatData(song, data);

            NeversoftMetadata.SaveSongItem(formatdata);

            DirectoryNode dir = data.Session["rootdir"] as DirectoryNode;

            FileNode chartpak = dir.Navigate("songs/" + song.ID + ".pak.ngc", false, true) as FileNode;

            if (chartpak == null)
            {
                return(false);
            }

            if (data.Game == Game.GuitarHero5 || data.Game == Game.BandHero)
            {
                ChartFormatGH5.Instance.Create(formatdata, new Stream[] { chartpak.Data }, ImportExpertPlus);
            }
            else
            {
                ChartFormatGH4.Instance.Create(formatdata, new Stream[] { chartpak.Data }, ImportExpertPlus);
            }

            FileNode audiofile   = dir.Navigate("music/" + song.ID + ".bik", false, true) as FileNode;
            FileNode previewfile = dir.Navigate("music/" + song.ID + "_preview.bik", false, true) as FileNode;

            if (audiofile != null)
            {
                AudioFormatBink.Instance.Create(formatdata, audiofile.Data, previewfile == null ? null : previewfile.Data, null);
            }

            data.AddSong(formatdata);

            chartpak.Data.Close();

            return(true);
        }
Beispiel #7
0
        public override PlatformData Create(string path, Game game, ProgressIndicator progress)
        {
            PlatformData data = new PlatformData(this, game);

            DirectoryNode dir = data.GetDirectoryStructure(path);

            data.Game = Platform.DetermineGame(data);

            try {
                FileNode qbpak = dir.Navigate("pak/qb.pak.ngc") as FileNode;
                if (qbpak == null)
                {
                    throw new FormatException("Couldn't find qb.pak on Guitar Hero Wii disc.");
                }

                FileNode qspak = dir.Navigate("pak/qs.pak.ngc") as FileNode;
                if (qspak == null)
                {
                    throw new FormatException("Couldn't find qs.pak on Guitar Hero Wii disc.");
                }

                Pak qs = new Pak(new EndianReader(qspak.Data, Endianness.BigEndian));

                StringList strings = new StringList();
                foreach (Pak.Node node in qs.Nodes)
                {
                    strings.ParseFromStream(node.Data);
                }

                Pak      qb           = new Pak(new EndianReader(qbpak.Data, Endianness.BigEndian));
                FileNode songlistfile = qb.FindFile(@"scripts\guitar\songlist.qb.ngc");
                if (songlistfile == null)
                {
                    songlistfile = qb.FindFile(@"scripts\guitar\songlist.qb");
                }

                if (songlistfile == null)
                {
                    throw new FormatException("Couldn't find the songlist on the Guitar Hero Wii disc pak.");
                }
                QbFile songlist = new QbFile(songlistfile.Data, PakFormat);

                data.Session["rootdir"] = dir;

                List <QbKey> listkeys = new List <QbKey>();
                foreach (uint songlistkey in NeversoftMetadata.SonglistKeys)
                {
                    QbKey        key  = QbKey.Create(songlistkey);
                    QbItemStruct list = songlist.FindItem(key, true) as QbItemStruct;
                    if (list != null && list.Items.Count > 0)
                    {
                        listkeys.Add(key);
                    }
                }

                progress.NewTask(listkeys.Count);
                List <string> songsadded = new List <string>();
                foreach (QbKey songlistkey in listkeys)
                {
                    QbItemStruct list = songlist.FindItem(songlistkey, true) as QbItemStruct;

                    progress.NewTask(list.Items.Count);

                    foreach (QbItemArray item in list.Items.OfType <QbItemArray>())
                    {
                        item.Items[0].ItemQbKey = item.ItemQbKey;
                        SongData song = NeversoftMetadata.GetSongData(data, item.Items[0] as QbItemStruct, strings);

                        progress.Progress();

                        if (songsadded.Contains(song.ID))
                        {
                            continue;
                        }

                        try {
                            if (AddSong(data, song, progress))
                            {
                                songsadded.Add(song.ID);
                            }
                        } catch (Exception exception) {
                            Exceptions.Warning(exception, "Unable to properly parse " + song.Name);
                        }
                    }

                    progress.EndTask();
                    progress.Progress();
                }
                progress.EndTask();

                qbpak.Data.Close();
                qspak.Data.Close();
            } catch (Exception exception) {
                Exceptions.Error(exception, "An error occurred while parsing the Guitar Hero Wii disc.");
            }

            return(data);
        }
        public override PlatformData Create(string path, Game game, ProgressIndicator progress)
        {
            PlatformData data = new PlatformData(this, game);

            DirectoryNode dir = data.GetDirectoryStructure(path);

            FileNode binfile = dir.Navigate("001.bin") as FileNode;

            if (binfile == null)
            {
                Exceptions.Error("Unable to open Guitar Hero World Tour DLC because 001.bin is missing.");
            }

            data.Session["rootdir"] = dir;

            try {
                DlcBin   bin          = new DlcBin(binfile.Data);
                U8       u8           = new U8(bin.Data);
                FileNode listfile     = u8.Root.Navigate("DLC1.pak.ngc") as FileNode;
                Pak      qb           = new Pak(new EndianReader(listfile.Data, Endianness.BigEndian));
                FileNode songlistfile = qb.Root.Find("catalog_info.qb.ngc", SearchOption.AllDirectories) as FileNode;
                QbFile   songlist     = new QbFile(songlistfile.Data, PakFormat);

                StringList strings = new StringList();
                foreach (Pak.Node node in qb.Nodes)
                {
                    if (!node.Filename.HasValue())
                    {
                        strings.ParseFromStream(node.Data);
                    }
                }

                List <QbKey> listkeys = new List <QbKey>();
                foreach (uint songlistkey in NeversoftMetadata.SonglistKeys)
                {
                    QbKey        key  = QbKey.Create(songlistkey);
                    QbItemStruct list = songlist.FindItem(key, true) as QbItemStruct;
                    if (list != null && list.Items.Count > 0)
                    {
                        listkeys.Add(key);
                    }
                }

                Stream       str    = new FileStream(@"C:\ghwt.xml", FileMode.Create);
                StreamWriter writer = new StreamWriter(str);

                progress.NewTask(listkeys.Count);
                foreach (QbKey songlistkey in listkeys)
                {
                    QbItemStruct list = songlist.FindItem(songlistkey, true) as QbItemStruct;

                    progress.NewTask(list.Items.Count);

                    foreach (QbItemArray item in list.Items.OfType <QbItemArray>())
                    {
                        item.Items[0].ItemQbKey = item.ItemQbKey;
                        SongData song = NeversoftMetadata.GetSongData(data, item.Items[0] as QbItemStruct, strings);

                        writer.WriteLine("\t<song id=\"" + song.ID + "\">");
                        writer.WriteLine("\t\t<pack>Guitar Hero World Tour DLC</pack>");
                        writer.WriteLine("\t\t<nameprefix>[GHWT DLC]</nameprefix>");
                        writer.WriteLine("\t\t<name>" + song.Name + "</name>");
                        writer.WriteLine("\t\t<artist>" + song.Artist + "</artist>");
                        writer.WriteLine("\t\t<album>" + song.Album + "</album>");
                        writer.WriteLine("\t\t<genre>" + song.Genre + "</genre>");
                        writer.WriteLine("\t\t<track>" + song.AlbumTrack.ToString() + "</track>");
                        writer.WriteLine("\t\t<difficulty instrument=\"band\" rank=\"1\" />");
                        writer.WriteLine("\t\t<difficulty instrument=\"guitar\" rank=\"1\" />");
                        writer.WriteLine("\t\t<difficulty instrument=\"bass\" rank=\"1\" />");
                        writer.WriteLine("\t\t<difficulty instrument=\"drum\" rank=\"1\" />");
                        writer.WriteLine("\t\t<difficulty instrument=\"vocals\" rank=\"1\" />");
                        writer.WriteLine("\t</song>");

                        try {
                            AddSong(data, song, progress);
                        } catch (Exception exception) {
                            Exceptions.Warning(exception, "Unable to properly parse " + song.Name);
                        }
                        progress.Progress();
                    }

                    progress.EndTask();
                    progress.Progress();
                }
                progress.EndTask();
                writer.Close();

                binfile.Data.Close();
            } catch (Exception exception) {
                Exceptions.Error(exception, "An error occurred while parsing the Guitar Hero World Tour DLC list.");
            }

            return(data);
        }
Beispiel #9
0
        public override ChartFormat DecodeChart(FormatData data, ProgressIndicator progress)
        {
            if (!data.HasStream(this, ChartName) || !data.HasStream(this, SectionsName))
            {
                throw new FormatException();
            }

            progress.NewTask(6 + 8);

            Stream chartstream   = data.GetStream(this, ChartName);
            Stream sectionstream = data.GetStream(this, SectionsName);

            PakFormat format     = NeversoftMetadata.GetSongItemType(data.Song);
            SongData  song       = NeversoftMetadata.GetSongData(data.PlatformData, NeversoftMetadata.GetSongItem(data));
            Pak       chartpak   = new Pak(new EndianReader(chartstream, Endianness.BigEndian));     // TODO: Endianness based on format?
            FileNode  chartfile  = chartpak.Root.Find(song.ID + ".mid.qb.ngc", SearchOption.AllDirectories, true) as FileNode;
            QbFile    qbsections = new QbFile(sectionstream, format);
            QbFile    qbchart    = new QbFile(chartfile.Data, format);

            NoteChart chart = new NoteChart();

            chart.PartGuitar = new NoteChart.Guitar(chart);
            chart.PartBass   = new NoteChart.Bass(chart);
            chart.Events     = new NoteChart.EventsTrack(chart);
            chart.Venue      = new NoteChart.VenueTrack(chart);
            chart.Beat       = new NoteChart.BeatTrack(chart);

            progress.Progress();

            DecodeChartFretbars(song, qbchart, chart);

            progress.Progress();

            DecodeChartMarkers(song, qbsections, qbchart, chart);

            progress.Progress();

            for (NoteChart.TrackType track = NoteChart.TrackType.Guitar; track <= NoteChart.TrackType.Bass; track++)
            {
                for (NoteChart.Difficulty difficulty = NoteChart.Difficulty.Easy; difficulty <= NoteChart.Difficulty.Expert; difficulty++)
                {
                    DecodeChartNotes(data, song, qbchart, chart, track, difficulty, data.Song.Data.GetValue <bool>("GH3ChartCoop"));
                    progress.Progress();
                }
            }

            progress.Progress();

            DecodeChartDrums(song, qbchart, chart);

            progress.Progress();

            DecodeChartVenue(song, qbchart, chart);

            ImportMap.ImportChart(data.Song, chart);

            progress.Progress();

            data.CloseStream(chartstream);
            data.CloseStream(sectionstream);

            progress.EndTask();

            return(new ChartFormat(chart));
        }
Beispiel #10
0
 public static void Initialise()
 {
     Instance = new NeversoftMetadata();
     Platform.AddFormat(Instance);
 }
Beispiel #11
0
        public static AudioFormat GetAudioFormat(FormatData data)
        {
            SongData    song        = data.Song;
            AudioFormat audioformat = new AudioFormat();

            QbItemStruct item = GetSongItem(data);

            if (item == null)
            {
                return(null);
            }
            float bandvolume   = 0;
            float guitarvolume = 0;
            float bassvolume   = 0;
            float drumvolume   = 0;

            QbItemFloat subitem = item.FindItem(QbKey.Create(0xD8F335CF), false) as QbItemFloat;             // GH3: band_playback_volume

            if (subitem != null)
            {
                bandvolume = (subitem as QbItemFloat).Values[0];
                bassvolume = bandvolume;
            }
            subitem = item.FindItem(QbKey.Create(0xA449CAD3), false) as QbItemFloat;             // GH3: guitar_playback_volume
            if (subitem != null)
            {
                guitarvolume = (subitem as QbItemFloat).Values[0];
            }
            subitem = item.FindItem(QbKey.Create(0x46507438), false) as QbItemFloat;             // GH4: overall_song_volume
            if (subitem != null)
            {
                bandvolume   = (subitem as QbItemFloat).Values[0];
                guitarvolume = bandvolume;
                bassvolume   = bandvolume;
                drumvolume   = bandvolume;
            }

            // GH4 engine games that came out after GHWT use a different drum audio scheme; the GH5 engine uses the same as GHWT
            bool gh4v2 = NeversoftMetadata.IsGuitarHero4(song.Game) && song.Game != Game.GuitarHeroWorldTour;
            // GHVH is the only BIK-based GH game with stereo bass
            bool ghvh = song.Game == Game.GuitarHeroVanHalen;

            if (gh4v2)
            {
                // Kick
                audioformat.Mappings.Add(new AudioFormat.Mapping(drumvolume, -1, Instrument.Drums));
                audioformat.Mappings.Add(new AudioFormat.Mapping(drumvolume, 1, Instrument.Drums));
                // Snare
                audioformat.Mappings.Add(new AudioFormat.Mapping(drumvolume, -1, Instrument.Drums));
                audioformat.Mappings.Add(new AudioFormat.Mapping(drumvolume, 1, Instrument.Drums));
            }
            else
            {
                // Kick
                audioformat.Mappings.Add(new AudioFormat.Mapping(drumvolume, 0, Instrument.Drums));
                // Snare
                audioformat.Mappings.Add(new AudioFormat.Mapping(drumvolume, 0, Instrument.Drums));
            }
            // Overhead
            audioformat.Mappings.Add(new AudioFormat.Mapping(drumvolume, -1, Instrument.Drums));
            audioformat.Mappings.Add(new AudioFormat.Mapping(drumvolume, 1, Instrument.Drums));
            // Guitar
            audioformat.Mappings.Add(new AudioFormat.Mapping(guitarvolume, -1, Instrument.Guitar));
            audioformat.Mappings.Add(new AudioFormat.Mapping(guitarvolume, 1, Instrument.Guitar));
            // Bass
            audioformat.Mappings.Add(new AudioFormat.Mapping(bassvolume, ghvh ? -1 : 0, Instrument.Bass));
            if (ghvh)
            {
                audioformat.Mappings.Add(new AudioFormat.Mapping(bassvolume, 1, Instrument.Bass));
            }
            // Else / Vocals
            audioformat.Mappings.Add(new AudioFormat.Mapping(bandvolume, -1, Instrument.Ambient));
            audioformat.Mappings.Add(new AudioFormat.Mapping(bandvolume, 1, Instrument.Ambient));
            // Preview
            audioformat.Mappings.Add(new AudioFormat.Mapping(bandvolume, -1, Instrument.Preview));
            audioformat.Mappings.Add(new AudioFormat.Mapping(bandvolume, 1, Instrument.Preview));

            return(audioformat);
        }
Beispiel #12
0
        public ChartFormat DecodeChart(FormatData data, ProgressIndicator progress, params Stream[] chartstreams)
        {
            progress.NewTask(5 + 12);

            PakFormat format = NeversoftMetadata.GetSongItemType(data.Song);
            SongData  song   = NeversoftMetadata.GetSongData(data.PlatformData, NeversoftMetadata.GetSongItem(data));

            List <Pak> chartpaks = new List <Pak>();

            foreach (Stream stream in chartstreams)
            {
                chartpaks.Add(new Pak(new EndianReader(stream, Endianness.BigEndian)));                 // TODO: Endianness based on format?
            }

            FileNode chartfile = null;

            foreach (Pak pak in chartpaks)
            {
                chartfile = pak.FindFile(song.ID + ".mid.qb.ngc") ?? chartfile;
                chartfile = pak.FindFile(song.ID + ".mid.qb") ?? chartfile;
            }
            if (chartfile == null)
            {
                foreach (Pak pak in chartpaks)
                {
                    chartfile = chartfile ?? pak.FindFileType(0xa7f505c4);
                }
            }
            QbFile qbchart = null;

            if (chartfile != null)
            {
                qbchart = new QbFile(chartfile.Data, format);
            }

            StringList strings = new StringList();

            foreach (Pak pak in chartpaks)
            {
                foreach (Pak.Node n in pak.Nodes)
                {
                    if (!n.Filename.HasValue())
                    {
                        strings.ParseFromStream(n.Data);
                    }
                }
            }

            QbFile   qbsections    = null;
            FileNode qbsectionfile = null;

            foreach (Pak pak in chartpaks)
            {
                qbsectionfile = pak.FindFile(song.ID + ".mid_text.qb.ngc") as FileNode ?? qbsectionfile;
                qbsectionfile = pak.FindFile(song.ID + ".mid_text.qb") as FileNode ?? qbsectionfile;
            }
            if (qbsectionfile != null)
            {
                qbsections = new QbFile(qbsectionfile.Data, format);
            }

            Notes    notes     = null;
            FileNode notesfile = null;

            foreach (Pak pak in chartpaks)
            {
                notesfile = notesfile ?? pak.FindFileType(0xa9d5bc8f);
                notesfile = pak.FindFile(song.ID + ".note.ngc") as FileNode ?? notesfile;
                notesfile = pak.FindFile(song.ID + ".note") as FileNode ?? notesfile;
            }
            if (notesfile == null)
            {
                foreach (Pak pak in chartpaks)
                {
                    notesfile = pak.FindFileType(0xa9d5bc8f) ?? notesfile;
                }
            }
            if (notesfile != null)
            {
                notesfile.Data.Position = 0;
                notes = Notes.Create(new EndianReader(notesfile.Data, Endianness.BigEndian));
            }

            NoteChart chart = new NoteChart();

            chart.PartGuitar = new NoteChart.Guitar(chart);
            chart.PartBass   = new NoteChart.Bass(chart);
            chart.PartDrums  = new NoteChart.Drums(chart);
            chart.PartVocals = new NoteChart.Vocals(chart);
            chart.Events     = new NoteChart.EventsTrack(chart);
            chart.Venue      = new NoteChart.VenueTrack(chart);
            chart.Beat       = new NoteChart.BeatTrack(chart);

            bool   gh4v2      = NeversoftMetadata.IsGuitarHero4(data.PlatformData.Game) && data.PlatformData.Game != Game.GuitarHeroWorldTour;
            string drumconfig = gh4v2 ? "drums3" : "drums2";

            chart.PartDrums.Mixing.Add(new Pair <NoteChart.Point, Pair <NoteChart.Difficulty, string> >(new NoteChart.Point(0), new Pair <NoteChart.Difficulty, string>(NoteChart.Difficulty.Easy, drumconfig + "easy")));
            chart.PartDrums.Mixing.Add(new Pair <NoteChart.Point, Pair <NoteChart.Difficulty, string> >(new NoteChart.Point(0), new Pair <NoteChart.Difficulty, string>(NoteChart.Difficulty.Medium, drumconfig)));
            chart.PartDrums.Mixing.Add(new Pair <NoteChart.Point, Pair <NoteChart.Difficulty, string> >(new NoteChart.Point(0), new Pair <NoteChart.Difficulty, string>(NoteChart.Difficulty.Hard, drumconfig)));
            chart.PartDrums.Mixing.Add(new Pair <NoteChart.Point, Pair <NoteChart.Difficulty, string> >(new NoteChart.Point(0), new Pair <NoteChart.Difficulty, string>(NoteChart.Difficulty.Expert, drumconfig)));

            progress.Progress();

            DecodeChartFretbars(song, qbchart, notes, chart);

            progress.Progress();

            DecodeChartSections(song, qbchart, strings, qbsections, notes, chart);

            progress.Progress();

            for (NoteChart.TrackType track = NoteChart.TrackType.Guitar; track <= NoteChart.TrackType.Drums;)
            {
                for (NoteChart.Difficulty difficulty = NoteChart.Difficulty.Easy; difficulty <= NoteChart.Difficulty.Expert; difficulty++)
                {
                    DecodeChartNotes(song, qbchart, notes, chart, track, difficulty);
                    progress.Progress();
                }
                switch (track)
                {
                case NoteChart.TrackType.Guitar: track = NoteChart.TrackType.Bass; break;

                case NoteChart.TrackType.Bass: track = NoteChart.TrackType.Drums; break;

                case NoteChart.TrackType.Drums: track = NoteChart.TrackType.Events; break;
                }
            }

            // Automatic Drum Fills - 1-measure fills every 4 measures, if there's no overdrive overlap
            FillSections(chart, 1, 4, 3, chart.PartDrums.DrumFills, chart.PartDrums.Overdrive);

            progress.Progress();

            if (DecodeChartVocals(song, qbchart, strings, notes, chart))
            {
                DecodeChartVocalPhrases(song, qbchart, notes, chart);
            }

            ImportMap.ImportChart(data.Song, chart);

            progress.Progress();

            progress.EndTask();

            return(new ChartFormat(chart));
        }