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 }); }
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 }); }
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)); }