public IList <TwinkleBeatmaniaChartEvent> Decode(ReadOnlySpan <byte> data, int length)
        {
            var result        = new List <TwinkleBeatmaniaChartEvent>();
            var noteCountMode = true;

            for (var i = 0; i < length; i += 4)
            {
                if (noteCountMode)
                {
                    if (data[i + 0x03] == 0 || data[i + 0x03] == 1)
                    {
                        continue;
                    }
                    noteCountMode = false;
                }

                var offset = Bitter.ToInt16S(data, i);
                if (offset == 0x7FFF)
                {
                    break;
                }

                var value   = data[i + 0x02];
                var command = data[i + 0x03];
                result.Add(new TwinkleBeatmaniaChartEvent
                {
                    Offset = (ushort)offset,
                    Param  = command,
                    Value  = value
                });
            }

            return(result);
        }
        public HeuristicResult Match(IHeuristicReader reader)
        {
            var data = reader.Read(0x10);

            if (data.Length < 0x10)
            {
                return(null);
            }

            var length = Bitter.ToInt32S(data);

            if (length == 0)
            {
                return(null);
            }

            if ((length & 0x7FF) != 0)
            {
                return(null);
            }

            if (data[0x05] == 0)
            {
                return(null);
            }

            var sampleRate = Bitter.ToInt16S(data, 6);

            if (sampleRate == 0)
            {
                return(null);
            }

            if (data[0x08] == 0)
            {
                return(null);
            }

            if (data[0x08] > 2)
            {
                return(null);
            }

            return(new VagHeuristicResult(this)
            {
                Start = 0x800,
                Interleave = 0x800,
                Channels = data[0x08],
                SampleRate = sampleRate,
                Length = length
            });
        }
Ejemplo n.º 3
0
        public TwinkleBeatmaniaSoundDefinition Decode(ReadOnlySpan <byte> data)
        {
            if (data.Length < 0x12)
            {
                return(null);
            }

            var invalid = true;

            for (var i = 1; i < 0x12; i++)
            {
                if (data[i] != data[0])
                {
                    invalid = false;
                    break;
                }
            }

            if (invalid)
            {
                return(null);
            }

            return(new TwinkleBeatmaniaSoundDefinition
            {
                Channel = data[0x00],
                Flags01 = data[0x01],
                Frequency = Bitter.ToInt16S(data, 0x02) & 0xFFFF,
                Volume = data[0x04],
                Panning = data[0x05],
                SampleStart = Bitter.ToInt24S(data, 0x06) & 0xFFFFFF,
                SampleEnd = Bitter.ToInt24S(data, 0x09) & 0xFFFFFF,
                Value0C = Bitter.ToInt16S(data, 0x0C) & 0xFFFF,
                Flags0E = data[0x0E],
                Flags0F = data[0x0F],
                SizeInBlocks = Bitter.ToInt16S(data, 0x10) & 0xFFFF
            });
        }
Ejemplo n.º 4
0
        public HeuristicResult Match(IHeuristicReader reader)
        {
            var noteCountMode = true;
            var hasBpm        = false;
            var hasEnd        = false;
            var hasTerminator = false;
            var evData        = new byte[4];

            while (true)
            {
                if (reader.Read(evData, 0, 4) < 4)
                {
                    break;
                }

                var eventOffset    = Bitter.ToInt16S(evData);
                var eventValue     = evData[2];
                var eventCommand   = evData[3];
                var eventParameter = eventCommand >> 4;
                var eventType      = eventCommand & 0xF;

                // empty event = invalid
                if (Bitter.ToInt32(evData) == 0)
                {
                    return(null);
                }

                // positive event offsets only
                if (eventOffset < 0)
                {
                    return(null);
                }

                // offsets can't be present during note count
                if (noteCountMode && eventOffset != 0)
                {
                    return(null);
                }

                // disable note count info if another event type shows up
                if (eventCommand != 0x00 && eventCommand != 0x01)
                {
                    noteCountMode = false;
                }

                // skip the rest of processing if in note count mode
                if (noteCountMode)
                {
                    continue;
                }

                // terminator bytes
                if (eventOffset == 0x7FFF)
                {
                    hasTerminator = true;
                    break;
                }

                // make sure we have the bare minimums
                if (eventType == 6)
                {
                    hasEnd = true;
                }
                else if (eventType == 4 && eventValue + (eventParameter << 8) != 0)
                {
                    hasBpm = true;
                }
            }

            if (!(hasBpm && hasEnd && hasTerminator))
            {
                return(null);
            }

            return(new HeuristicResult(this));
        }