-
Notifications
You must be signed in to change notification settings - Fork 0
/
MidiEvent.cpp
189 lines (154 loc) · 5.31 KB
/
MidiEvent.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
//
// Created by madsy on 18.03.17.
//
#include <stdexcept>
#include <cassert>
#include <fstream>
#include "MidiEvent.h"
MidiEvent::MidiEventType MidiEvent::getEventType(unsigned char event) {
unsigned int highest_nibble = (event >> 4u) & 0xFu;
unsigned int lowest_nibble = event & 0xFu;
//MSB must be set
if(!(highest_nibble & 0x8)){
return MidiEvent::MidiEventType::EVT_RUNNING_STATUS;
}
if(highest_nibble < 0xF){
return MidiEvent::MidiEventType::EVT_CHANNEL;
} else { //highest_nibble == 0xF
if(lowest_nibble == 0xF){
return MidiEvent::MidiEventType ::EVT_META;
} else if(lowest_nibble < 0x8){
return MidiEvent::MidiEventType ::EVT_SYSCOMMON;
} else {
return MidiEvent::MidiEventType ::EVT_SYSRT;
}
}
}
MidiEvent::ChannelEventType MidiEvent::getChannelEventType(unsigned char event) {
unsigned int code = (event >> 4) & ~0x8u;
//Should not be 0x7 here. That would be a system event with prefix 0xFx
assert(code != 0x7);
return (MidiEvent::ChannelEventType)code;
}
MidiEvent::SystemCommonEventType MidiEvent::getSystemCommonEventType(unsigned char event) {
unsigned int code = event & 0xFu;
/* should not be greater than 0x7 here*/
assert(code < 0x8);
if(code == 0x1 || code == 0x4 || code == 0x5){
throw std::runtime_error("Undefined system common event");
}
return (MidiEvent::SystemCommonEventType)code;
}
MidiEvent::SystemRealtimeEventType MidiEvent::getSystemRealtimeEventType(unsigned char event) {
unsigned int code = event & 0xFu;
/* must be greater than 0x7 here */
assert(code >= 0x8);
if(code == 0x9 || code == 0xD){
throw std::runtime_error("Undefined system realtime event");
}
return (MidiEvent::SystemRealtimeEventType)code;
}
MidiEvent::MetaEventType MidiEvent::getMetaEventType(unsigned int& bytesread, std::ifstream& strm) {
MidiEvent::MetaEventType type = MidiEvent::MetaEventType::EVT_COPYRIGHT;
unsigned char byte1, byte2, byte3;
byte1 = byte2 = byte3 = 0;
strm.read((char*)&byte1, 1);
bytesread++;
switch (byte1) {
case 0x0:{
strm.read((char*)&byte1, 1);
if(byte1 != 0){ throw std::runtime_error("Invalid Meta Event"); }
strm.read((char*)&byte1, 1);
if(byte1 != 2){ throw std::runtime_error("Invalid Meta Event"); }
type = MidiEvent::MetaEventType::EVT_SEQUENCE_NUMBER;
bytesread += 2;
break;
}
case 0x1:
type = MidiEvent::MetaEventType::EVT_TEXT;
break;
case 0x2:
type = MidiEvent::MetaEventType::EVT_COPYRIGHT;
break;
case 0x3:
type = MidiEvent::MetaEventType::EVT_TRACK_NAME;
break;
case 0x4:
type = MidiEvent::MetaEventType::EVT_INSTRUMENT_NAME;
break;
case 0x5:
type = MidiEvent::MetaEventType::EVT_LYRICS;
break;
case 0x6:
type = MidiEvent::MetaEventType::EVT_MARKER;
break;
case 0x7:
type = MidiEvent::MetaEventType::EVT_CUE_POINT;
break;
case 0x20:{
strm.read((char*)&byte1, 1);
if(byte1 != 0x1){ throw std::runtime_error("Invalid Meta Event"); }
type = MidiEvent::MetaEventType::EVT_MIDI_CHANNEL_PREFIX;
bytesread += 1;
break;
}
case 0x2F:{
strm.read((char*)&byte1, 1);
if(byte1 != 0x0){ throw std::runtime_error("Invalid Meta Event"); }
type = MidiEvent::MetaEventType::EVT_END_OF_TRACK;
bytesread += 1;
break;
}
case 0x51:{
strm.read((char*)&byte1, 1);
if(byte1 != 0x3){ throw std::runtime_error("Invalid Meta Event"); }
type = MidiEvent::MetaEventType::EVT_SET_TEMPO;
bytesread += 1;
break;
}
case 0x54:{
strm.read((char*)&byte1, 1);
if(byte1 != 0x5){ throw std::runtime_error("Invalid Meta Event"); }
type = MidiEvent::MetaEventType::EVT_SMPTE_OFFSET;
bytesread += 1;
break;
}
case 0x58:{
strm.read((char*)&byte1, 1);
if(byte1 != 0x4){ throw std::runtime_error("Invalid Meta Event"); }
type = MidiEvent::MetaEventType::EVT_TIME_SIGNATURE;
bytesread += 1;
break;
}
case 0x59:{
strm.read((char*)&byte1, 1);
if(byte1 != 0x2){ throw std::runtime_error("Invalid Meta Event"); }
type = MidiEvent::MetaEventType::EVT_KEY_SIGNATURE;
bytesread += 1;
break;
}
case 0x7F:{
type = MidiEvent::MetaEventType::EVT_SEQUENCER_SPECIFIC;
break;
}
default:
throw std::runtime_error("Invalid Meta Event");
}
return type;
}
MidiEvent::MidiEvent() {
}
unsigned int MidiEvent::getTimestamp() const {
return pTick;
}
void MidiEvent::print() {
printf("class %s event\n", typeid(this).name());
}
MidiEvent::MidiEvent(unsigned int timestamp) : pTick(timestamp){
}
unsigned int MidiEvent::pGetChannelIndex() const {
return 0;
}
unsigned int MidiEvent::getChannelIndex() const {
return pGetChannelIndex();
}