1 /* This file is part of Evoral.
2 * Copyright (C) 2008-2016 David Robillard <http://drobilla.net>
3 * Copyright (C) 2000-2008 Paul Davis
5 * Evoral is free software; you can redistribute it and/or modify it under the
6 * terms of the GNU General Public License as published by the Free Software
7 * Foundation; either version 2 of the License, or (at your option) any later
10 * Evoral is distributed in the hope that it will be useful, but WITHOUT ANY
11 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 #ifndef EVORAL_EVENT_HPP
20 #define EVORAL_EVENT_HPP
27 #include "evoral/midi_events.h"
28 #include "evoral/types.hpp"
29 #include "evoral/visibility.h"
31 /** If this is not defined, all methods of MidiEvent are RT safe
32 * but MidiEvent will never deep copy and (depending on the scenario)
33 * may not be usable in STL containers, signals, etc.
35 #define EVORAL_EVENT_ALLOC 1
39 LIBEVORAL_API event_id_t event_id_counter();
40 LIBEVORAL_API event_id_t next_event_id();
41 LIBEVORAL_API void init_event_id_counter(event_id_t n);
43 /** An event (much like a type generic jack_midi_event_t)
45 * Template parameter Time is the type of the time stamp used for this event.
47 template<typename Time>
48 class LIBEVORAL_API Event {
50 #ifdef EVORAL_EVENT_ALLOC
51 Event(EventType type=NO_EVENT, Time time=Time(), uint32_t size=0, uint8_t* buf=NULL, bool alloc=false);
53 Event(EventType type, Time time, uint32_t size, const uint8_t* buf);
57 * If \a alloc is true, the buffer will be copied and this method
58 * is NOT REALTIME SAFE. Otherwise both events share a buffer and
59 * memory management semantics are the caller's problem.
61 Event(const Event& copy, bool alloc);
65 void assign(const Event& other);
67 void set(const uint8_t* buf, uint32_t size, Time t);
69 inline bool operator==(const Event& other) const {
70 if (_type != other._type || _time != other._time || _size != other._size) {
73 return !memcmp(_buf, other._buf, _size);
76 inline bool operator!=(const Event& other) const { return ! operator==(other); }
78 inline bool owns_buffer() const { return _owns_buf; }
80 /** set event data (e.g. midi data)
81 * @param size number of bytes
82 * @param buf raw 8bit data
83 * @param own set to true if the buffer owns the data (copy, allocate/free) or false to reference previously allocated data.
85 inline void set_buffer(uint32_t size, uint8_t* buf, bool own) {
95 inline void realloc(uint32_t size) {
98 _buf = (uint8_t*) ::realloc(_buf, size);
100 _buf = (uint8_t*) ::malloc(size);
107 inline void clear() {
114 #endif // EVORAL_EVENT_ALLOC
116 inline EventType event_type() const { return _type; }
117 inline Time time() const { return _time; }
118 inline uint32_t size() const { return _size; }
119 inline const uint8_t* buffer() const { return _buf; }
120 inline uint8_t* buffer() { return _buf; }
122 inline void set_event_type(EventType t) { _type = t; }
124 inline void set_time(Time t) { _time = t; }
126 inline event_id_t id() const { return _id; }
127 inline void set_id(event_id_t n) { _id = n; }
129 /* The following methods are type specific and only make sense for the
130 correct event type. It is the caller's responsibility to only call
131 methods which make sense for the given event type. Currently this means
132 they all only make sense for MIDI, but built-in support may be added for
133 other protocols in the future, or the internal representation may change
134 to be protocol agnostic. */
136 uint8_t type() const { return _buf[0] & 0xF0; }
137 uint8_t channel() const { return _buf[0] & 0x0F; }
138 bool is_note_on() const { return type() == MIDI_CMD_NOTE_ON; }
139 bool is_note_off() const { return type() == MIDI_CMD_NOTE_OFF; }
140 bool is_note() const { return is_note_on() || is_note_off(); }
141 bool is_poly_pressure() const { return type() == MIDI_CMD_NOTE_PRESSURE; }
142 bool is_channel_pressure() const { return type() == MIDI_CMD_CHANNEL_PRESSURE; }
143 bool is_cc() const { return type() == MIDI_CMD_CONTROL; }
144 bool is_pgm_change() const { return type() == MIDI_CMD_PGM_CHANGE; }
145 bool is_pitch_bender() const { return type() == MIDI_CMD_BENDER; }
146 bool is_channel_event() const { return (0x80 <= type()) && (type() <= 0xE0); }
147 bool is_smf_meta_event() const { return _buf[0] == 0xFF; }
148 bool is_sysex() const { return _buf[0] == 0xF0 || _buf[0] == 0xF7; }
149 bool is_spp() const { return _buf[0] == 0xF2 && size() == 1; }
150 bool is_mtc_quarter() const { return _buf[0] == 0xF1 && size() == 1; }
151 bool is_mtc_full() const { return (size() == 10 &&
152 _buf[0] == 0xF0 && _buf[1] == 0x7F &&
153 _buf[3] == 0x01 && _buf[4] == 0x01); }
155 uint8_t note() const { return _buf[1]; }
156 uint8_t velocity() const { return _buf[2]; }
157 uint8_t poly_note() const { return _buf[1]; }
158 uint8_t poly_pressure() const { return _buf[2]; }
159 uint8_t channel_pressure() const { return _buf[1]; }
160 uint8_t cc_number() const { return _buf[1]; }
161 uint8_t cc_value() const { return _buf[2]; }
162 uint8_t pgm_number() const { return _buf[1]; }
163 uint8_t pitch_bender_lsb() const { return _buf[1]; }
164 uint8_t pitch_bender_msb() const { return _buf[2]; }
165 uint16_t pitch_bender_value() const { return ((0x7F & _buf[2]) << 7 | (0x7F & _buf[1])); }
167 void set_channel(uint8_t channel) { _buf[0] = (0xF0 & _buf[0]) | (0x0F & channel); }
168 void set_type(uint8_t type) { _buf[0] = (0x0F & _buf[0]) | (0xF0 & type); }
169 void set_note(uint8_t num) { _buf[1] = num; }
170 void set_velocity(uint8_t val) { _buf[2] = val; }
171 void set_cc_number(uint8_t num) { _buf[1] = num; }
172 void set_cc_value(uint8_t val) { _buf[2] = val; }
173 void set_pgm_number(uint8_t num) { _buf[1] = num; }
175 uint16_t value() const {
177 case MIDI_CMD_CONTROL:
179 case MIDI_CMD_BENDER:
180 return pitch_bender_value();
181 case MIDI_CMD_NOTE_PRESSURE:
182 return poly_pressure();
183 case MIDI_CMD_CHANNEL_PRESSURE:
184 return channel_pressure();
185 case MIDI_CMD_PGM_CHANGE:
193 EventType _type; ///< Type of event (application relative, NOT MIDI 'type')
194 Time _time; ///< Time stamp of event
195 uint32_t _size; ///< Size of buffer in bytes
196 uint8_t* _buf; ///< Event contents (e.g. raw MIDI data)
197 event_id_t _id; ///< Unique event ID
198 #ifdef EVORAL_EVENT_ALLOC
199 bool _owns_buf; ///< Whether buffer is locally allocated
203 template<typename Time>
204 /*LIBEVORAL_API*/ std::ostream& operator<<(std::ostream& o, const Evoral::Event<Time>& ev) {
205 o << "Event #" << ev.id() << " type = " << ev.event_type() << " @ " << ev.time();
207 for (uint32_t n = 0; n < ev.size(); ++n) {
208 o << ' ' << (int) ev.buffer()[n];
214 } // namespace Evoral
216 #endif // EVORAL_EVENT_HPP