Removed fixed/maximum event size assumption/limitation from MIDI buffer.
git-svn-id: svn://localhost/ardour2/branches/3.0@4471 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
554d46896b
commit
44ac5f5097
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright (C) 2006 Paul Davis
|
||||
Copyright (C) 2006-2009 Paul Davis
|
||||
Author: Dave Robillard
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
|
@ -20,8 +20,10 @@
|
|||
#ifndef __ardour_midi_buffer_h__
|
||||
#define __ardour_midi_buffer_h__
|
||||
|
||||
#include <evoral/midi_util.h>
|
||||
#include <midi++/event.h>
|
||||
#include <ardour/buffer.h>
|
||||
#include <ardour/event_type_map.h>
|
||||
|
||||
namespace ARDOUR {
|
||||
|
||||
|
@ -50,16 +52,23 @@ public:
|
|||
|
||||
template<typename B, typename E>
|
||||
struct iterator_base {
|
||||
iterator_base<B,E>(B& b, size_t i) : buffer(b), index(i) {}
|
||||
|
||||
inline E& operator*() const { return buffer[index]; }
|
||||
inline iterator_base<B,E>& operator++() { ++index; return *this; } // prefix
|
||||
inline bool operator!=(const iterator_base<B,E>& other) const {
|
||||
return index != other.index;
|
||||
iterator_base<B,E>(B& b, size_t o) : buffer(b), offset(o) {}
|
||||
inline E operator*() const {
|
||||
uint8_t* ev_start = buffer._data + offset + sizeof(Evoral::EventTime);
|
||||
return E(EventTypeMap::instance().midi_event_type(*ev_start),
|
||||
*(Evoral::EventTime*)(buffer._data + offset),
|
||||
Evoral::midi_event_size(*ev_start) + 1, ev_start);
|
||||
}
|
||||
inline iterator_base<B,E>& operator++() {
|
||||
uint8_t* ev_start = buffer._data + offset + sizeof(Evoral::EventTime);
|
||||
offset += sizeof(Evoral::EventTime) + Evoral::midi_event_size(*ev_start) + 1;
|
||||
return *this;
|
||||
}
|
||||
inline bool operator!=(const iterator_base<B,E>& other) const {
|
||||
return (&buffer != &other.buffer) || (offset != other.offset);
|
||||
}
|
||||
|
||||
B& buffer;
|
||||
size_t index;
|
||||
size_t offset;
|
||||
};
|
||||
|
||||
typedef iterator_base<MidiBuffer, Evoral::MIDIEvent> iterator;
|
||||
|
@ -72,24 +81,11 @@ public:
|
|||
const_iterator end() const { return const_iterator(*this, _size); }
|
||||
|
||||
private:
|
||||
|
||||
friend class iterator_base<MidiBuffer, Evoral::MIDIEvent>;
|
||||
friend class iterator_base<const MidiBuffer, const Evoral::MIDIEvent>;
|
||||
|
||||
const Evoral::MIDIEvent& operator[](size_t i) const { assert(i < _size); return _events[i]; }
|
||||
Evoral::MIDIEvent& operator[](size_t i) { assert(i < _size); return _events[i]; }
|
||||
|
||||
// FIXME: Eliminate this
|
||||
static const size_t MAX_EVENT_SIZE = 4; // bytes
|
||||
|
||||
/* We use _size as "number of events", so the size of _data is
|
||||
* (_size * MAX_EVENT_SIZE)
|
||||
*/
|
||||
|
||||
/* FIXME: this is utter crap. rewrite as a flat/packed buffer like MidiRingBuffer */
|
||||
|
||||
Evoral::MIDIEvent* _events; ///< Event structs that point to offsets in _data
|
||||
uint8_t* _data; ///< MIDI, straight up. No time stamps.
|
||||
size_t _size; ///< Size in bytes of used portion of _data
|
||||
uint8_t* _data; ///< timestamp, event, timestamp, event, ...
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ class MidiPort : public Port {
|
|||
return get_midi_buffer (nframes, offset);
|
||||
}
|
||||
|
||||
MidiBuffer& get_midi_buffer( nframes_t nframes, nframes_t offset );
|
||||
MidiBuffer& get_midi_buffer (nframes_t nframes, nframes_t offset);
|
||||
|
||||
protected:
|
||||
friend class AudioEngine;
|
||||
|
|
|
@ -40,7 +40,7 @@ public:
|
|||
void resolve_notes (MidiBuffer& buffer, nframes_t time);
|
||||
|
||||
private:
|
||||
void track_note_onoffs(Evoral::MIDIEvent& event);
|
||||
void track_note_onoffs(const Evoral::MIDIEvent& event);
|
||||
|
||||
std::bitset<128*16> _active_notes;
|
||||
};
|
||||
|
|
|
@ -50,7 +50,7 @@ PeakMeter::run_in_place (BufferSet& bufs, nframes_t start_frame, nframes_t end_f
|
|||
// GUI needs a better MIDI meter, not much information can be
|
||||
// expressed through peaks alone
|
||||
for (MidiBuffer::iterator i = bufs.get_midi(n).begin(); i != bufs.get_midi(n).end(); ++i) {
|
||||
const Evoral::MIDIEvent& ev = *i;
|
||||
const Evoral::MIDIEvent ev(*i, false);
|
||||
if (ev.is_note_on()) {
|
||||
const float this_vel = log(ev.buffer()[2] / 127.0 * (M_E*M_E-M_E) + M_E) - 1.0;
|
||||
//printf("V %d -> %f\n", (int)((Byte)ev.buffer[2]), this_vel);
|
||||
|
|
|
@ -33,7 +33,7 @@ using namespace ARDOUR;
|
|||
// FIXME: mirroring for MIDI buffers?
|
||||
MidiBuffer::MidiBuffer(size_t capacity)
|
||||
: Buffer(DataType::MIDI, capacity)
|
||||
, _events(0)
|
||||
, _size(0)
|
||||
, _data(0)
|
||||
{
|
||||
if (capacity) {
|
||||
|
@ -44,12 +44,7 @@ MidiBuffer::MidiBuffer(size_t capacity)
|
|||
|
||||
MidiBuffer::~MidiBuffer()
|
||||
{
|
||||
if (_events) {
|
||||
free(_events);
|
||||
}
|
||||
if (_data) {
|
||||
free(_data);
|
||||
}
|
||||
free(_data);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -62,30 +57,24 @@ MidiBuffer::resize(size_t size)
|
|||
}
|
||||
|
||||
free(_data);
|
||||
free(_events);
|
||||
|
||||
_size = 0;
|
||||
_capacity = size;
|
||||
|
||||
#ifdef NO_POSIX_MEMALIGN
|
||||
_events = (Evoral::MIDIEvent *) malloc(sizeof(Evoral::MIDIEvent) * _capacity);
|
||||
_data = (uint8_t *) malloc(sizeof(uint8_t) * _capacity * MAX_EVENT_SIZE);
|
||||
_data = (uint8_t*)malloc(_capacity);
|
||||
#else
|
||||
posix_memalign((void**)&_events, CPU_CACHE_ALIGN, sizeof(Evoral::Event) * _capacity);
|
||||
posix_memalign((void**)&_data, CPU_CACHE_ALIGN, sizeof(uint8_t) * _capacity * MAX_EVENT_SIZE);
|
||||
posix_memalign((void**)&_data, CPU_CACHE_ALIGN, _capacity);
|
||||
#endif
|
||||
assert(_data);
|
||||
assert(_events);
|
||||
}
|
||||
|
||||
void
|
||||
MidiBuffer::copy(const MidiBuffer& copy)
|
||||
{
|
||||
assert(_capacity >= copy._capacity);
|
||||
_size = 0;
|
||||
|
||||
for (size_t i = 0; i < copy.size(); ++i)
|
||||
push_back(copy[i]);
|
||||
assert(_capacity >= copy._size);
|
||||
_size = copy._size;
|
||||
memcpy(_data, copy._data, copy._size);
|
||||
}
|
||||
|
||||
|
||||
|
@ -109,11 +98,11 @@ MidiBuffer::read_from(const Buffer& src, nframes_t nframes, nframes_t offset)
|
|||
assert(_size == 0);
|
||||
}
|
||||
|
||||
// FIXME: slow
|
||||
for (size_t i = 0; i < msrc.size(); ++i) {
|
||||
const Evoral::MIDIEvent& ev = msrc[i];
|
||||
//cout << "MidiBuffer::read_from event type: " << int(ev.type())
|
||||
// << " time: " << ev.time() << " buffer size: " << _size << endl;
|
||||
for (MidiBuffer::const_iterator i = msrc.begin(); i != msrc.end(); ++i) {
|
||||
const Evoral::MIDIEvent ev(*i, false);
|
||||
/*cout << this << " MidiBuffer::read_from event type: " << int(ev.type())
|
||||
<< " time: " << ev.time() << " size: " << ev.size()
|
||||
<< " status: " << (int)*ev.buffer() << " buffer size: " << _size << endl;*/
|
||||
if (ev.time() < offset) {
|
||||
//cout << "MidiBuffer::read_from skipped event before " << offset << endl;
|
||||
} else if (ev.time() < (nframes + offset)) {
|
||||
|
@ -139,27 +128,19 @@ MidiBuffer::read_from(const Buffer& src, nframes_t nframes, nframes_t offset)
|
|||
bool
|
||||
MidiBuffer::push_back(const Evoral::MIDIEvent& ev)
|
||||
{
|
||||
if (_size == _capacity) {
|
||||
const size_t stamp_size = sizeof(Evoral::EventTime);
|
||||
if (_size + stamp_size + ev.size() >= _capacity) {
|
||||
cerr << "MidiBuffer::push_back failed (buffer is full)" << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t* const write_loc = _data + (_size * MAX_EVENT_SIZE);
|
||||
uint8_t* const write_loc = _data + _size;
|
||||
*((Evoral::EventTime*)write_loc) = ev.time();
|
||||
memcpy(write_loc + stamp_size, ev.buffer(), ev.size());
|
||||
|
||||
memcpy(write_loc, ev.buffer(), ev.size());
|
||||
_events[_size] = ev;
|
||||
_events[_size].set_buffer(ev.size(), write_loc, false);
|
||||
|
||||
/*cerr << "MidiBuffer: pushed @ " << _events[_size].time()
|
||||
<< " size = " << _size << endl;
|
||||
for (size_t i = 0; i < _events[_size].size(); ++i) {
|
||||
printf("%X ", _events[_size].buffer()[i]);
|
||||
}
|
||||
printf("\n");*/
|
||||
|
||||
++_size;
|
||||
_size += stamp_size + ev.size();
|
||||
_silent = false;
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -174,27 +155,19 @@ MidiBuffer::push_back(const Evoral::MIDIEvent& ev)
|
|||
bool
|
||||
MidiBuffer::push_back(const jack_midi_event_t& ev)
|
||||
{
|
||||
if (_size == _capacity) {
|
||||
const size_t stamp_size = sizeof(Evoral::EventTime);
|
||||
if (_size + stamp_size + ev.size >= _capacity) {
|
||||
cerr << "MidiBuffer::push_back failed (buffer is full)" << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t* const write_loc = _data + (_size * MAX_EVENT_SIZE);
|
||||
uint8_t* const write_loc = _data + _size;
|
||||
*((Evoral::EventTime*)write_loc) = ev.time;
|
||||
memcpy(write_loc + stamp_size, ev.buffer, ev.size);
|
||||
|
||||
memcpy(write_loc, ev.buffer, ev.size);
|
||||
_events[_size].time() = (double)ev.time;
|
||||
_events[_size].set_buffer(ev.size, write_loc, false);
|
||||
|
||||
/*cerr << "MidiBuffer: pushed @ " << _events[_size].time()
|
||||
<< " size = " << _size << endl;
|
||||
for (size_t i = 0; i < _events[_size].size(); ++i) {
|
||||
printf("%X ", _events[_size].buffer()[i]);
|
||||
}
|
||||
printf("\n");*/
|
||||
|
||||
++_size;
|
||||
_size += stamp_size + ev.size;
|
||||
_silent = false;
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -207,27 +180,19 @@ MidiBuffer::push_back(const jack_midi_event_t& ev)
|
|||
* location, or the buffer will be corrupted and very nasty things will happen.
|
||||
*/
|
||||
uint8_t*
|
||||
MidiBuffer::reserve(double time, size_t size)
|
||||
MidiBuffer::reserve(Evoral::EventTime time, size_t size)
|
||||
{
|
||||
if (size > MAX_EVENT_SIZE) {
|
||||
cerr << "WARNING: Failed to reserve " << size << " bytes for event";
|
||||
const size_t stamp_size = sizeof(Evoral::EventTime);
|
||||
if (_size + stamp_size + size >= _capacity) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (_size == _capacity) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t* const write_loc = _data + (_size * MAX_EVENT_SIZE);
|
||||
|
||||
_events[_size].time() = time;
|
||||
_events[_size].set_buffer(size, write_loc, false);
|
||||
++_size;
|
||||
|
||||
//cerr << "MidiBuffer: reserved, size = " << _size << endl;
|
||||
uint8_t* const write_loc = _data + _size;
|
||||
*((Evoral::EventTime*)write_loc) = time;
|
||||
|
||||
_size += stamp_size + size;
|
||||
_silent = false;
|
||||
|
||||
|
||||
return write_loc;
|
||||
}
|
||||
|
||||
|
@ -239,12 +204,11 @@ MidiBuffer::silence(nframes_t dur, nframes_t offset)
|
|||
if (offset != 0)
|
||||
cerr << "WARNING: MidiBuffer::silence w/ offset != 0 (not implemented)" << endl;
|
||||
|
||||
memset(_events, 0, sizeof(Evoral::Event) * _capacity);
|
||||
memset(_data, 0, sizeof(uint8_t) * _capacity * MAX_EVENT_SIZE);
|
||||
_size = 0;
|
||||
_silent = true;
|
||||
}
|
||||
|
||||
/** Merge \a other into this buffer. Realtime safe. */
|
||||
bool
|
||||
MidiBuffer::merge_in_place(const MidiBuffer &other)
|
||||
{
|
||||
|
@ -252,36 +216,21 @@ MidiBuffer::merge_in_place(const MidiBuffer &other)
|
|||
return true;
|
||||
}
|
||||
|
||||
if (this->size() == 0) {
|
||||
if (_size == 0) {
|
||||
copy(other);
|
||||
return true;
|
||||
}
|
||||
|
||||
{
|
||||
MidiBuffer merge_buffer(0);
|
||||
Evoral::MIDIEvent onstack_events[_capacity];
|
||||
uint8_t onstack_data[_capacity * MAX_EVENT_SIZE];
|
||||
merge_buffer._events = onstack_events;
|
||||
merge_buffer._data = onstack_data;
|
||||
merge_buffer._size = 0;
|
||||
|
||||
bool retval = merge_buffer.merge(*this, other);
|
||||
|
||||
copy(merge_buffer);
|
||||
|
||||
// set pointers to zero again, so destructor
|
||||
// does not end in calling free() for memory
|
||||
// on the stack;
|
||||
merge_buffer._events = 0;
|
||||
merge_buffer._data = 0;
|
||||
|
||||
return retval;
|
||||
if (_size + other.size() > _capacity) {
|
||||
cerr << "MidiBuffer::merge failed (no space)" << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
cerr << "FIXME: MIDI BUFFER IN-PLACE MERGE" << endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Clear, and merge \a a and \a b into this buffer.
|
||||
*
|
||||
* FIXME: This is slow.
|
||||
*
|
||||
* \return true if complete merge was successful
|
||||
*/
|
||||
|
@ -297,40 +246,8 @@ MidiBuffer::merge(const MidiBuffer& a, const MidiBuffer& b)
|
|||
if (this == &b) {
|
||||
merge_in_place(a);
|
||||
}
|
||||
|
||||
size_t a_index = 0;
|
||||
size_t b_index = 0;
|
||||
size_t count = a.size() + b.size();
|
||||
|
||||
while (count > 0) {
|
||||
|
||||
if (size() == capacity()) {
|
||||
cerr << "WARNING: MIDI buffer overrun, events lost!" << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (a_index == a.size()) {
|
||||
push_back(b[b_index]);
|
||||
++b_index;
|
||||
} else if (b_index == b.size()) {
|
||||
push_back(a[a_index]);
|
||||
++a_index;
|
||||
} else {
|
||||
const Evoral::MIDIEvent& a_ev = a[a_index];
|
||||
const Evoral::MIDIEvent& b_ev = b[b_index];
|
||||
|
||||
if (a_ev.time() <= b_ev.time()) {
|
||||
push_back(a_ev);
|
||||
++a_index;
|
||||
} else {
|
||||
push_back(b_ev);
|
||||
++b_index;
|
||||
}
|
||||
}
|
||||
|
||||
--count;
|
||||
}
|
||||
|
||||
|
||||
cerr << "FIXME: MIDI BUFFER MERGE" << endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -518,20 +518,12 @@ MidiDiskstream::process (nframes_t transport_frame, nframes_t nframes, nframes_t
|
|||
|
||||
if (nominally_recording || rec_nframes) {
|
||||
|
||||
assert(_source_port);
|
||||
|
||||
// Pump entire port buffer into the ring buffer (FIXME: split cycles?)
|
||||
//_capture_buf->write(_source_port->get_midi_buffer(), transport_frame);
|
||||
size_t num_events = _source_port->get_midi_buffer( nframes, offset ).size();
|
||||
size_t to_write = std::min(_capture_buf->write_space(), num_events);
|
||||
|
||||
MidiBuffer::iterator port_iter = _source_port->get_midi_buffer( nframes, offset ).begin();
|
||||
|
||||
for (size_t i=0; i < to_write; ++i) {
|
||||
const Evoral::MIDIEvent& ev = *port_iter;
|
||||
MidiBuffer& buf = _source_port->get_midi_buffer(nframes, offset);
|
||||
for (MidiBuffer::iterator i = buf.begin(); i != buf.end(); ++i) {
|
||||
const Evoral::MIDIEvent ev(*i, false);
|
||||
assert(ev.buffer());
|
||||
_capture_buf->write(ev.time() + transport_frame, ev.type(), ev.size(), ev.buffer());
|
||||
++port_iter;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
|
|
@ -31,7 +31,7 @@ MidiPort::MidiPort (const std::string& name, Flags flags, bool ext, nframes_t ca
|
|||
{
|
||||
// FIXME: size kludge (see BufferSet::ensure_buffers)
|
||||
// Jack needs to tell us this
|
||||
_buffer = new MidiBuffer (capacity * 8);
|
||||
_buffer = new MidiBuffer (capacity * 32);
|
||||
}
|
||||
|
||||
MidiPort::~MidiPort()
|
||||
|
@ -54,8 +54,8 @@ MidiPort::cycle_start (nframes_t nframes, nframes_t offset)
|
|||
}
|
||||
|
||||
MidiBuffer &
|
||||
MidiPort::get_midi_buffer( nframes_t nframes, nframes_t offset ) {
|
||||
|
||||
MidiPort::get_midi_buffer (nframes_t nframes, nframes_t offset)
|
||||
{
|
||||
if (_has_been_mixed_down) {
|
||||
return *_buffer;
|
||||
}
|
||||
|
@ -80,8 +80,6 @@ MidiPort::get_midi_buffer( nframes_t nframes, nframes_t offset ) {
|
|||
_buffer->push_back (ev);
|
||||
}
|
||||
|
||||
assert(_buffer->size() == event_count);
|
||||
|
||||
if (nframes) {
|
||||
_has_been_mixed_down = true;
|
||||
}
|
||||
|
@ -167,7 +165,7 @@ MidiPort::mixdown (nframes_t cnt, nframes_t offset, bool first_overwrite)
|
|||
|
||||
if (first_overwrite) {
|
||||
_buffer->read_from ((dynamic_cast<MidiPort*>(*p))->get_midi_buffer (cnt, offset), cnt, offset);
|
||||
p++;
|
||||
++p;
|
||||
}
|
||||
|
||||
// XXX DAVE: this is just a guess
|
||||
|
@ -176,3 +174,4 @@ MidiPort::mixdown (nframes_t cnt, nframes_t offset, bool first_overwrite)
|
|||
_buffer->merge (*_buffer, (dynamic_cast<MidiPort*>(*p))->get_midi_buffer (cnt, offset));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -33,7 +33,6 @@ size_t
|
|||
MidiRingBuffer::read(MidiBuffer& dst, nframes_t start, nframes_t end, nframes_t offset)
|
||||
{
|
||||
if (read_space() == 0) {
|
||||
//cerr << "MRB: NO READ SPACE" << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -100,7 +99,7 @@ MidiRingBuffer::read(MidiBuffer& dst, nframes_t start, nframes_t end, nframes_t
|
|||
|
||||
uint8_t* write_loc = dst.reserve(ev_time, ev_size);
|
||||
if (write_loc == NULL) {
|
||||
//cerr << "MRB: Unable to reserve space in buffer, event skipped";
|
||||
cerr << "MRB: Unable to reserve space in buffer, event skipped";
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -113,7 +112,7 @@ MidiRingBuffer::read(MidiBuffer& dst, nframes_t start, nframes_t end, nframes_t
|
|||
++count;
|
||||
//cerr << "MRB - read event at time " << ev_time << endl;
|
||||
} else {
|
||||
//cerr << "WARNING: error reading event contents from MIDI ring" << endl;
|
||||
cerr << "WARNING: error reading event contents from MIDI ring" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ MidiStateTracker::MidiStateTracker ()
|
|||
}
|
||||
|
||||
void
|
||||
MidiStateTracker::track_note_onoffs (Evoral::MIDIEvent &event)
|
||||
MidiStateTracker::track_note_onoffs (const Evoral::MIDIEvent &event)
|
||||
{
|
||||
if (event.is_note_on()) {
|
||||
_active_notes [event.note() + 128 * event.channel()] = true;
|
||||
|
@ -46,12 +46,13 @@ MidiStateTracker::track (const MidiBuffer::iterator &from, const MidiBuffer::ite
|
|||
bool ret = false;
|
||||
|
||||
for (MidiBuffer::iterator i = from; i != to; ++i) {
|
||||
if ((*i).event_type() == LoopEventType) {
|
||||
const Evoral::MIDIEvent ev(*i, false);
|
||||
if (ev.event_type() == LoopEventType) {
|
||||
ret = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
track_note_onoffs (*i);
|
||||
track_note_onoffs (ev);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -586,76 +586,11 @@ MidiTrack::process_output_buffers (BufferSet& bufs,
|
|||
}
|
||||
|
||||
void
|
||||
MidiTrack::write_controller_messages(MidiBuffer& output_buf, nframes_t start_frame, nframes_t end_frame,
|
||||
MidiTrack::write_controller_messages(MidiBuffer& output_buf, nframes_t start, nframes_t end,
|
||||
nframes_t nframes, nframes_t offset)
|
||||
{
|
||||
#if 0
|
||||
BufferSet& mix_buffers = _session.get_mix_buffers(ChanCount(DataType::MIDI, 2));
|
||||
|
||||
/* FIXME: this could be more realtimey */
|
||||
|
||||
// Write immediate events (UI controls)
|
||||
MidiBuffer& cc_buf = mix_buffers.get_midi(0);
|
||||
cc_buf.silence(nframes, offset);
|
||||
|
||||
uint8_t buf[3]; // CC = 3 bytes
|
||||
buf[0] = MIDI_CMD_CONTROL;
|
||||
Evoral::Event ev(0, 3, buf, false);
|
||||
|
||||
// Write track controller automation
|
||||
// This now lives in MidiModel. Any need for track automation like this?
|
||||
// Relative Velocity?
|
||||
if (_session.transport_rolling()) {
|
||||
for (Controls::const_iterator i = _controls.begin(); i != _controls.end(); ++i) {
|
||||
const boost::shared_ptr<AutomationList> list = (*i).second->list();
|
||||
|
||||
if ( (!list->automation_playback())
|
||||
|| (list->parameter().type() != MidiCCAutomation))
|
||||
continue;
|
||||
|
||||
double start = start_frame;
|
||||
double x, y;
|
||||
while ((*i).second->list()->rt_safe_earliest_event(start, end_frame, x, y)) {
|
||||
assert(x >= start_frame);
|
||||
assert(x <= end_frame);
|
||||
|
||||
const nframes_t stamp = (nframes_t)floor(x - start_frame);
|
||||
assert(stamp < nframes);
|
||||
|
||||
assert(y >= 0.0);
|
||||
assert(y <= 127.0);
|
||||
|
||||
ev.time() = stamp;
|
||||
ev.buffer()[1] = (uint8_t)list->parameter().id();
|
||||
ev.buffer()[2] = (uint8_t)y;
|
||||
|
||||
cc_buf.push_back(ev);
|
||||
|
||||
start = x + 1; // FIXME? maybe?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* FIXME: too much copying! */
|
||||
|
||||
// Merge cc buf into output
|
||||
if (cc_buf.size() > 0) {
|
||||
|
||||
// Both CC and route, must merge
|
||||
if (output_buf.size() > 0) {
|
||||
|
||||
MidiBuffer& mix_buf = mix_buffers.get_midi(1);
|
||||
mix_buf.merge(output_buf, cc_buf);
|
||||
output_buf.copy(mix_buf);
|
||||
|
||||
} else {
|
||||
output_buf.copy(cc_buf);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Append immediate events (UI controls)
|
||||
_immediate_events.read(output_buf, 0, 0, offset + nframes-1); // all stamps = 0
|
||||
_immediate_events.read(output_buf, 0, 0, offset + nframes - 1); // all stamps = 0
|
||||
}
|
||||
|
||||
int
|
||||
|
|
|
@ -266,11 +266,13 @@ SMFSource::write_unlocked (MidiRingBuffer& src, nframes_t cnt)
|
|||
void
|
||||
SMFSource::append_event_unlocked(EventTimeUnit unit, const Evoral::Event& ev)
|
||||
{
|
||||
if (ev.size() == 0)
|
||||
if (ev.size() == 0) {
|
||||
cerr << "SMFSource: Warning: skipping empty event" << endl;
|
||||
return;
|
||||
}
|
||||
|
||||
/*printf("SMFSource: %s - append_event_unlocked chan = %u, time = %lf, size = %u, data = ",
|
||||
name().c_str(), (unsigned)ev.channel(), ev.time(), ev.size());
|
||||
/*printf("SMFSource: %s - append_event_unlocked time = %lf, size = %u, data = ",
|
||||
name().c_str(), ev.time(), ev.size());
|
||||
for (size_t i=0; i < ev.size(); ++i) {
|
||||
printf("%X ", ev.buffer()[i]);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user