summaryrefslogtreecommitdiffabout
path: root/include/midillo/message.h
blob: d6f0f36bf73f3258931da3a208d920463d7ed127 (plain)
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
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
#ifndef __MIDILLO_MESSAGE_H
#define __MIDILLO_MESSAGE_H

#include <istream>
#include <ostream>
#include <vector>

/**
 * @file
 * @brief MIDI message
 */

namespace midillo {
    using std::istream;
    using std::ostream;
    using std::vector;

    enum {
	// bits
	status_bit          = 0x80,
	status_event_bits   = 0xF0,
	status_channel_bits = 0x0F,
	status_system_bits  = 0xFF,
	// channel voice messages
	status_note_off                = 0x80,
	status_note_on                 = 0x90,
	status_polyphonic_key_pressure = 0xA0,
	status_aftertouch              = status_polyphonic_key_pressure,
	status_control_change          = 0xB0,
	status_program_change          = 0xC0,
	status_channel_pressure        = 0xD0,
	status_pitch_wheel_change      = 0xE0,
	status_system                  = 0xF0,
	// system common messages
	status_system_sysex                 = 0xF0,
	status_system_MTC_quarter_frame     = 0xF1,
	status_system_song_position_pointer = 0xF2,
	status_system_song_select           = 0xF3,
	status_system_tune_request          = 0xF6,
	status_system_end_of_sysex          = 0xF7,
	// system real-time messages
	status_system_timing_clock          = 0xF8,
	status_system_midi_clock	    = status_system_timing_clock,
	status_system_midi_tick		    = 0xF9,
	status_system_start                 = 0xFA,
	status_system_midi_start	    = status_system_start,
	status_system_continue              = 0xFB,
	status_system_midi_continue	    = status_system_continue,
	status_system_stop                  = 0xFC,
	status_system_midi_stop		    = status_system_stop,
	status_system_active_sense          = 0xFE,
	status_system_rest                  = 0xFF,
	status_system_reset                 = status_system_rest,
	// midi file specific
	status_system_meta                  = 0xFF
    };
    enum {
	// meta events
	meta_sequence_number = 0x00,
	meta_text            = 0x01,
	meta_copyright       = 0x02,
	meta_seq_track_name  = 0x03,
	meta_instrument      = 0x04,
	meta_lyric           = 0x05,
	meta_marker          = 0x06,
	meta_cue_point       = 0x07,
	meta_patch_name      = 0x08,
	meta_port_name       = 0x09,
	meta_EOT             = 0x2F,
	meta_tempo           = 0x51,
	meta_SMPTE_offset    = 0x54,
	meta_time_sig        = 0x58,
	meta_key_sig         = 0x59,
	meta_proprietary     = 0x7F,
	// obsolete meta events
	meta_midi_channel    = 0x20,
	meta_midi_port       = 0x21
    };

    /**
     * MIDI message container
     */
    class message_t {
	public:
	    /**
	     * MIDI status byte
	     */
	    int status;
	    /**
	     * MIDI meta event type
	     */
	    int meta_status;
	    typedef unsigned char byte_t;
	    typedef vector<byte_t> bytes_t;
	    /**
	     * MIDI message data -- content is message-specific
	     */
	    bytes_t data;

	    message_t()
		: status(-1) { }
	    message_t(const message_t& m)
		: status(m.status), meta_status(m.meta_status), data(m.data) { }

	    message_t& operator=(const message_t& m) {
		status = m.status;
		meta_status = m.meta_status;
		data = m.data;
		return *this;
	    }

	    /**
	     * Load MIDI message from the stream
	     * @param rs reference to the running status
	     * @param s input stream
	     */
	    void load(int& rs,istream& s);
	    /**
	     * Save MIDI message to the stream
	     * @param rs reference to the running status
	     * @param s output stream
	     */
	    void save(int& rs,ostream& s) const;
	    /**
	     * Calculate the amount of data that would be written to stream in
	     * case of save()
	     * @param rs reference to the running status
	     * @return the number of bytes
	     */
	    unsigned long calculate_save_size(int& rs) const;

	    /**
	     * Load data so that we have c bytes of data for the event
	     * @param s input stream
	     * @param c size of data needed for the event
	     */
	    void load_data(istream& s,int c);
	    /**
	     * Load sysex data from the stream
	     * @param s input stream
	     */
	    void load_sysex(istream& s);

	    /**
	     * Save data to the stream
	     * @param s output stream
	     */
	    void save_data(ostream& s) const;
	    /**
	     * Save data to the stream and verify if the amount of data is
	     * correct
	     * @param s output stream
	     * @param c data bytes count
	     */
	    void save_data(ostream& s,int c) const;
	    /**
	     * Save sysex data to the stream
	     * @param s output stream
	     */
	    void save_sysex(ostream& s) const;

	    /**
	     * See if the event is meta event
	     * @return true if yes
	     */
	    bool is_meta() const {
		return status==status_system_meta;
	    }
	    /**
	     * Check whether the event is a specific meta event
	     * @param meta meta event type
	     * @return true if yes
	     */
	    bool is_meta(int meta) const {
		return is_meta() && (meta_status==meta);
	    }

	    /**
	     * See if the event is system event
	     * @return true if yes
	     */
	    bool is_system() const {
		return (status&status_event_bits)==status_system && !is_meta();
	    }

	    /**
	     * Dump textual representation of midi message to stream
	     * @param s output stream
	     */
	    void dump(ostream& s) const;

    };

    inline ostream& operator<<(ostream& s,const message_t& m) {
	m.dump(s); return s;
    }

}

#endif /* __MIDILLO_MESSAGE_H */