Esempio n. 1
0
 // 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);
         }
     }
 }
Esempio n. 2
0
        public override void Parse(ParseType parseType)
        {
            ResetAllData(parseType);
            if ((parseType & ParseType.Header) == ParseType.Header)
            {
                LnType = 1;
            }
            InitSources();

            Stack <IfBlock> ifStack;
            ExtendedSortedSet <BMSEvent> bmev;
            HashSet <int> channels;
            Random        random;
            int           maxCombos = 0;

            if ((parseType & ParseType.Content) == ParseType.Content)
            {
                ifStack = new Stack <IfBlock>();
                ifStack.Push(new IfBlock {
                    parsing = true
                });
                random     = new Random();
                bmev       = new ExtendedSortedSet <BMSEvent>();
                randomized = false;
                channels   = null;
            }
            else if ((parseType & ParseType.ContentSummary) == ParseType.ContentSummary)
            {
                ifStack  = null;
                random   = null;
                bmev     = null;
                channels = new HashSet <int>();
            }
            else
            {
                ifStack  = null;
                random   = null;
                bmev     = null;
                channels = null;
            }
            for (int i = 0, c = bmsContent.Count; i < c; i++)
            {
                try {
                    string line = bmsContent[i];
                    string command, command2, param1, param2;

                    // Command parsing
                    int colonIndex = line.IndexOf(':', 1), spaceIndex = line.IndexOf(' ', 1);
                    int spliiterIndex = colonIndex >= 0 && (spaceIndex > colonIndex || spaceIndex < 0) ? colonIndex : spaceIndex;
                    if (spliiterIndex > 0)
                    {
                        command = line.Substring(0, spliiterIndex);
                        if (spliiterIndex + 1 < line.Length)
                        {
                            param1 = line.Substring(spliiterIndex + 1).Trim();
                        }
                        else
                        {
                            param1 = string.Empty;
                        }
                    }
                    else
                    {
                        command = line;
                        param1  = string.Empty;
                    }
                    command = command.ToLower();

                    // Header part
                    if ((parseType & ParseType.Header) == ParseType.Header)
                    {
                        if (ParseHeaderLine(command, param1))
                        {
                            continue;
                        }
                    }

                    // nnnXX pattern parsing
                    if (command.Length > 4)
                    {
                        int j = command.Length - 2;
                        command2 = command.Substring(1, j - 1);
                        param2   = command.Substring(j);
                    }
                    else
                    {
                        command2 = command;
                        param2   = string.Empty;
                    }

                    // Resource part
                    if ((parseType & ParseType.Resources) == ParseType.Resources)
                    {
                        if (ParseResourceLine(command2, param1, param2))
                        {
                            continue;
                        }
                    }

                    // Content part
                    if ((parseType & ParseType.Content) == ParseType.Content)
                    {
                        if (CheckExecution(ifStack, random, command, param1))
                        {
                            continue;
                        }
                        if (ParseContentLine(command2, param1, param2, bmev))
                        {
                            continue;
                        }
                    }
                    else if ((parseType & ParseType.ContentSummary) == ParseType.ContentSummary)
                    {
                        if (ParseSummary(command2, param1, param2, channels, out int combos))
                        {
                            maxCombos += combos;
                            continue;
                        }
                    }
                } catch (Exception ex) {
                    throw new LineParseException(i, ex);
                }
            }

            if ((parseType & ParseType.Content) == ParseType.Content)
            {
                BeatResetFix(bmev);
                PostProcessContent(bmev);
            }
            else if ((parseType & ParseType.ContentSummary) == ParseType.ContentSummary)
            {
                this.maxCombos = maxCombos;
                ReportChannels(channels);
            }

            base.Parse(parseType);
        }
Esempio n. 3
0
        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);
            }
        }
Esempio n. 4
0
        private static bool ParseContentLine(string command2, string strParam1, string strParam2, ExtendedSortedSet <BMSEvent> bmev)
        {
            if (!int.TryParse(command2, out int verse))
            {
                return(false);
            }
            int channel = GetChannelNumberById(strParam2);

            if (channel < 0)
            {
                return(false);
            }
            strParam1 = spaceMatcher.Replace(strParam1, string.Empty);
            int          length = strParam1.Length / 2;
            BMSEventType evType;

            switch (channel)
            {
            case 1: evType = BMSEventType.WAV; break;

            case 2:
                bmev.Add(new BMSEvent {
                    measure = verse,
                    beat    = 0,
                    Data2F  = double.Parse(strParam1),
                    type    = BMSEventType.BeatReset
                }, InsertMode.OldFirst);
                return(true);

            case 3: evType = BMSEventType.BPM; break;

            case 4:
            case 6:
            case 7: evType = BMSEventType.BMP; break;

            case 8: evType = BMSEventType.BPM; break;

            case 9: evType = BMSEventType.STOP; break;

            default:
                if (channel > 10 && channel < 30)
                {
                    evType = BMSEventType.Note;
                }
                else if (channel > 50 && channel < 70)
                {
                    evType = BMSEventType.LongNoteStart;
                }
                else
                {
                    evType = BMSEventType.Unknown;
                }
                break;
            }
            for (int i = 0; i < length; i++)
            {
                int value = Base36.Decode(strParam1.Substring(i * 2, 2));
                if (value > 0)
                {
                    bmev.Add(new BMSEvent {
                        measure = verse,
                        beat    = (float)i / length,
                        type    = evType,
                        data1   = channel,
                        data2   = value
                    }, InsertMode.OldFirst);
                }
            }
            return(true);
        }