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.
This commit is contained in:
David Robillard 2016-11-06 22:04:35 -05:00
parent 875b1367b2
commit 08fffeffec
33 changed files with 174 additions and 250 deletions

View File

@ -41,7 +41,7 @@
#include "ardour/session.h"
#include "evoral/Parameter.hpp"
#include "evoral/MIDIEvent.hpp"
#include "evoral/Event.hpp"
#include "evoral/Control.hpp"
#include "evoral/midi_util.h"
@ -1293,14 +1293,9 @@ MidiRegionView::display_sysexes()
if (!UIConfiguration::instance().get_never_display_periodic_midi()) {
for (MidiModel::SysExes::const_iterator i = _model->sysexes().begin(); i != _model->sysexes().end(); ++i) {
const boost::shared_ptr<const Evoral::MIDIEvent<Evoral::Beats> > mev =
boost::static_pointer_cast<const Evoral::MIDIEvent<Evoral::Beats> > (*i);
if (mev) {
if (mev->is_spp() || mev->is_mtc_quarter() || mev->is_mtc_full()) {
have_periodic_system_messages = true;
break;
}
if ((*i)->is_spp() || (*i)->is_mtc_quarter() || (*i)->is_mtc_full()) {
have_periodic_system_messages = true;
break;
}
}
@ -1325,17 +1320,11 @@ MidiRegionView::display_sysexes()
}
for (MidiModel::SysExes::const_iterator i = _model->sysexes().begin(); i != _model->sysexes().end(); ++i) {
const boost::shared_ptr<const Evoral::MIDIEvent<Evoral::Beats> > mev =
boost::static_pointer_cast<const Evoral::MIDIEvent<Evoral::Beats> > (*i);
Evoral::Beats time = (*i)->time();
if (mev) {
if (mev->is_spp() || mev->is_mtc_quarter() || mev->is_mtc_full()) {
if (!display_periodic_messages) {
continue;
}
if ((*i)->is_spp() || (*i)->is_mtc_quarter() || (*i)->is_mtc_full()) {
if (!display_periodic_messages) {
continue;
}
}
@ -3927,7 +3916,7 @@ MidiRegionView::data_recorded (boost::weak_ptr<MidiSource> w)
framepos_t back = max_framepos;
for (MidiBuffer::iterator i = buf->begin(); i != buf->end(); ++i) {
Evoral::MIDIEvent<MidiBuffer::TimeType> const ev (*i, false);
const Evoral::Event<MidiBuffer::TimeType>& ev = *i;
if (ev.is_channel_event()) {
if (get_channel_mode() == FilterChannels) {

View File

@ -70,6 +70,13 @@ Amp::configure_io (ChanCount in, ChanCount out)
return Processor::configure_io (in, out);
}
static void
scale_midi_velocity(Evoral::Event<MidiBuffer::TimeType>& ev, float factor)
{
factor = std::max(factor, 0.0f);
ev.set_velocity(std::min(127L, lrintf(ev.velocity() * factor)));
}
void
Amp::run (BufferSet& bufs, framepos_t /*start_frame*/, framepos_t /*end_frame*/, double /*speed*/, pframes_t nframes, bool)
{
@ -88,10 +95,10 @@ Amp::run (BufferSet& bufs, framepos_t /*start_frame*/, framepos_t /*end_frame*/,
for (BufferSet::midi_iterator i = bufs.midi_begin(); i != bufs.midi_end(); ++i) {
MidiBuffer& mb (*i);
for (MidiBuffer::iterator m = mb.begin(); m != mb.end(); ++m) {
Evoral::MIDIEvent<MidiBuffer::TimeType> ev = *m;
Evoral::Event<MidiBuffer::TimeType> ev = *m;
if (ev.is_note_on()) {
assert(ev.time() >= 0 && ev.time() < nframes);
ev.scale_velocity (fabsf (gab[ev.time()]));
scale_midi_velocity (ev, fabsf (gab[ev.time()]));
}
}
}
@ -135,9 +142,9 @@ Amp::run (BufferSet& bufs, framepos_t /*start_frame*/, framepos_t /*end_frame*/,
MidiBuffer& mb (*i);
for (MidiBuffer::iterator m = mb.begin(); m != mb.end(); ++m) {
Evoral::MIDIEvent<MidiBuffer::TimeType> ev = *m;
Evoral::Event<MidiBuffer::TimeType> ev = *m;
if (ev.is_note_on()) {
ev.scale_velocity (fabsf (_current_gain));
scale_midi_velocity (ev, fabsf (_current_gain));
}
}
}
@ -186,11 +193,11 @@ Amp::apply_gain (BufferSet& bufs, framecnt_t sample_rate, framecnt_t nframes, ga
MidiBuffer& mb (*i);
for (MidiBuffer::iterator m = mb.begin(); m != mb.end(); ++m) {
Evoral::MIDIEvent<MidiBuffer::TimeType> ev = *m;
Evoral::Event<MidiBuffer::TimeType> ev = *m;
if (ev.is_note_on()) {
const gain_t scale = delta * (ev.time()/(double) nframes);
ev.scale_velocity (fabsf (initial+scale));
scale_midi_velocity (ev, fabsf (initial + scale));
}
}
}
@ -304,7 +311,7 @@ Amp::apply_simple_gain (BufferSet& bufs, framecnt_t nframes, gain_t target, bool
MidiBuffer& mb (*i);
for (MidiBuffer::iterator m = mb.begin(); m != mb.end(); ++m) {
Evoral::MIDIEvent<MidiBuffer::TimeType> ev = *m;
Evoral::Event<MidiBuffer::TimeType> ev = *m;
if (ev.is_note_on()) {
ev.set_velocity (0);
}
@ -324,9 +331,9 @@ Amp::apply_simple_gain (BufferSet& bufs, framecnt_t nframes, gain_t target, bool
MidiBuffer& mb (*i);
for (MidiBuffer::iterator m = mb.begin(); m != mb.end(); ++m) {
Evoral::MIDIEvent<MidiBuffer::TimeType> ev = *m;
Evoral::Event<MidiBuffer::TimeType> ev = *m;
if (ev.is_note_on()) {
ev.scale_velocity (fabsf (target));
scale_midi_velocity(ev, fabsf (target));
}
}
}

View File

@ -31,7 +31,7 @@
#include "ardour/types.h"
#if defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT
#include "evoral/MIDIEvent.hpp"
#include "evoral/Event.hpp"
struct _VstEvents;
typedef struct _VstEvents VstEvents;
struct _VstMidiEvent;
@ -196,7 +196,7 @@ private:
~VSTBuffer ();
void clear ();
void push_back (Evoral::MIDIEvent<framepos_t> const &);
void push_back (Evoral::Event<framepos_t> const &);
VstEvents* events () const {
return _events;
}

View File

@ -47,7 +47,7 @@ public:
void copy(const MidiBuffer& copy);
void copy(MidiBuffer const * const);
bool push_back(const Evoral::MIDIEvent<TimeType>& event);
bool push_back(const Evoral::Event<TimeType>& event);
bool push_back(TimeType time, size_t size, const uint8_t* data);
uint8_t* reserve(TimeType time, size_t size);
@ -56,7 +56,7 @@ public:
size_t size() const { return _size; }
bool empty() const { return _size == 0; }
bool insert_event(const Evoral::MIDIEvent<TimeType>& event);
bool insert_event(const Evoral::Event<TimeType>& event);
bool merge_in_place(const MidiBuffer &other);
/** EventSink interface for non-RT use (export, bounce). */
@ -122,8 +122,8 @@ public:
size_t offset;
};
typedef iterator_base< MidiBuffer, Evoral::MIDIEvent<TimeType> > iterator;
typedef iterator_base< const MidiBuffer, const Evoral::MIDIEvent<TimeType> > const_iterator;
typedef iterator_base< MidiBuffer, Evoral::Event<TimeType> > iterator;
typedef iterator_base< const MidiBuffer, const Evoral::Event<TimeType> > const_iterator;
iterator begin() { return iterator(*this, 0); }
iterator end() { return iterator(*this, _size); }
@ -176,8 +176,8 @@ public:
static bool second_simultaneous_midi_byte_is_first (uint8_t, uint8_t);
private:
friend class iterator_base< MidiBuffer, Evoral::MIDIEvent<TimeType> >;
friend class iterator_base< const MidiBuffer, const Evoral::MIDIEvent<TimeType> >;
friend class iterator_base< MidiBuffer, Evoral::Event<TimeType> >;
friend class iterator_base< const MidiBuffer, const Evoral::Event<TimeType> >;
uint8_t* _data; ///< timestamp, event, timestamp, event, ...
pframes_t _size;

View File

@ -241,14 +241,14 @@ AsyncMIDIPort::write (const MIDI::byte * msg, size_t msglen, MIDI::timestamp_t t
necessary.
*/
if (!vec.buf[0]->owns_buffer()) {
vec.buf[0]->set_buffer (0, 0, true);
}
vec.buf[0]->set_buffer (0, 0, true);
}
vec.buf[0]->set (msg, msglen, timestamp);
} else {
/* see comment in previous branch of if() statement */
if (!vec.buf[1]->owns_buffer()) {
vec.buf[1]->set_buffer (0, 0, true);
}
vec.buf[1]->set_buffer (0, 0, true);
}
vec.buf[1]->set (msg, msglen, timestamp);
}

View File

@ -1686,7 +1686,7 @@ AUPlugin::connect_and_run (BufferSet& bufs,
/* one MIDI port/buffer only */
MidiBuffer& m = bufs.get_midi (i);
for (MidiBuffer::iterator i = m.begin(); i != m.end(); ++i) {
Evoral::MIDIEvent<framepos_t> ev (*i);
Evoral::Event<framepos_t> ev (*i);
if (ev.is_channel_event()) {
const uint8_t* b = ev.buffer();
DEBUG_TRACE (DEBUG::AudioUnits, string_compose ("%1: MIDI event %2\n", name(), ev));

View File

@ -401,7 +401,7 @@ BufferSet::VSTBuffer::clear ()
}
void
BufferSet::VSTBuffer::push_back (Evoral::MIDIEvent<framepos_t> const & ev)
BufferSet::VSTBuffer::push_back (Evoral::Event<framepos_t> const & ev)
{
if (ev.size() > 3) {
/* XXX: this will silently drop MIDI messages longer than 3 bytes, so

View File

@ -234,7 +234,7 @@ DelayLine::run (BufferSet& bufs, framepos_t /* start_frame */, framepos_t /* end
// move events from dly-buffer into current-buffer until nsamples
// and remove them from the dly-buffer
for (MidiBuffer::iterator m = dly->begin(); m != dly->end();) {
const Evoral::MIDIEvent<MidiBuffer::TimeType> ev (*m, false);
const Evoral::Event<MidiBuffer::TimeType> ev (*m, false);
if (ev.time() >= nsamples) {
break;
}
@ -250,7 +250,7 @@ DelayLine::run (BufferSet& bufs, framepos_t /* start_frame */, framepos_t /* end
// move events after nsamples from current-buffer into dly-buffer
// and trim current-buffer after nsamples
for (MidiBuffer::iterator m = mb.begin(); m != mb.end();) {
const Evoral::MIDIEvent<MidiBuffer::TimeType> ev (*m, false);
const Evoral::Event<MidiBuffer::TimeType> ev (*m, false);
if (ev.time() < nsamples) {
++m;
continue;

View File

@ -447,7 +447,7 @@ LuaBindings::common (lua_State* L)
.addFunction ("size", &Evoral::Event<framepos_t>::size)
.addFunction ("set_buffer", &Evoral::Event<framepos_t>::set_buffer)
.addFunction ("buffer", (uint8_t*(Evoral::Event<framepos_t>::*)())&Evoral::Event<framepos_t>::buffer)
.addFunction ("time", (framepos_t (Evoral::Event<framepos_t>::*)())&Evoral::MIDIEvent<framepos_t>::time)
.addFunction ("time", (framepos_t (Evoral::Event<framepos_t>::*)())&Evoral::Event<framepos_t>::time)
.endClass ()
.beginClass <Evoral::Beats> ("Beats")
@ -1908,10 +1908,10 @@ LuaBindings::dsp (lua_State* L)
.addFunction ("empty", &MidiBuffer::empty)
.addFunction ("resize", &MidiBuffer::resize)
.addFunction ("copy", (void (MidiBuffer::*)(MidiBuffer const * const))&MidiBuffer::copy)
.addFunction ("push_event", (bool (MidiBuffer::*)(const Evoral::MIDIEvent<framepos_t>&))&MidiBuffer::push_back)
.addFunction ("push_event", (bool (MidiBuffer::*)(const Evoral::Event<framepos_t>&))&MidiBuffer::push_back)
.addFunction ("push_back", (bool (MidiBuffer::*)(framepos_t, size_t, const uint8_t*))&MidiBuffer::push_back)
// TODO iterators..
.addExtCFunction ("table", &luabridge::CFunc::listToTable<const Evoral::MIDIEvent<framepos_t>, MidiBuffer>)
.addExtCFunction ("table", &luabridge::CFunc::listToTable<const Evoral::Event<framepos_t>, MidiBuffer>)
.endClass()
.beginClass <BufferSet> ("BufferSet")
@ -1924,12 +1924,12 @@ LuaBindings::dsp (lua_State* L)
luabridge::getGlobalNamespace (L)
.beginNamespace ("Evoral")
.deriveClass <Evoral::MIDIEvent<framepos_t>, Evoral::Event<framepos_t> > ("MidiEvent")
.deriveClass <Evoral::Event<framepos_t>, Evoral::Event<framepos_t> > ("MidiEvent")
// add Ctor?
.addFunction ("type", &Evoral::MIDIEvent<framepos_t>::type)
.addFunction ("channel", &Evoral::MIDIEvent<framepos_t>::channel)
.addFunction ("set_type", &Evoral::MIDIEvent<framepos_t>::set_type)
.addFunction ("set_channel", &Evoral::MIDIEvent<framepos_t>::set_channel)
.addFunction ("type", &Evoral::Event<framepos_t>::type)
.addFunction ("channel", &Evoral::Event<framepos_t>::channel)
.addFunction ("set_type", &Evoral::Event<framepos_t>::set_type)
.addFunction ("set_channel", &Evoral::Event<framepos_t>::set_channel)
.endClass ()
.endNamespace ();

View File

@ -667,7 +667,7 @@ LuaProc::connect_and_run (BufferSet& bufs,
if (valid) {
for (MidiBuffer::iterator m = bufs.get_midi(idx).begin();
m != bufs.get_midi(idx).end(); ++m, ++e) {
const Evoral::MIDIEvent<framepos_t> ev(*m, false);
const Evoral::Event<framepos_t> ev(*m, false);
luabridge::LuaRef lua_midi_data (luabridge::newTable (L));
const uint8_t* data = ev.buffer();
for (uint32_t i = 0; i < ev.size(); ++i) {

View File

@ -2601,7 +2601,7 @@ LV2Plugin::connect_and_run(BufferSet& bufs,
MetricSection* metric = (metric_i != tmap.metrics_end())
? *metric_i : NULL;
if (m != m_end && (!metric || metric->frame() > (*m).time())) {
const Evoral::MIDIEvent<framepos_t> ev(*m, false);
const Evoral::Event<framepos_t> ev(*m, false);
if (ev.time() < nframes) {
LV2_Evbuf_Iterator eend = lv2_evbuf_end(_ev_buffers[port_index]);
lv2_evbuf_write(&eend, ev.time(), 0, type, ev.size(), ev.buffer());

View File

@ -106,7 +106,7 @@ PeakMeter::run (BufferSet& bufs, framepos_t /*start_frame*/, framepos_t /*end_fr
const MidiBuffer& buf (bufs.get_midi(i));
for (MidiBuffer::const_iterator e = buf.begin(); e != buf.end(); ++e) {
const Evoral::MIDIEvent<framepos_t> ev(*e, false);
const Evoral::Event<framepos_t> ev(*e, false);
if (ev.is_note_on()) {
const float this_vel = ev.buffer()[2] / 127.0;
if (this_vel > val) {

View File

@ -110,7 +110,7 @@ MidiBuffer::read_from (const Buffer& src, framecnt_t nframes, frameoffset_t dst_
}
for (MidiBuffer::const_iterator i = msrc.begin(); i != msrc.end(); ++i) {
const Evoral::MIDIEvent<TimeType> ev(*i, false);
const Evoral::Event<TimeType> ev(*i, false);
if (dst_offset >= 0) {
/* Positive offset: shifting events from internal
@ -168,7 +168,7 @@ MidiBuffer::merge_from (const Buffer& src, framecnt_t /*nframes*/, frameoffset_t
* @return false if operation failed (not enough room)
*/
bool
MidiBuffer::push_back(const Evoral::MIDIEvent<TimeType>& ev)
MidiBuffer::push_back(const Evoral::Event<TimeType>& ev)
{
return push_back (ev.time(), ev.size(), ev.buffer());
}
@ -220,7 +220,7 @@ MidiBuffer::push_back(TimeType time, size_t size, const uint8_t* data)
}
bool
MidiBuffer::insert_event(const Evoral::MIDIEvent<TimeType>& ev)
MidiBuffer::insert_event(const Evoral::Event<TimeType>& ev)
{
if (size() == 0) {
return push_back(ev);
@ -273,7 +273,7 @@ MidiBuffer::insert_event(const Evoral::MIDIEvent<TimeType>& ev)
uint32_t
MidiBuffer::write(TimeType time, Evoral::EventType type, uint32_t size, const uint8_t* buf)
{
insert_event(Evoral::MIDIEvent<TimeType>(type, time, size, const_cast<uint8_t*>(buf)));
insert_event(Evoral::Event<TimeType>(type, time, size, const_cast<uint8_t*>(buf)));
return size;
}

View File

@ -42,7 +42,7 @@ MidiChannelFilter::filter(BufferSet& bufs)
MidiBuffer& buf = bufs.get_midi(0);
for (MidiBuffer::iterator e = buf.begin(); e != buf.end(); ) {
Evoral::MIDIEvent<framepos_t> ev(*e, false);
Evoral::Event<framepos_t> ev(*e, false);
if (ev.is_channel_event()) {
switch (mode) {

View File

@ -409,7 +409,7 @@ MidiDiskstream::process (BufferSet& bufs, framepos_t transport_frame, pframes_t
MidiChannelFilter* filter = mt ? &mt->capture_filter() : NULL;
for (MidiBuffer::iterator i = buf.begin(); i != buf.end(); ++i) {
Evoral::MIDIEvent<MidiBuffer::TimeType> ev(*i, false);
Evoral::Event<MidiBuffer::TimeType> ev(*i, false);
if (ev.time() + rec_offset > rec_nframes) {
break;
}

View File

@ -1497,7 +1497,7 @@ MidiModel::write_section_to (boost::shared_ptr<MidiSource> source,
for (Evoral::Sequence<TimeType>::const_iterator i = begin(TimeType(), true); i != end(); ++i) {
if (i->time() >= begin_time && i->time() < end_time) {
Evoral::MIDIEvent<TimeType> mev (*i, true); /* copy the event */
Evoral::Event<TimeType> mev (*i, true); /* copy the event */
if (offset_events) {
mev.set_time(mev.time() - begin_time);

View File

@ -230,7 +230,7 @@ MidiPort::flush_buffers (pframes_t nframes)
for (MidiBuffer::iterator i = _buffer->begin(); i != _buffer->end(); ++i) {
const Evoral::MIDIEvent<MidiBuffer::TimeType> ev (*i, false);
const Evoral::Event<MidiBuffer::TimeType> ev (*i, false);
if (sends_output() && _trace_on) {

View File

@ -17,7 +17,7 @@
*/
#include "evoral/MIDIEvent.hpp"
#include "evoral/Event.hpp"
#include "midi++/channel.h"
#include "midi++/parser.h"
#include "midi++/port.h"

View File

@ -122,7 +122,7 @@ MidiStateTracker::resolve_notes (MidiBuffer &dst, framepos_t time)
for (int note = 0; note < 128; ++note) {
while (_active_notes[note + 128 * channel]) {
uint8_t buffer[3] = { ((uint8_t) (MIDI_CMD_NOTE_OFF | channel)), uint8_t (note), 0 };
Evoral::MIDIEvent<MidiBuffer::TimeType> noteoff
Evoral::Event<MidiBuffer::TimeType> noteoff
(MIDI_CMD_NOTE_OFF, time, 3, buffer, false);
/* note that we do not care about failure from
push_back() ... should we warn someone ?
@ -181,7 +181,7 @@ MidiStateTracker::resolve_notes (MidiSource& src, const MidiSource::Lock& lock,
for (int channel = 0; channel < 16; ++channel) {
for (int note = 0; note < 128; ++note) {
while (_active_notes[note + 128 * channel]) {
Evoral::MIDIEvent<Evoral::Beats> ev ((MIDI_CMD_NOTE_OFF|channel), time, 3, 0, true);
Evoral::Event<Evoral::Beats> ev ((MIDI_CMD_NOTE_OFF|channel), time, 3, 0, true);
ev.set_type (MIDI_CMD_NOTE_OFF);
ev.set_channel (channel);
ev.set_note (note);

View File

@ -339,7 +339,7 @@ MidiTrack::update_controls(const BufferSet& bufs)
{
const MidiBuffer& buf = bufs.get_midi(0);
for (MidiBuffer::const_iterator e = buf.begin(); e != buf.end(); ++e) {
const Evoral::MIDIEvent<framepos_t>& ev = *e;
const Evoral::Event<framepos_t>& ev = *e;
const Evoral::Parameter param = midi_parameter(ev.buffer(), ev.size());
const boost::shared_ptr<Evoral::Control> control = this->control(param);
if (control) {
@ -549,7 +549,7 @@ MidiTrack::push_midi_input_to_step_edit_ringbuffer (framecnt_t nframes)
for (MidiBuffer::const_iterator e = mb->begin(); e != mb->end(); ++e) {
const Evoral::MIDIEvent<framepos_t> ev(*e, false);
const Evoral::Event<framepos_t> ev(*e, false);
/* note on, since for step edit, note length is determined
elsewhere

View File

@ -334,7 +334,7 @@ SMFSource::write_unlocked (const Lock& lock,
_model->start_write();
}
Evoral::MIDIEvent<framepos_t> ev;
Evoral::Event<framepos_t> ev;
while (true) {
/* Get the event time, in frames since session start but ignoring looping. */
bool ret;

View File

@ -284,7 +284,7 @@
>
</File>
<File
RelativePath="..\src\MIDIEvent.cpp"
RelativePath="..\src\MIDIXML.cpp"
>
</File>
<File
@ -496,7 +496,7 @@
>
</File>
<File
RelativePath="..\evoral\MIDIEvent.hpp"
RelativePath="..\evoral\MIDIXML.hpp"
>
</File>
<File

View File

@ -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
};

View File

@ -1,115 +0,0 @@
/* This file is part of Evoral.
* Copyright (C) 2008 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
* terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option) any later
* version.
*
* Evoral is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef EVORAL_MIDI_EVENT_HPP
#define EVORAL_MIDI_EVENT_HPP
#include <cmath>
#include <boost/shared_ptr.hpp>
#include "evoral/visibility.h"
#include "evoral/Event.hpp"
#include "evoral/midi_events.h"
namespace Evoral {
/** MIDI helper functions for an Event.
*
* This class contains no data, an Evoral::Event can be cast to a MIDIEvent
* but the application must make sure the Event actually contains
* valid MIDI data for these functions to make sense.
*/
template<typename Time>
class /*LIBEVORAL_API*/ MIDIEvent : public Event<Time> {
public:
MIDIEvent(EventType type=0, Time time=0, uint32_t size=0, uint8_t* buf=NULL, bool alloc=false)
: Event<Time>(type, time, size, buf, alloc)
{}
MIDIEvent(const Event<Time>& copy, bool alloc)
: Event<Time>(copy, alloc)
{}
inline uint8_t type() const { return (this->_buf[0] & 0xF0); }
inline void set_type(uint8_t type) { this->_buf[0] = (0x0F & this->_buf[0])
| (0xF0 & type); }
inline uint8_t channel() const { return (this->_buf[0] & 0x0F); }
inline void set_channel(uint8_t channel) { this->_buf[0] = (0xF0 & this->_buf[0])
| (0x0F & channel); }
inline bool is_note_on() const { return (type() == MIDI_CMD_NOTE_ON); }
inline bool is_note_off() const { return (type() == MIDI_CMD_NOTE_OFF); }
inline bool is_cc() const { return (type() == MIDI_CMD_CONTROL); }
inline bool is_pitch_bender() const { return (type() == MIDI_CMD_BENDER); }
inline bool is_pgm_change() const { return (type() == MIDI_CMD_PGM_CHANGE); }
inline bool is_note() const { return (is_note_on() || is_note_off()); }
inline bool is_poly_pressure() const { return (type() == MIDI_CMD_NOTE_PRESSURE); }
inline bool is_channel_pressure() const { return (type() == MIDI_CMD_CHANNEL_PRESSURE); }
inline uint8_t note() const { return (this->_buf[1]); }
inline void set_note(uint8_t n) { this->_buf[1] = n; }
inline uint8_t velocity() const { return (this->_buf[2]); }
inline void set_velocity(uint8_t value) { this->_buf[2] = value; }
inline void scale_velocity(float factor) {
if (factor < 0) factor = 0;
this->_buf[2] = (uint8_t) lrintf (this->_buf[2]*factor);
if (this->_buf[2] > 127) this->_buf[2] = 127;
}
inline uint8_t cc_number() const { return (this->_buf[1]); }
inline void set_cc_number(uint8_t number) { this->_buf[1] = number; }
inline uint8_t cc_value() const { return (this->_buf[2]); }
inline void set_cc_value(uint8_t value) { this->_buf[2] = value; }
inline uint8_t pitch_bender_lsb() const { return (this->_buf[1]); }
inline uint8_t pitch_bender_msb() const { return (this->_buf[2]); }
inline uint16_t pitch_bender_value() const { return ( ((0x7F & this->_buf[2]) << 7)
| (0x7F & this->_buf[1]) ); }
inline uint8_t pgm_number() const { return (this->_buf[1]); }
inline void set_pgm_number(uint8_t number) { this->_buf[1] = number; }
inline uint8_t poly_note() const { return (this->_buf[1]); }
inline uint8_t poly_pressure() const { return (this->_buf[2]); }
inline uint8_t channel_pressure() const { return (this->_buf[1]); }
inline bool is_channel_event() const { return (0x80 <= type()) && (type() <= 0xE0); }
inline bool is_smf_meta_event() const { return this->_buf[0] == 0xFF; }
inline bool is_sysex() const { return this->_buf[0] == 0xF0
|| this->_buf[0] == 0xF7; }
inline bool is_spp() const { return this->_buf[0] == 0xF2 && this->size() == 1; }
inline bool is_mtc_quarter() const { return this->_buf[0] == 0xF1 && this->size() == 1; }
inline bool is_mtc_full() const {
return this->size() == 10 && this->_buf[0] == 0xf0 && this->_buf[1] == 0x7f &&
this->_buf[3] == 0x01 && this->_buf[4] == 0x01;
}
inline 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;
}
}
};
} // namespace Evoral
#endif // EVORAL_MIDI_EVENT_HPP

View File

@ -19,7 +19,7 @@
#ifndef EVORAL_MIDI_XML_HPP
#define EVORAL_MIDI_XML_HPP
#include "evoral/MIDIEvent.hpp"
#include "evoral/Event.hpp"
#include "pbd/xml++.h"
namespace Evoral {
@ -27,7 +27,7 @@ namespace MIDIXML {
template<typename Time>
bool
xml_to_midi(const XMLNode& node, Evoral::MIDIEvent<Time>& ev)
xml_to_midi(const XMLNode& node, Evoral::Event<Time>& ev)
{
if (node.name() == "ControlChange") {
ev.set_type(MIDI_CMD_CONTROL);
@ -45,7 +45,7 @@ xml_to_midi(const XMLNode& node, Evoral::MIDIEvent<Time>& ev)
template<typename Time>
boost::shared_ptr<XMLNode>
midi_to_xml(const Evoral::MIDIEvent<Time>& ev)
midi_to_xml(const Evoral::Event<Time>& ev)
{
XMLNode* result = 0;

View File

@ -24,7 +24,7 @@
#include <stdint.h>
#include "evoral/visibility.h"
#include "evoral/MIDIEvent.hpp"
#include "evoral/Event.hpp"
namespace Evoral {
@ -105,8 +105,8 @@ public:
private:
// Event buffers are self-contained
MIDIEvent<Time> _on_event;
MIDIEvent<Time> _off_event;
Event<Time> _on_event;
Event<Time> _off_event;
};
template<typename Time>

View File

@ -22,7 +22,7 @@
#include "evoral/visibility.h"
#include "evoral/Event.hpp"
#include "evoral/MIDIEvent.hpp"
#include "evoral/Event.hpp"
namespace Evoral {
@ -138,7 +138,7 @@ public:
/** The PatchChange is made up of messages() MIDI messages; this method returns them by index.
* @param i index of message to return.
*/
MIDIEvent<Time> const & message (int i) const {
Event<Time> const & message (int i) const {
switch (i) {
case 0:
return _bank_change_msb;
@ -158,9 +158,9 @@ public:
}
private:
MIDIEvent<Time> _bank_change_msb;
MIDIEvent<Time> _bank_change_lsb;
MIDIEvent<Time> _program_change;
Event<Time> _bank_change_msb;
Event<Time> _bank_change_lsb;
Event<Time> _program_change;
};
}

View File

@ -335,10 +335,10 @@ private:
bool overlaps_unlocked (const NotePtr& ev, const NotePtr& ignore_this_note) const;
bool contains_unlocked (const NotePtr& ev) const;
void append_note_on_unlocked(const MIDIEvent<Time>& event, Evoral::event_id_t);
void append_note_off_unlocked(const MIDIEvent<Time>& event);
void append_note_on_unlocked(const Event<Time>& event, Evoral::event_id_t);
void append_note_off_unlocked(const Event<Time>& event);
void append_control_unlocked(const Parameter& param, Time time, double value, Evoral::event_id_t);
void append_sysex_unlocked(const MIDIEvent<Time>& ev, Evoral::event_id_t);
void append_sysex_unlocked(const Event<Time>& ev, Evoral::event_id_t);
void append_patch_change_unlocked(const PatchChange<Time>&, Evoral::event_id_t);
void get_notes_by_pitch (Notes&, NoteOperator, uint8_t val, int chan_mask = 0) const;

View File

@ -16,6 +16,7 @@
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <cassert>
#include <iostream>
#include <limits>
#include <glib.h>

View File

@ -330,7 +330,7 @@ Sequence<Time>::const_iterator::operator++()
assert(_event && _event->buffer() && _event->size() > 0);
const MIDIEvent<Time>& ev = *((const MIDIEvent<Time>*)_event.get());
const Event<Time>& ev = *_event.get();
if (!( ev.is_note()
|| ev.is_cc()
@ -902,12 +902,10 @@ Sequence<Time>::remove_sysex_unlocked (const SysExPtr sysex)
*/
template<typename Time>
void
Sequence<Time>::append(const Event<Time>& event, event_id_t evid)
Sequence<Time>::append(const Event<Time>& ev, event_id_t evid)
{
WriteLock lock(write_lock());
const MIDIEvent<Time>& ev = (const MIDIEvent<Time>&)event;
assert(_notes.empty() || ev.time() >= (*_notes.rbegin())->time());
assert(_writing);
@ -968,7 +966,7 @@ Sequence<Time>::append(const Event<Time>& event, event_id_t evid)
template<typename Time>
void
Sequence<Time>::append_note_on_unlocked (const MIDIEvent<Time>& ev, event_id_t evid)
Sequence<Time>::append_note_on_unlocked (const Event<Time>& ev, event_id_t evid)
{
DEBUG_TRACE (DEBUG::Sequence, string_compose ("%1 c=%2 note %3 on @ %4 v=%5\n", this,
(int)ev.channel(), (int)ev.note(),
@ -1000,7 +998,7 @@ Sequence<Time>::append_note_on_unlocked (const MIDIEvent<Time>& ev, event_id_t e
template<typename Time>
void
Sequence<Time>::append_note_off_unlocked (const MIDIEvent<Time>& ev)
Sequence<Time>::append_note_off_unlocked (const Event<Time>& ev)
{
DEBUG_TRACE (DEBUG::Sequence, string_compose ("%1 c=%2 note %3 OFF @ %4 v=%5\n",
this, (int)ev.channel(),
@ -1067,7 +1065,7 @@ Sequence<Time>::append_control_unlocked(const Parameter& param, Time time, doubl
template<typename Time>
void
Sequence<Time>::append_sysex_unlocked(const MIDIEvent<Time>& ev, event_id_t /* evid */)
Sequence<Time>::append_sysex_unlocked(const Event<Time>& ev, event_id_t /* evid */)
{
#ifdef DEBUG_SEQUENCE
cerr << this << " SysEx @ " << ev.time() << " \t= \t [ " << hex;
@ -1076,7 +1074,7 @@ Sequence<Time>::append_sysex_unlocked(const MIDIEvent<Time>& ev, event_id_t /* e
} cerr << "]" << endl;
#endif
boost::shared_ptr<MIDIEvent<Time> > event(new MIDIEvent<Time>(ev, true));
boost::shared_ptr< Event<Time> > event(new Event<Time>(ev, true));
/* XXX sysex events should use IDs */
_sysexes.insert(event);
}

View File

@ -77,12 +77,12 @@ SequenceTest::iteratorSeekTest ()
bool on = true;
for (Sequence<Time>::const_iterator i = seq->begin(Evoral::Beats(600)); i != seq->end(); ++i) {
if (on) {
CPPUNIT_ASSERT(((const MIDIEvent<Time>&)*i).is_note_on());
CPPUNIT_ASSERT((*i)->is_note_on());
CPPUNIT_ASSERT_EQUAL(i->time(), Time((num_notes + 6) * 100));
++num_notes;
on = false;
} else {
CPPUNIT_ASSERT(((const MIDIEvent<Time>&)*i).is_note_off());
CPPUNIT_ASSERT((*i)->is_note_off());
on = true;
}
}

View File

@ -38,6 +38,5 @@
#define EVORAL_EVENT_ALLOC 1
#include "evoral/Event.hpp"
#include "evoral/MIDIEvent.hpp"
#endif /* __libmidipp_midi_event_h__ */

View File

@ -97,12 +97,12 @@ Patch::get_state (void)
node->add_property("Name", _name);
/*
typedef std::list< boost::shared_ptr< Evoral::MIDIEvent<Evoral::Beats> > > PatchMidiCommands;
typedef std::list< boost::shared_ptr< Evoral::Event<Evoral::Beats> > > PatchMidiCommands;
XMLNode* commands = node->add_child("PatchMIDICommands");
for (PatchMidiCommands::const_iterator event = _patch_midi_commands.begin();
event != _patch_midi_commands.end();
++event) {
commands->add_child_copy(*((((Evoral::MIDIEvent&)*event)).to_xml()));
commands->add_child_copy(Evoral::MIDIXML::midi_to_xml(*event));
}
*/