protected int FindEventIndex(BMSEvent ev) { int firstIndex = bmsEvents.BinarySearchIndex(ev, BinarySearchMethod.FirstExact); int lastIndex = bmsEvents.BinarySearchIndex(ev, BinarySearchMethod.LastExact, firstIndex); return(firstIndex == lastIndex ? firstIndex : bmsEvents.IndexOf(ev, firstIndex, lastIndex - firstIndex + 1)); }
protected int AddEvent(BMSEvent ev) { if (ev.IsNote) { allChannels.Add(ev.data1); maxCombos++; } return(bmsEvents.InsertInOrdered(ev)); }
protected void ReplaceEvent(int index, BMSEvent newEv) { BMSEvent original = bmsEvents[index]; if (original.CompareTo(newEv) == 0) { bmsEvents[index] = newEv; return; } bmsEvents.RemoveAt(index); bmsEvents.InsertInOrdered(newEv); }
// Insert beat reset after 1 measure of time signature change event according to BMS specifications. private static void BeatResetFix(List <BMSEvent> bmev) { BMSEvent[] beatResetEvents = bmev.Where(ev => ev.type == BMSEventType.BeatReset).ToArray(); for (int i = 0, l = beatResetEvents.Length; i < l; i++) { BMSEvent currentEv = beatResetEvents[i]; int meas = currentEv.measure; if (i == l - 1 || (beatResetEvents[i + 1].measure - meas > 1 && currentEv.Data2F != 1)) { bmev.InsertInOrdered(new BMSEvent { measure = meas + 1, beat = 0, Data2F = 1, type = BMSEventType.BeatReset }); } } }
private void PostProcessContent(List <BMSEvent> bmev) { Dictionary <int, BMSEvent> lnMarker = new Dictionary <int, BMSEvent>(); double bpm = initialBPM, beatOffset = 0, beatPerMeas = 1; TimeSpan referenceTimePoint = TimeSpan.Zero; TimeSpan stopTimePoint = TimeSpan.Zero; float stopMeasBeat = 0; AddEvent(new BMSEvent { measure = 0, beat = 0, type = BMSEventType.BPM, Data2F = bpm }); foreach (BMSEvent ev in bmev) { BMSEvent converted = new BMSEvent(); converted.measure = ev.measure; converted.beat = (float)(ev.beat * beatPerMeas); if (ev.measure + ev.beat == stopMeasBeat) { converted.time = stopTimePoint; } else { converted.time = referenceTimePoint + MeasureBeatToTimeSpan(ev.measure + ev.beat - beatOffset, beatPerMeas, bpm); } switch (ev.type) { case BMSEventType.BPM: BMSResourceData bpmData; int bpmInt; double newBpm; if (ev.data1 == 8 && TryGetResourceData(ResourceType.bpm, ev.data2, out bpmData)) // Extended BPM { newBpm = Convert.ToDouble(bpmData.additionalData); } else if (ev.data1 == 3 && int.TryParse(Base36.Encode((int)ev.data2), NumberStyles.HexNumber, null, out bpmInt)) // BPM { newBpm = bpmInt; } else { continue; } if (newBpm == bpm) { continue; } converted.type = BMSEventType.BPM; converted.Data2F = newBpm; referenceTimePoint = converted.time; beatOffset = ev.measure + ev.beat; bpm = newBpm; minBpm = Math.Min(minBpm, (float)newBpm); break; case BMSEventType.BeatReset: double newBeatPerMeas = ev.Data2F; if (newBeatPerMeas == beatPerMeas) { continue; } converted.type = BMSEventType.BeatReset; converted.Data2F = ev.Data2F * 4; beatOffset = ev.measure; beatPerMeas = newBeatPerMeas; referenceTimePoint = converted.time; break; case BMSEventType.STOP: BMSResourceData stopData; if (!TryGetResourceData(ResourceType.stop, ev.data2, out stopData)) { continue; } double stopSeconds = Convert.ToDouble(stopData.additionalData) / bpm * 1.25; if (stopSeconds <= 0) { continue; } converted.type = BMSEventType.STOP; stopTimePoint = converted.time; stopMeasBeat = ev.measure + ev.beat; TimeSpan stopTime = new TimeSpan((long)Math.Round(stopSeconds * TimeSpan.TicksPerSecond)); converted.data2 = stopTime.Ticks; referenceTimePoint += stopTime; break; case BMSEventType.BMP: converted.type = BMSEventType.BMP; switch (ev.data1) { case 4: converted.data1 = 0; break; case 6: converted.data1 = -1; break; case 7: converted.data1 = 1; break; default: continue; } converted.data2 = ev.data2; break; case BMSEventType.LongNoteStart: converted.data1 = ev.data1 - 40; converted.data2 = ev.data2; converted.sliceStart = TimeSpan.Zero; converted.sliceEnd = TimeSpan.MaxValue; BMSEvent lnStart; if (lnMarker.TryGetValue(ev.data1, out lnStart)) { converted.type = BMSEventType.LongNoteEnd; int index = FindEventIndex(lnStart); lnStart.time2 = converted.time; ReplaceEvent(index, lnStart); lnMarker.Remove(ev.data1); } else { converted.type = BMSEventType.LongNoteStart; lnMarker[ev.data1] = converted; } break; case BMSEventType.Unknown: continue; default: if ((ev.data1 >= 30 && ev.data1 <= 50) || ev.data1 >= 70) { continue; } converted.type = ev.type; converted.data1 = ev.data1; converted.data2 = ev.data2; converted.sliceStart = TimeSpan.Zero; converted.sliceEnd = TimeSpan.MaxValue; break; } AddEvent(converted); } }