1 #pragma once
2 
SwapByteOrderInt(uint32_t val)3 constexpr uint32_t SwapByteOrderInt(uint32_t val)
4 {
5 	return (val >> 24) |
6 		((val << 8) & 0x00FF0000) |
7 		((val >> 8) & 0x0000FF00) |
8 		(val << 24);
9 }
10 
SwapByteOrderShort(uint16_t val)11 constexpr uint16_t SwapByteOrderShort(uint16_t val)
12 {
13 	return static_cast<uint16_t>((val >> 8) | (val << 8));
14 }
15 
16 #pragma pack(push)
17 #pragma pack(1)
18 struct riff_block
19 {
20 	uint32_t TkStart;
21 	uint32_t CbBuffer;
22 	char AData[4];
23 };
24 
25 struct riff_data
26 {
27 	uint32_t Data;
28 	uint32_t DataSize;
29 	uint32_t BlocksPerChunk;
30 	riff_block Blocks[1];
31 };
32 
33 struct riff_header
34 {
35 	uint32_t Riff;
36 	uint32_t FileSize;
37 	uint32_t Mids;
38 	uint32_t Fmt;
39 	uint32_t FmtSize;
40 	uint32_t dwTimeFormat;
41 	uint32_t cbMaxBuffer;
42 	uint32_t dwFlags;
43 	riff_data Data;
44 };
45 
46 struct midi_event
47 {
48 	uint32_t iTicks;
49 	uint32_t iEvent;
50 };
51 
52 struct midi_header
53 {
midi_headermidi_header54 	explicit midi_header(uint16_t tickdiv)
55 		: tickdiv(tickdiv)
56 	{
57 	}
58 
59 	const char MThd[4]{'M', 'T', 'h', 'd'};
60 	const uint32_t chunklen = SwapByteOrderInt(6);
61 	const int16_t format = SwapByteOrderShort(0);
62 	const uint16_t ntracks = SwapByteOrderShort(1);
63 	uint16_t tickdiv;
64 };
65 
66 struct midi_track
67 {
midi_trackmidi_track68 	explicit midi_track(uint32_t chunklen)
69 		: chunklen(chunklen)
70 	{
71 	}
72 
73 	const char MTrk[4]{'M', 'T', 'r', 'k'};
74 	uint32_t chunklen;
75 };
76 
77 static_assert(sizeof(riff_block) == 0xC, "Wrong size of riff_block");
78 static_assert(sizeof(riff_data) == 0x18, "Wrong size of riff_data");
79 static_assert(sizeof(riff_header) == 0x38, "Wrong size of riff_header");
80 static_assert(sizeof(midi_event) == 8, "Wrong size of midi_event2");
81 static_assert(sizeof(midi_header) == 14, "Wrong size of midi_header");
82 static_assert(sizeof(midi_track) == 8, "Wrong size of midi_track");
83 
84 #pragma pack(pop)
85 
86 class midi
87 {
88 public:
89 	static int play_pb_theme();
90 	static int music_stop();
91 	static int music_init();
92 	static void music_shutdown();
93 private:
94 	static std::vector<Mix_Music*> LoadedTracks;
95 	static Mix_Music *track1, *track2, *track3, *active_track, *NextTrack;
96 	static bool SetNextTrackFlag;
97 	static Mix_Music* load_track(std::string fileName);
98 	static bool play_track(Mix_Music* midi);
99 	static std::vector<uint8_t>* MdsToMidi(std::string file);
100 };
101