void OnHasKeyFrame(BMSEvent bmsEvent) { if (!bmsEvent.IsNote || !bmsManager.GetAllAdoptedChannels().Contains(bmsEvent.data1)) { return; } bool isLongNote = bmsEvent.type == BMSEventType.LongNoteEnd || bmsEvent.type == BMSEventType.LongNoteStart, lnDown = false; TimeSpan lnEndpos = TimeSpan.Zero; QueuedLongNoteState queuedLNState = new QueuedLongNoteState(); if (isLongNote) { queuedLongNoteState.TryGetValue(bmsEvent.data1, out queuedLNState); lnDown = queuedLNState.isNoteDown; queuedLNState.isNoteDown = !lnDown; if (!lnDown) { queuedLNState.longNoteId++; lnEndpos = bmsEvent.time2; } queuedLongNoteState[bmsEvent.data1] = queuedLNState; } GetChannelQueue(bmsEvent.data1).Enqueue(new KeyFrame { timePosition = bmsEvent.time, channelId = bmsEvent.data1, dataId = (int)bmsEvent.data2, type = isLongNote ? (lnDown ? NoteType.LongEnd : NoteType.LongStart) : NoteType.Normal, longNoteId = queuedLNState.longNoteId, lnEndPosition = lnEndpos, sliceStart = bmsEvent.sliceStart, sliceEnd = bmsEvent.sliceEnd }); }
void OnPreEvent(BMSEvent bmsEvent) { if (OnPreNoteEvent != null) { OnPreNoteEvent.Invoke(bmsEvent); } }
private void CalculateTimingPoints(List <BMSEvent> bmev) { BMSEvent referencePoint = DefaultReferencePoint; for (int i = 0, l = bmev.Count; i < l; i++) { BMSEvent ev = bmev[i]; ev.time = TicksToTime(referencePoint, ev.ticks); switch (ev.type) { case BMSEventType.BPM: if (referencePoint.data2 != ev.data2) { referencePoint = ev; } break; case BMSEventType.STOP: referencePoint.time = TicksToTime(referencePoint, ev.ticks + (int)ev.data2); ev.data2 = (referencePoint.time - ev.time).Ticks; break; } bmev[i] = ev; } }
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)); }
void OnPostMap(BMSEvent bmsEvent) { if (!bmsEvent.IsNote || !bmsManager.GetAllAdoptedChannels().Contains(bmsEvent.data1)) { return; } HandleNoteEvent(bmsEvent.data1, false, false); }
void OnEventUpdate(BMSEvent bmsEvent) { switch (bmsEvent.type) { case BMSEventType.WAV: PlayWAV((int)bmsEvent.data2, bmsEvent.sliceStart, bmsEvent.sliceEnd); break; case BMSEventType.BMP: ChangeBGA(bmsEvent.data1, (int)bmsEvent.data2); break; case BMSEventType.BeatReset: bpmBasePointBeatFlow = 0; bpmBasePoint = timePosition; currentTimeSignature = (float)bmsEvent.Data2F; break; case BMSEventType.BPM: float newBpm = (float)bmsEvent.Data2F; bpmBasePointBeatFlow += (timePosition - bpmBasePoint).ToAccurateMinuteF() * bpm; bpmBasePoint = timePosition; bpm = newBpm; CalculatePreOffset(); if (OnChangeBPM != null) { OnChangeBPM.Invoke(newBpm); } break; case BMSEventType.STOP: TimeSpan offset = new TimeSpan(bmsEvent.data2); stopPosition = bmsEvent.time + offset; bpmBasePoint -= offset; break; default: if (!handledChannels.Contains(bmsEvent.data1)) { bool shouldPlayWav = true; if (bmsEvent.type == BMSEventType.LongNoteEnd || bmsEvent.type == BMSEventType.LongNoteStart) { int lnState; if (!autoPlayLNState.TryGetValue(bmsEvent.data1, out lnState)) { lnState = 0; } shouldPlayWav = lnState != bmsEvent.data2; autoPlayLNState[bmsEvent.data1] = lnState > 0 ? 0 : bmsEvent.data1; } if (shouldPlayWav) { PlayWAV((int)bmsEvent.data2, bmsEvent.sliceStart, bmsEvent.sliceEnd); } } if (OnNoteEvent != null) { OnNoteEvent.Invoke(bmsEvent); } break; } }
protected int AddEvent(BMSEvent ev) { if (ev.IsNote) { allChannels.Add(ev.data1); maxCombos++; } return(bmsEvents.InsertInOrdered(ev)); }
private TimeSpan TicksToTime(BMSEvent referencePoint, int currentTicks) { return(referencePoint.time + new TimeSpan( (long)Math.Round( (double)(currentTicks - referencePoint.ticks) / tickResoultion / referencePoint.Data2F * TimeSpan.TicksPerMinute ) )); }
void NoteEvent(BMSEvent bmsEvent) { if (autoMode) { if (!bmsManager.GetAllAdoptedChannels().Contains(bmsEvent.data1)) { return; } HandleNoteEvent(bmsEvent.data1, true, bmsEvent.type == BMSEventType.LongNoteStart || bmsEvent.type == BMSEventType.Note); } }
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(ExtendedSortedSet <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.Add(new BMSEvent { measure = meas + 1, beat = 0, Data2F = 1, type = BMSEventType.BeatReset }, InsertMode.OldFirst); } } }
private TimeSpan CalculateTime(List <BMSEvent> bmev, int ticks) { int index = bmev.BinarySearchIndex( new BMSEvent { ticks = ticks }, BinarySearchMethod.FloorClosest | BinarySearchMethod.LastExact, 0, -1, TicksComparer.instance ); BMSEvent lastReferencePoint = DefaultReferencePoint; TimeSpan stopOffset = TimeSpan.Zero; while (index >= 0) { lastReferencePoint = bmev[index]; bool found = false; switch (lastReferencePoint.type) { case BMSEventType.BPM: lastReferencePoint.time += stopOffset; found = true; break; case BMSEventType.STOP: stopOffset += new TimeSpan(lastReferencePoint.data2); break; } if (found) { break; } index--; } return(TicksToTime(lastReferencePoint, ticks)); }
private void PostProcessContent(ExtendedSortedSet <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; EnsureCapacity(bmev.Count + 1); AddEvent(new BMSEvent { measure = 0, beat = 0, type = BMSEventType.BPM, Data2F = bpm }); foreach (BMSEvent ev in bmev) { BMSEvent converted = new BMSEvent { measure = ev.measure, 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: double newBpm; if (ev.data1 == 8 && TryGetResourceData(ResourceType.bpm, ev.data2, out BMSResourceData bpmData)) // Extended BPM { newBpm = Convert.ToDouble(bpmData.additionalData); } else if (ev.data1 == 3 && int.TryParse(Base36.Encode((int)ev.data2), NumberStyles.HexNumber, null, out int 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: if (!TryGetResourceData(ResourceType.stop, ev.data2, out BMSResourceData 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; if (lnMarker.TryGetValue(ev.data1, out BMSEvent 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); } }
public void AddEvent(BMSEvent bmsEvent) => eventTree.Add(bmsEvent);
private void ParseSoundChannel(List <BMSEvent> bmev, IJsonWrapper rawData, int index) { string name = rawData.GetChild("name").AsString(); if (string.IsNullOrEmpty(name)) { return; } AddResource(ResourceType.wav, index, name); BMSEvent? lastEvent = null; TimeSpan slicedPosition = TimeSpan.Zero; IList <BMSEvent> events = Events; foreach (IJsonWrapper note in rawData.GetChild("notes").GetChilds()) { BMSEvent currentEvent; int ticks = note.GetChild("y").AsInt32(); int channelId = GetChannelMap(note.GetChild("x").AsInt32()); int length = note.GetChild("l").AsInt32(); TimeSpan currentTime = CalculateTime(bmev, ticks); if (lastEvent.HasValue) { currentEvent = lastEvent.Value; int lastIndex = FindEventIndex(currentEvent); if (note.GetChild("c").AsBoolean()) { currentEvent.sliceEnd = slicedPosition = currentTime - currentEvent.time + currentEvent.sliceStart; } else { currentEvent.sliceEnd = TimeSpan.MaxValue; slicedPosition = TimeSpan.Zero; } ReplaceEvent(lastIndex, currentEvent); } if (length > 0) { TimeSpan endTime = CalculateTime(bmev, ticks + length); lastEvent = currentEvent = new BMSEvent { type = BMSEventType.LongNoteStart, ticks = ticks, time = currentTime, data1 = channelId, data2 = index, time2 = endTime - currentTime, sliceStart = slicedPosition, sliceEnd = TimeSpan.MaxValue }; AddEvent(currentEvent); AddEvent(new BMSEvent { type = BMSEventType.LongNoteEnd, ticks = ticks + length, time = endTime, data1 = channelId, data2 = index }); } else { lastEvent = currentEvent = new BMSEvent { type = channelId == 0 ? BMSEventType.WAV : BMSEventType.Note, ticks = ticks, time = currentTime, data1 = channelId, data2 = index, sliceStart = slicedPosition, sliceEnd = TimeSpan.MaxValue }; AddEvent(currentEvent); } } }