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.
137 lines
2.1 KiB
C++
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
|