Zack Buhman 86d12c37ed midi: add generator
This adds both a midi generator and a midi type 1 simulator.

While I would have preferred to use an existing tool for this, I found
that timidity++ does not emit pitch wheel events correctly, and I
don't know of another widely-distributed tool that does midi-to-midi
format conversion.

The c++ and python versions were co-developed. I wrote one to test the
other. There is more cleanup to do, but `roundtrip.cpp` produces a
valid type 0 midi file given a type 1 or type 0 midi file as input.
2023-07-01 00:15:53 +00:00

137 lines
2.1 KiB
C++

#pragma once
#include <cstdint>
namespace midi {
struct division_t {
enum struct type_t : uint8_t {
time_code,
metrical,
} type;
union {
struct {
int8_t smpte;
uint8_t ticks_per_frame;
} time_code;
struct {
uint16_t ticks_per_quarter_note;
} metrical;
};
};
struct header_t {
enum struct format_t : uint8_t {
_0,
_1,
_2,
} format;
uint16_t ntrks;
division_t division;
};
struct midi_event_t {
struct note_off_t {
uint8_t channel;
uint8_t note;
uint8_t velocity;
};
struct note_on_t {
uint8_t channel;
uint8_t note;
uint8_t velocity;
};
struct polyphonic_key_pressure_t {
uint8_t channel;
uint8_t note;
uint8_t pressure;
};
struct control_change_t {
uint8_t channel;
uint8_t control;
uint8_t value;
};
struct program_change_t {
uint8_t channel;
uint8_t program;
};
struct channel_pressure_t {
uint8_t channel;
uint8_t pressure;
};
struct pitch_bend_change_t {
uint8_t channel;
uint8_t lsb;
uint8_t msb;
};
struct channel_mode_t {
uint8_t channel;
uint8_t controller;
uint8_t value;
};
enum struct type_t {
note_off,
note_on,
polyphonic_key_pressure,
control_change,
program_change,
channel_pressure,
pitch_bend_change,
channel_mode,
} type;
union event_t {
note_off_t note_off;
note_on_t note_on;
polyphonic_key_pressure_t polyphonic_key_pressure;
control_change_t control_change;
program_change_t program_change;
channel_pressure_t channel_pressure;
pitch_bend_change_t pitch_bend_change;
channel_mode_t channel_mode;
} data;
};
struct sysex_event_t {
const uint8_t * data;
uint32_t length;
uint8_t tag;
};
struct meta_event_t {
const uint8_t * data;
uint32_t length;
uint8_t type;
};
struct event_t {
enum struct type_t {
midi,
sysex,
meta,
} type;
union _event_t {
midi_event_t midi;
sysex_event_t sysex;
meta_event_t meta;
} event;
};
struct mtrk_event_t {
uint32_t delta_time;
event_t event;
};
struct track_t {
uint32_t length;
};
} // midi