summaryrefslogtreecommitdiff
path: root/libs/evoral/evoral/Event.hpp
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2016-11-06 22:04:35 -0500
committerDavid Robillard <d@drobilla.net>2016-12-03 15:18:21 -0500
commit08fffeffec10beb708610fd35eb9e7c35365d446 (patch)
treece9c8c77e6a926b4d8be90052c32945b7718bb4b /libs/evoral/evoral/Event.hpp
parent875b1367b2c4750ecd861424c57ed4bcc9c642d2 (diff)
Remove Evoral::MIDIEvent
It is slightly questionable whether type specific methods like velocity() belong on Event at all, these may be better off as free functions. However the code currently uses them as methods in many places, and it seems like a step in the right direction, since, for example, we might some day have events that have a velocity but aren't stored as MIDI messages (e.g. if Ardour uses an internal musical model that is more expressive). In any case, the former inheritance and plethora of sloppy casts is definitely not the right thing.
Diffstat (limited to 'libs/evoral/evoral/Event.hpp')
-rw-r--r--libs/evoral/evoral/Event.hpp119
1 files changed, 82 insertions, 37 deletions
diff --git a/libs/evoral/evoral/Event.hpp b/libs/evoral/evoral/Event.hpp
index cbb62e2f4c..526513b3fe 100644
--- a/libs/evoral/evoral/Event.hpp
+++ b/libs/evoral/evoral/Event.hpp
@@ -1,5 +1,5 @@
/* This file is part of Evoral.
- * Copyright (C) 2008 David Robillard <http://drobilla.net>
+ * Copyright (C) 2008-2016 David Robillard <http://drobilla.net>
* Copyright (C) 2000-2008 Paul Davis
*
* Evoral is free software; you can redistribute it and/or modify it under the
@@ -24,8 +24,9 @@
#include <sstream>
#include <stdint.h>
-#include "evoral/visibility.h"
+#include "evoral/midi_events.h"
#include "evoral/types.hpp"
+#include "evoral/visibility.h"
/** If this is not defined, all methods of MidiEvent are RT safe
* but MidiEvent will never deep copy and (depending on the scenario)
@@ -37,7 +38,7 @@ namespace Evoral {
LIBEVORAL_API event_id_t event_id_counter();
LIBEVORAL_API event_id_t next_event_id();
-LIBEVORAL_API void init_event_id_counter(event_id_t n);
+LIBEVORAL_API void init_event_id_counter(event_id_t n);
/** An event (much like a type generic jack_midi_event_t)
*
@@ -47,9 +48,9 @@ template<typename Time>
class LIBEVORAL_API Event {
public:
#ifdef EVORAL_EVENT_ALLOC
- Event (EventType type=0, Time time=Time(), uint32_t size=0, uint8_t* buf=NULL, bool alloc=false);
+ Event(EventType type=0, Time time=Time(), uint32_t size=0, uint8_t* buf=NULL, bool alloc=false);
- Event (EventType type, Time time, uint32_t size, const uint8_t* buf);
+ Event(EventType type, Time time, uint32_t size, const uint8_t* buf);
/** Copy \a copy.
*
@@ -59,33 +60,20 @@ public:
*/
Event(const Event& copy, bool alloc);
- ~Event();
+ ~Event();
- void assign (const Event& other);
+ void assign(const Event& other);
void set(const uint8_t* buf, uint32_t size, Time t);
inline bool operator==(const Event& other) const {
- if (_type != other._type)
+ if (_type != other._type ||
+ _nominal_time != other._nominal_time ||
+ _original_time != other._original_time ||
+ _size != other._size) {
return false;
-
- if (_nominal_time != other._nominal_time)
- return false;
-
- if (_original_time != other._original_time)
- return false;
-
- if (_size != other._size)
- return false;
-
- if (_buf == other._buf)
- return true;
-
- for (uint32_t i=0; i < _size; ++i)
- if (_buf[i] != other._buf[i])
- return false;
-
- return true;
+ }
+ return !memcmp(_buf, other._buf, _size);
}
inline bool operator!=(const Event& other) const { return ! operator==(other); }
@@ -127,10 +115,6 @@ public:
_buf = NULL;
}
-#else
-
- inline void set_buffer(uint8_t* buf) { _buf = buf; }
-
#endif // EVORAL_EVENT_ALLOC
inline EventType event_type() const { return _type; }
@@ -148,15 +132,76 @@ public:
inline event_id_t id() const { return _id; }
inline void set_id(event_id_t n) { _id = n; }
+ /* The following methods are type specific and only make sense for the
+ correct event type. It is the caller's responsibility to only call
+ methods which make sense for the given event type. Currently this means
+ they all only make sense for MIDI, but built-in support may be added for
+ other protocols in the future, or the internal representation may change
+ to be protocol agnostic. */
+
+ uint8_t type() const { return _buf[0] & 0xF0; }
+ uint8_t channel() const { return _buf[0] & 0x0F; }
+ bool is_note_on() const { return type() == MIDI_CMD_NOTE_ON; }
+ bool is_note_off() const { return type() == MIDI_CMD_NOTE_OFF; }
+ bool is_note() const { return is_note_on() || is_note_off(); }
+ bool is_poly_pressure() const { return type() == MIDI_CMD_NOTE_PRESSURE; }
+ bool is_channel_pressure() const { return type() == MIDI_CMD_CHANNEL_PRESSURE; }
+ bool is_cc() const { return type() == MIDI_CMD_CONTROL; }
+ bool is_pgm_change() const { return type() == MIDI_CMD_PGM_CHANGE; }
+ bool is_pitch_bender() const { return type() == MIDI_CMD_BENDER; }
+ bool is_channel_event() const { return (0x80 <= type()) && (type() <= 0xE0); }
+ bool is_smf_meta_event() const { return _buf[0] == 0xFF; }
+ bool is_sysex() const { return _buf[0] == 0xF0 || _buf[0] == 0xF7; }
+ bool is_spp() const { return _buf[0] == 0xF2 && size() == 1; }
+ bool is_mtc_quarter() const { return _buf[0] == 0xF1 && size() == 1; }
+ bool is_mtc_full() const { return (size() == 10 &&
+ _buf[0] == 0xF0 && _buf[1] == 0x7F &&
+ _buf[3] == 0x01 && _buf[4] == 0x01); }
+
+ uint8_t note() const { return _buf[1]; }
+ uint8_t velocity() const { return _buf[2]; }
+ uint8_t poly_note() const { return _buf[1]; }
+ uint8_t poly_pressure() const { return _buf[2]; }
+ uint8_t channel_pressure() const { return _buf[1]; }
+ uint8_t cc_number() const { return _buf[1]; }
+ uint8_t cc_value() const { return _buf[2]; }
+ uint8_t pgm_number() const { return _buf[1]; }
+ uint8_t pitch_bender_lsb() const { return _buf[1]; }
+ uint8_t pitch_bender_msb() const { return _buf[2]; }
+ uint16_t pitch_bender_value() const { return ((0x7F & _buf[2]) << 7 | (0x7F & _buf[1])); }
+
+ void set_channel(uint8_t channel) { _buf[0] = (0xF0 & _buf[0]) | (0x0F & channel); }
+ void set_type(uint8_t type) { _buf[0] = (0x0F & _buf[0]) | (0xF0 & type); }
+ void set_note(uint8_t num) { _buf[1] = num; }
+ void set_velocity(uint8_t val) { _buf[2] = val; }
+ void set_cc_number(uint8_t num) { _buf[1] = num; }
+ void set_cc_value(uint8_t val) { _buf[2] = val; }
+ void set_pgm_number(uint8_t num) { _buf[1] = num; }
+
+ uint16_t value() const {
+ switch (type()) {
+ case MIDI_CMD_CONTROL:
+ return cc_value();
+ case MIDI_CMD_BENDER:
+ return pitch_bender_value();
+ case MIDI_CMD_NOTE_PRESSURE:
+ return poly_pressure();
+ case MIDI_CMD_CHANNEL_PRESSURE:
+ return channel_pressure();
+ default:
+ return 0;
+ }
+ }
+
protected:
- EventType _type; /**< Type of event (application relative, NOT MIDI 'type') */
- Time _original_time; /**< Sample index (or beat time) at which event is valid */
- Time _nominal_time; /**< Quantized version of _time, used in preference */
- uint32_t _size; /**< Number of uint8_ts of data in \a buffer */
- uint8_t* _buf; /**< Raw MIDI data */
- event_id_t _id; /** UUID for each event, should probably be 64bit or at least unsigned */
+ EventType _type; ///< Type of event (application relative, NOT MIDI 'type')
+ Time _original_time; ///< Time stamp of event
+ Time _nominal_time; ///< Quantized version of _time, used in preference
+ uint32_t _size; ///< Size of buffer in bytes
+ uint8_t* _buf; ///< Event contents (e.g. raw MIDI data)
+ event_id_t _id; ///< Unique event ID
#ifdef EVORAL_EVENT_ALLOC
- bool _owns_buf; /**< Whether buffer is locally allocated */
+ bool _owns_buf; ///< Whether buffer is locally allocated
#endif
};