btparser/cparser/MIDITemplate.bt

242 lines
5.6 KiB
Plaintext
Raw Normal View History

/* 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;