private static void DecodeChartMarkers(SongData song, QbFile qbsections, QbFile qbchart, NoteChart chart) { QbItemStructArray markers = (qbchart.FindItem(QbKey.Create(song.ID + "_markers"), false) as QbItemArray).Items[0] as QbItemStructArray; if (markers != null) { foreach (QbItemStruct mark in markers.Items) { QbItemString section = qbsections.FindItem((mark.Items[1] as QbItemQbKey).Values[0], false) as QbItemString; chart.Events.Sections.Add(new Pair <NoteChart.Point, string>(new NoteChart.Point(chart.GetTicks((mark.Items[0] as QbItemInteger).Values[0])), section.Strings[0])); } } }
private void DecodeChartSections(SongData song, QbFile qbchart, StringList strings, QbFile qbsections, Notes notes, NoteChart chart) { if (notes != null) { uint[] values = GetChartValues(notes, null, QbKey.Create(0x92511D84), null, 4, 4); for (int k = 0; k < values.Length; k += 2) { uint time = values[k]; string text = strings.FindItem(QbKey.Create(values[k + 1])); chart.Events.Sections.Add(new Pair <NoteChart.Point, string>(new NoteChart.Point(chart.GetTicks(time)), text)); } } else { QbItemStructArray markers = (qbchart.FindItem(QbKey.Create(song.ID + "_guitar_markers"), false) as QbItemArray).Items[0] as QbItemStructArray; foreach (QbItemStruct mark in markers.Items) { QbItemQbKey section = qbsections.FindItem((mark.Items[1] as QbItemQbKey).Values[0], false) as QbItemQbKey; chart.Events.Sections.Add(new Pair <NoteChart.Point, string>(new NoteChart.Point(chart.GetTicks((mark.Items[0] as QbItemInteger).Values[0])), strings.FindItem(section.Values[0]))); } } }
private static QbItemBase createQbItemType(QbFile qbFile, QbItemType type, QbFormat qbFormat, bool hasQbFormat) { QbItemBase qib = null; if (qbFile.PakFormat.GetQbItemValue(type, qbFile) == 0xFFFFFFFF) throw new ApplicationException(string.Format("'{0}' data value not known for {1}", type.ToString(), qbFile.PakFormat.FriendlyName)); switch (type) { //case QbItemType.Unknown: // break; case QbItemType.SectionString: case QbItemType.SectionStringW: case QbItemType.ArrayString: case QbItemType.ArrayStringW: case QbItemType.StructItemString: case QbItemType.StructItemStringW: qib = new QbItemString(qbFile); break; case QbItemType.SectionArray: case QbItemType.ArrayArray: case QbItemType.StructItemArray: qib = new QbItemArray(qbFile); break; case QbItemType.SectionStruct: case QbItemType.StructItemStruct: case QbItemType.StructHeader: qib = new QbItemStruct(qbFile); break; case QbItemType.SectionScript: qib = new QbItemScript(qbFile); break; case QbItemType.SectionFloat: case QbItemType.ArrayFloat: case QbItemType.StructItemFloat: qib = new QbItemFloat(qbFile); break; case QbItemType.SectionFloatsX2: case QbItemType.SectionFloatsX3: case QbItemType.ArrayFloatsX2: case QbItemType.ArrayFloatsX3: case QbItemType.StructItemFloatsX2: case QbItemType.StructItemFloatsX3: qib = new QbItemFloatsArray(qbFile); break; case QbItemType.SectionInteger: case QbItemType.SectionStringPointer: case QbItemType.ArrayInteger: case QbItemType.ArrayStringPointer: //GH:GH case QbItemType.StructItemStringPointer: case QbItemType.StructItemInteger: qib = new QbItemInteger(qbFile); break; case QbItemType.SectionQbKey: case QbItemType.SectionQbKeyString: case QbItemType.SectionQbKeyStringQs: //GH:GH case QbItemType.ArrayQbKey: case QbItemType.ArrayQbKeyString: case QbItemType.ArrayQbKeyStringQs: //GH:GH case QbItemType.StructItemQbKey: case QbItemType.StructItemQbKeyString: case QbItemType.StructItemQbKeyStringQs: qib = new QbItemQbKey(qbFile); break; case QbItemType.Floats: qib = new QbItemFloats(qbFile); break; case QbItemType.ArrayStruct: qib = new QbItemStructArray(qbFile); break; default: throw new ApplicationException(string.Format("'{0}' is not recognised by CreateQbItemType.", type.ToString())); } if (qib != null) qib.Create(type); return qib; }
public override void Construct(BinaryEndianReader br, QbItemType type) { //System.Diagnostics.Debug.WriteLine(string.Format("{0} - 0x{1}", type.ToString(), (base.StreamPos(br) - 4).ToString("X").PadLeft(8, '0'))); base.Construct(br, type); QbItemBase qib = null; QbItemType arrayType; uint arrayValue; for (int i = 0; i < base.ItemCount; i++) { arrayValue = br.ReadUInt32(this.Root.PakFormat.EndianType); arrayType = this.Root.PakFormat.GetQbItemType(arrayValue); switch (arrayType) { case QbItemType.Floats: qib = new QbItemFloats(this.Root); break; case QbItemType.ArrayStruct: qib = new QbItemStructArray(this.Root); break; case QbItemType.ArrayFloat: qib = new QbItemFloat(this.Root); break; case QbItemType.ArrayString: case QbItemType.ArrayStringW: qib = new QbItemString(this.Root); break; case QbItemType.ArrayFloatsX2: case QbItemType.ArrayFloatsX3: qib = new QbItemFloatsArray(this.Root); break; case QbItemType.ArrayStringPointer: case QbItemType.ArrayInteger: qib = new QbItemInteger(this.Root); break; case QbItemType.ArrayArray: qib = new QbItemArray(this.Root); break; case QbItemType.ArrayQbKey: case QbItemType.ArrayQbKeyString: case QbItemType.ArrayQbKeyStringQs: //GH:GH qib = new QbItemQbKey(this.Root); break; case QbItemType.StructHeader: qib = new QbItemStruct(this.Root); break; default: throw new ApplicationException(string.Format("Location 0x{0}: Unknown array type 0x{1}", (base.StreamPos(br) - 4).ToString("X").PadLeft(8, '0'), arrayValue.ToString("X").PadLeft(8, '0'))); } qib.Construct(br, arrayType); AddItem(qib); } base.ConstructEnd(br); }
private bool DecodeChartVocals(SongData song, QbFile qbchart, StringList strings, Notes notes, NoteChart chart) { uint[] values = GetChartValues(notes, qbchart, QbKey.Create(0xE8E6ADCB), QbKey.Create(song.ID + "_song_vocals"), 4, 2, 1); for (int k = 0; k < values.Length; k += 3) { byte note = (byte)values[k + 2]; if (note != 2) { if (note > 84) { note -= 12; } chart.PartVocals.Gems.Add(new Midi.NoteEvent(chart.GetTicks(values[k]), 0, note, 100, chart.GetTicksDuration(values[k], values[k + 1]))); } } List <Pair <NoteChart.Point, string> > vlyrics = new List <Pair <NoteChart.Point, string> >(); if (notes != null) { byte[][] vdata = notes.Find(QbKey.Create(0x1DA27F4E)).Data; foreach (byte[] d in vdata) { EndianReader reader = new EndianReader(new MemoryStream(d), Endianness.BigEndian); uint time = reader.ReadUInt32(); string lyric = reader.ReadString(); vlyrics.Add(new Pair <NoteChart.Point, string>( new NoteChart.Point(chart.GetTicks(time)), lyric )); } } else { QbItemStructArray lyrics = (qbchart.FindItem(QbKey.Create(song.ID + "_lyrics"), false) as QbItemArray).Items[0] as QbItemStructArray; if (lyrics != null) { foreach (QbItemBase item in lyrics.Items) { string lyric = strings.FindItem((item.Items[1] as QbItemQbKey).Values[0]); vlyrics.Add(new Pair <NoteChart.Point, string>( new NoteChart.Point(chart.GetTicks((item.Items[0] as QbItemInteger).Values[0])), lyric )); } } } Pair <NoteChart.Point, string> lastlyric = null; foreach (var item in vlyrics) { string lyric = item.Value; if (lyric.StartsWith("=") && lastlyric != null) { if (lastlyric.Value.EndsWith("-")) { lastlyric.Value = lastlyric.Value.Substring(0, lastlyric.Value.Length - 1) + '='; } else { lastlyric.Value += "-"; } lyric = lyric.Substring(1); } lastlyric = new Pair <NoteChart.Point, string>( item.Key, lyric ); chart.PartVocals.Lyrics.Add(lastlyric); } foreach (Midi.NoteEvent item in chart.PartVocals.Gems) { bool found = false; foreach (Pair <NoteChart.Point, string> lyric in chart.PartVocals.Lyrics) { if (lyric.Key.Time == item.Time) { if (item.Note == 26) { lyric.Value += "#"; item.Note = 36; } found = true; break; } } if (!found) { chart.PartVocals.Lyrics.Add(new Pair <NoteChart.Point, string>(new NoteChart.Point(item.Time), "+")); } } __goddamnremovals: //Midi.NoteEvent lastnote = null; foreach (Pair <NoteChart.Point, string> lyric in chart.PartVocals.Lyrics) { bool found = false; foreach (Midi.NoteEvent item in chart.PartVocals.Gems) { if (lyric.Key.Time == item.Time) { found = true; break; } } if (!found) { /* * ulong duration = chart.GetTicksDuration(chart.GetTime(lyric.Key.Time) / 1000, 30); * if (lastnote != null && lastnote.Time + lastnote.Duration > lyric.Key.Time) * lastnote.Duration = lyric.Key.Time - lastnote.Time - 20; * lastnote = new Midi.NoteEvent(lyric.Key.Time, 0, 36, 100, duration); * chart.PartVocals.Gems.Add(lastnote); * lyric.Value += "^"; */ chart.PartVocals.Lyrics.Remove(lyric); goto __goddamnremovals; } } if (chart.PartVocals.Gems.Count == 0) { chart.PartVocals = null; return(false); } return(true); }
private void calculateMarkers(int[] frets, QbItemArray arr, QbFile text) { int minNote = this.Notes.MinNoteOffsetSynced + _startPaddingMs + _fretPadding; int maxNote = this.Notes.MaxNoteOffsetSynced + _startPaddingMs + _fretPadding; int pos = minNote; int sectionSecs = 20000; int sections = (maxNote - minNote) / sectionSecs; //every x seconds for (int c = text.Items.Count - 1; c > 0; c--) text.RemoveItem(text.Items[c]); QbItemStructArray sa = new QbItemStructArray(arr.Root); sa.Create(QbItemType.ArrayStruct); arr.Items.Clear(); arr.AddItem(sa); QbItemStruct s; QbItemInteger i; QbItemQbKey q; string sectionTitle; QbKey qbKey; QbItemString txt; for (int c = 0; c < sections; c++) { if (pos + 3000 > this.Length) break; //don't create a section less than 3 seconds long sectionTitle = string.Format("Section {0}", (c + 1).ToString()); qbKey = QbKey.Create(string.Format("{0}_markers_text_{1}", this.SongQb.Id, QbKey.Create(sectionTitle).Crc.ToString("x").ToLower())); txt = new QbItemString(text); txt.Create(QbItemType.SectionString); txt.ItemQbKey = qbKey; txt.Strings = new string[] { sectionTitle }; text.AddItem(txt); s = new QbItemStruct(arr.Root); s.Create(QbItemType.StructHeader); sa.AddItem(s); i = new QbItemInteger(arr.Root); i.Create(QbItemType.StructItemInteger); i.ItemQbKey = QbKey.Create("time"); i.Values = new uint[] { findNearestFret((uint)pos, frets) }; s.AddItem(i); pos += sectionSecs; q = new QbItemQbKey(arr.Root); q.Create(QbItemType.StructItemQbKeyString); q.ItemQbKey = QbKey.Create("marker"); q.Values = new QbKey[] { qbKey }; s.AddItem(q); } text.AlignPointers(); arr.Root.AlignPointers(); }
private void setMarkers(int[] frets, QbItemArray arr, QbFile text, NotesMarker[] markers) { int minNote = this.Notes.MinNoteOffsetSynced + _startPaddingMs + _fretPadding; QbItemStruct s; QbItemInteger i; QbItemQbKey q; QbKey qbKey; QbItemString txt; for (int c = text.Items.Count - 1; c > 0; c--) text.RemoveItem(text.Items[c]); if (arr.Items[0] is QbItemFloats) { QbItemStructArray newArr = new QbItemStructArray(arr.Root); newArr.Create(QbItemType.ArrayStruct); arr.AddItem(newArr); arr.RemoveItem(arr.Items[0]); } QbItemStructArray sa = (QbItemStructArray)arr.Items[0]; sa.Items.Clear(); NotesMarker marker; List<NotesMarker> mrk = new List<NotesMarker>(markers); if (mrk.Count > 0 && mrk[0].Offset > minNote) //some charts don't have sections at the start so you can't practice the start notes :-( { if (mrk[0].Offset > minNote + 5000) // if > 5secs then add new mrk.Insert(0, new NotesMarker("Start", minNote)); else //else move first marker back to start mrk[0].Offset = minNote; } for (int c = 0; c < mrk.Count; c++) { marker = mrk[c]; if (c < mrk.Count - 1 && mrk[c + 1].Offset < minNote) continue; //don't add sections at the start that would have no notes (crashes song??) qbKey = QbKey.Create(string.Format("{0}_markers_text_{1}", this.SongQb.Id, QbKey.Create(marker.Title).Crc.ToString("x").ToLower())); txt = new QbItemString(text); txt.Create(QbItemType.SectionString); txt.ItemQbKey = qbKey; txt.Strings = new string[] { marker.Title }; text.AddItem(txt); s = new QbItemStruct(arr.Root); s.Create(QbItemType.StructHeader); sa.AddItem(s); i = new QbItemInteger(arr.Root); i.Create(QbItemType.StructItemInteger); i.ItemQbKey = QbKey.Create("time"); i.Values = new uint[] { findNearestFret((uint)marker.Offset, frets) }; s.AddItem(i); q = new QbItemQbKey(arr.Root); q.Create(QbItemType.StructItemQbKeyString); q.ItemQbKey = QbKey.Create("marker"); q.Values = new QbKey[] { qbKey }; s.AddItem(q); } text.AlignPointers(); arr.Root.AlignPointers(); }