mirror of https://github.com/x64dbg/btparser
242 lines
5.6 KiB
Plaintext
242 lines
5.6 KiB
Plaintext
|
/* General-MIDI Parser
|
||
|
* By Jack Andersen
|
||
|
*/
|
||
|
|
||
|
BigEndian();
|
||
|
|
||
|
struct MidiHeader
|
||
|
{
|
||
|
char m_magic[4] <format = hex>;
|
||
|
uint m_seclen;
|
||
|
enum <short>
|
||
|
{
|
||
|
MIDI_SINGLE = 0,
|
||
|
MIDI_MULTIPLE = 1,
|
||
|
MIDI_PATTERN = 2
|
||
|
} m_format;
|
||
|
short m_ntracks;
|
||
|
short m_tickdiv;
|
||
|
};
|
||
|
|
||
|
struct DeltaTime
|
||
|
{
|
||
|
local uint total = 0;
|
||
|
char t0;
|
||
|
total += t0 & 0x7f;
|
||
|
if (!(t0 & 0x80))
|
||
|
break;
|
||
|
|
||
|
total <<= 7;
|
||
|
char t1;
|
||
|
total += t1 & 0x7f;
|
||
|
if (!(t1 & 0x80))
|
||
|
break;
|
||
|
|
||
|
total <<= 7;
|
||
|
char t2;
|
||
|
total += t2 & 0x7f;
|
||
|
if (!(t2 & 0x80))
|
||
|
break;
|
||
|
|
||
|
total <<= 7;
|
||
|
char t3;
|
||
|
total += t3 & 0x7f;
|
||
|
if (!(t3 & 0x80))
|
||
|
break;
|
||
|
};
|
||
|
|
||
|
struct MidiMessage
|
||
|
{
|
||
|
DeltaTime m_dtime;
|
||
|
char m_status;
|
||
|
local char m_channel = m_status & 0xf;
|
||
|
if ((m_status & 0xf0) == 0x80)
|
||
|
{
|
||
|
struct
|
||
|
{
|
||
|
char m_note;
|
||
|
char m_velocity;
|
||
|
} note_off_event;
|
||
|
}
|
||
|
else if ((m_status & 0xf0) == 0x90)
|
||
|
{
|
||
|
struct
|
||
|
{
|
||
|
char m_note;
|
||
|
char m_velocity;
|
||
|
} note_on_event;
|
||
|
}
|
||
|
else if ((m_status & 0xf0) == 0xA0)
|
||
|
{
|
||
|
struct
|
||
|
{
|
||
|
char m_note;
|
||
|
char m_pressure;
|
||
|
} note_pressure_event;
|
||
|
}
|
||
|
else if ((m_status & 0xf0) == 0xB0)
|
||
|
{
|
||
|
struct
|
||
|
{
|
||
|
char m_controller;
|
||
|
char m_value;
|
||
|
} controller_event;
|
||
|
}
|
||
|
else if ((m_status & 0xf0) == 0xC0)
|
||
|
{
|
||
|
struct
|
||
|
{
|
||
|
char m_program;
|
||
|
} program_event;
|
||
|
}
|
||
|
else if ((m_status & 0xf0) == 0xD0)
|
||
|
{
|
||
|
struct
|
||
|
{
|
||
|
char m_pressure;
|
||
|
} channel_pressure_event;
|
||
|
}
|
||
|
else if ((m_status & 0xf0) == 0xE0)
|
||
|
{
|
||
|
struct
|
||
|
{
|
||
|
char m_lsb;
|
||
|
char m_msb;
|
||
|
} pitch_bend_event;
|
||
|
}
|
||
|
else if (m_status == -1)
|
||
|
{
|
||
|
struct
|
||
|
{
|
||
|
enum <char>
|
||
|
{
|
||
|
META_SEQUENCE_NUM = 0,
|
||
|
META_TEXT = 1,
|
||
|
META_COPYRIGHT = 2,
|
||
|
META_SEQUENCE_NAME = 3,
|
||
|
META_INSTRUMENT_NAME = 4,
|
||
|
META_LYRIC = 5,
|
||
|
META_MARKER = 6,
|
||
|
META_CUE_POINT = 7,
|
||
|
META_PROGRAM_NAME = 8,
|
||
|
META_DEVICE_NAME = 9,
|
||
|
META_MIDI_CHANNEL_PREFIX = 0x20,
|
||
|
META_MIDI_PORT = 0x21,
|
||
|
META_END_OF_TRACK = 0x2f,
|
||
|
META_TEMPO = 0x51,
|
||
|
META_SMPTE_OFFSET = 0x54,
|
||
|
META_TIME_SIGNATURE = 0x58,
|
||
|
META_KEY_SIGNATURE = 0x59,
|
||
|
META_SEQUENCER_EVENT = 0x7f
|
||
|
} m_type;
|
||
|
DeltaTime m_length;
|
||
|
if (m_type == META_SEQUENCE_NUM)
|
||
|
{
|
||
|
short m_seqNum;
|
||
|
}
|
||
|
else if (m_type == META_TEXT)
|
||
|
{
|
||
|
char m_text[m_length.total];
|
||
|
}
|
||
|
else if (m_type == META_COPYRIGHT)
|
||
|
{
|
||
|
char m_copyright[m_length.total];
|
||
|
}
|
||
|
else if (m_type == META_SEQUENCE_NAME)
|
||
|
{
|
||
|
char m_name[m_length.total];
|
||
|
}
|
||
|
else if (m_type == META_INSTRUMENT_NAME)
|
||
|
{
|
||
|
char m_name[m_length.total];
|
||
|
}
|
||
|
else if (m_type == META_LYRIC)
|
||
|
{
|
||
|
char m_lyric[m_length.total];
|
||
|
}
|
||
|
else if (m_type == META_MARKER)
|
||
|
{
|
||
|
char m_marker[m_length.total];
|
||
|
}
|
||
|
else if (m_type == META_CUE_POINT)
|
||
|
{
|
||
|
char m_cuePoint[m_length.total];
|
||
|
}
|
||
|
else if (m_type == META_PROGRAM_NAME)
|
||
|
{
|
||
|
char m_programName[m_length.total];
|
||
|
}
|
||
|
else if (m_type == META_DEVICE_NAME)
|
||
|
{
|
||
|
char m_deviceName[m_length.total];
|
||
|
}
|
||
|
else if (m_type == META_MIDI_CHANNEL_PREFIX)
|
||
|
{
|
||
|
char m_channelPrefix;
|
||
|
}
|
||
|
else if (m_type == META_MIDI_PORT)
|
||
|
{
|
||
|
char m_port;
|
||
|
}
|
||
|
else if (m_type == META_END_OF_TRACK)
|
||
|
{
|
||
|
}
|
||
|
else if (m_type == META_TEMPO)
|
||
|
{
|
||
|
uint m_usecPerQuarterNote : 24;
|
||
|
local uint m_bpm = 60000000 / m_usecPerQuarterNote;
|
||
|
FSeek(FTell() - 1);
|
||
|
}
|
||
|
else if (m_type == META_SMPTE_OFFSET)
|
||
|
{
|
||
|
char m_hours;
|
||
|
char m_mins;
|
||
|
char m_secs;
|
||
|
char m_fps;
|
||
|
char m_fracFrames;
|
||
|
}
|
||
|
else if (m_type == META_TIME_SIGNATURE)
|
||
|
{
|
||
|
char m_numerator;
|
||
|
char m_denominator;
|
||
|
char m_clocksPerClick;
|
||
|
char m_32ndPer4th;
|
||
|
}
|
||
|
else if (m_type == META_KEY_SIGNATURE)
|
||
|
{
|
||
|
char m_flatsSharps;
|
||
|
char m_majorMinor;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
char m_data[m_length.total];
|
||
|
}
|
||
|
} meta_event;
|
||
|
}
|
||
|
else if ((m_status & 0xf0) == 0xF0)
|
||
|
{
|
||
|
struct
|
||
|
{
|
||
|
DeltaTime m_length;
|
||
|
char m_message[m_length.total];
|
||
|
} sysex_event;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
struct MidiTrack
|
||
|
{
|
||
|
char m_magic[4] <format = hex>;
|
||
|
uint m_seclen;
|
||
|
local uint remaining = m_seclen;
|
||
|
while (remaining) {
|
||
|
MidiMessage message;
|
||
|
remaining -= sizeof(message);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
struct
|
||
|
{
|
||
|
MidiHeader header;
|
||
|
MidiTrack tracks[header.m_ntracks] <optimize=false>;
|
||
|
} file;
|