CorsixTH engine (the C++ part)
Open source implementation of Theme Hospital
Loading...
Searching...
No Matches
xmi2mid.h
Go to the documentation of this file.
1/*
2Copyright (c) 2009 Peter "Corsix" Cawley
3
4Permission is hereby granted, free of charge, to any person obtaining a copy of
5this software and associated documentation files (the "Software"), to deal in
6the Software without restriction, including without limitation the rights to
7use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
8of the Software, and to permit persons to whom the Software is furnished to do
9so, subject to the following conditions:
10
11The above copyright notice and this permission notice shall be included in all
12copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20SOFTWARE.
21*/
22
23#ifndef CORSIX_TH_XMI2MID_H_
24#define CORSIX_TH_XMI2MID_H_
25#include "config.h"
26
27#include <vector>
28
29// MIDI Events are from the MIDI 1.0 Spec
30// MIDI Meta Events are from the Standard MIDI File Spec 1.0
31// Both specs are available from the MIDI Association website:
32// https://www.midi.org
33
34constexpr uint8_t midi_event_note_off = 0x80;
35constexpr uint8_t midi_event_note_on = 0x90;
36constexpr uint8_t midi_event_poly_key_pressure = 0xA0;
37constexpr uint8_t midi_event_control_change = 0xB0;
38constexpr uint8_t midi_event_program_change = 0xC0;
39constexpr uint8_t midi_event_channel_pressure = 0xD0;
40constexpr uint8_t midi_event_pitch_bend = 0xE0;
41
42constexpr uint8_t midi_event_sysex = 0xF0;
43constexpr uint8_t midi_event_end_of_sysex = 0xF7;
44constexpr uint8_t midi_event_meta = 0xFF;
45
46constexpr uint8_t midi_meta_event_end_of_track = 0x2F;
47constexpr uint8_t midi_meta_event_set_tempo = 0x51;
48
49constexpr uint8_t midi_control_code_volume = 7;
50
51constexpr uint8_t midi_channel_code_all_notes_off = 123;
52constexpr uint8_t midi_channel_code_all_sound_off = 120;
54
55namespace {
56
57// Multiply the time duration of XMI events and the tempo by this factor.
58// The idea is to reduce the rounding errors that occur when converting from
59// XMI's 120Hz timing to MIDI's microseconds per quarter note timing.
60// Larger values reduce rounding errors but also increase the chance of hitting
61// the maximum MIDI division of 0x7FFF (32767).
62//
63// Experimentally 100 results in a division of 10000 for the fastest tempo in
64// Theme Hospital. Many but not all tracks have exact timing with a value of 1.
65constexpr int time_multiplier = 100;
66
67} // namespace
68
69// There are 120 ticks per second in XMI timing (which reduces to 3 / 25000us).
70constexpr double xmi_ticks_per_microsecond = (3.0 * time_multiplier) / 25000.0;
71constexpr double xmi_microseconds_per_tick = 25000.0 / (3.0 * time_multiplier);
72
73struct midi_token {
74 int time;
75 std::vector<uint8_t> buffer{};
76 uint8_t type;
77 uint8_t data{0};
78
79 midi_token(int time, uint8_t type) : time(time), type(type) {}
80};
81
82bool operator<(const midi_token& oLeft, const midi_token& oRight);
83
84using midi_token_list = std::vector<midi_token>;
85
87 size_t xmi_length, uint32_t& iTempo);
88
89uint8_t* transcode_xmi_to_midi(const unsigned char* xmi_data, size_t xmi_length,
90 size_t* midi_length);
91
92#endif // CORSIX_TH_XMI2MID_H_
Definition xmi2mid.h:73
uint8_t type
Definition xmi2mid.h:76
std::vector< uint8_t > buffer
Definition xmi2mid.h:75
uint8_t data
Definition xmi2mid.h:77
int time
Definition xmi2mid.h:74
midi_token(int time, uint8_t type)
Definition xmi2mid.h:79
constexpr uint8_t midi_event_program_change
Definition xmi2mid.h:38
constexpr uint8_t midi_event_note_off
Definition xmi2mid.h:34
constexpr uint8_t midi_channel_code_all_sound_off
Definition xmi2mid.h:52
constexpr uint8_t midi_event_note_on
Definition xmi2mid.h:35
constexpr uint8_t midi_control_code_volume
Definition xmi2mid.h:49
std::vector< midi_token > midi_token_list
Definition xmi2mid.h:84
constexpr double xmi_microseconds_per_tick
Definition xmi2mid.h:71
bool operator<(const midi_token &oLeft, const midi_token &oRight)
Definition xmi2mid.cpp:41
constexpr uint8_t midi_channel_code_reset_controllers
Definition xmi2mid.h:53
constexpr double xmi_ticks_per_microsecond
Definition xmi2mid.h:70
constexpr uint8_t midi_event_control_change
Definition xmi2mid.h:37
constexpr uint8_t midi_channel_code_all_notes_off
Definition xmi2mid.h:51
constexpr uint8_t midi_event_channel_pressure
Definition xmi2mid.h:39
uint8_t * transcode_xmi_to_midi(const unsigned char *xmi_data, size_t xmi_length, size_t *midi_length)
Definition xmi2mid.cpp:327
constexpr uint8_t midi_meta_event_end_of_track
Definition xmi2mid.h:46
constexpr uint8_t midi_event_sysex
Definition xmi2mid.h:42
constexpr uint8_t midi_event_meta
Definition xmi2mid.h:44
constexpr uint8_t midi_meta_event_set_tempo
Definition xmi2mid.h:47
constexpr uint8_t midi_event_end_of_sysex
Definition xmi2mid.h:43
midi_token_list xmi_to_midi_token_list(const unsigned char *xmi_data, size_t xmi_length, uint32_t &iTempo)
Definition xmi2mid.cpp:208
constexpr uint8_t midi_event_pitch_bend
Definition xmi2mid.h:40
constexpr uint8_t midi_event_poly_key_pressure
Definition xmi2mid.h:36