basic work to permit "MIDI catchup" for MIDI state at any point on the timeline
This currently does nothing and cannot be enabled
This commit is contained in:
parent
4647dd6b41
commit
cb91334cc6
|
@ -103,6 +103,8 @@ public:
|
||||||
|
|
||||||
bool declick_in_progress () const;
|
bool declick_in_progress () const;
|
||||||
|
|
||||||
|
void set_need_midi_catchup (bool);
|
||||||
|
|
||||||
/* inc/dec variants MUST be called as part of the process call tree, before any
|
/* inc/dec variants MUST be called as part of the process call tree, before any
|
||||||
* disk readers are invoked. We use it when the session needs the
|
* disk readers are invoked. We use it when the session needs the
|
||||||
* transport (and thus effective read position for DiskReaders) to keep
|
* transport (and thus effective read position for DiskReaders) to keep
|
||||||
|
@ -248,6 +250,9 @@ private:
|
||||||
|
|
||||||
samplepos_t last_refill_loop_start;
|
samplepos_t last_refill_loop_start;
|
||||||
void setup_preloop_buffer ();
|
void setup_preloop_buffer ();
|
||||||
|
|
||||||
|
bool _midi_catchup;
|
||||||
|
bool _need_midi_catchup;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ARDOUR
|
} // namespace ARDOUR
|
||||||
|
|
|
@ -37,6 +37,7 @@ namespace ARDOUR {
|
||||||
|
|
||||||
class MidiBuffer;
|
class MidiBuffer;
|
||||||
class MidiNoteTracker;
|
class MidiNoteTracker;
|
||||||
|
class MidiStateTracker;
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
class LIBARDOUR_API RTMidiBuffer : public Evoral::EventSink<samplepos_t>
|
class LIBARDOUR_API RTMidiBuffer : public Evoral::EventSink<samplepos_t>
|
||||||
|
@ -62,6 +63,7 @@ class LIBARDOUR_API RTMidiBuffer : public Evoral::EventSink<samplepos_t>
|
||||||
|
|
||||||
uint32_t write (TimeType time, Evoral::EventType type, uint32_t size, const uint8_t* buf);
|
uint32_t write (TimeType time, Evoral::EventType type, uint32_t size, const uint8_t* buf);
|
||||||
uint32_t read (MidiBuffer& dst, samplepos_t start, samplepos_t end, MidiNoteTracker& tracker, samplecnt_t offset = 0);
|
uint32_t read (MidiBuffer& dst, samplepos_t start, samplepos_t end, MidiNoteTracker& tracker, samplecnt_t offset = 0);
|
||||||
|
void track (MidiStateTracker&, samplepos_t start, samplepos_t end);
|
||||||
|
|
||||||
void dump (uint32_t);
|
void dump (uint32_t);
|
||||||
void reverse ();
|
void reverse ();
|
||||||
|
|
|
@ -65,6 +65,8 @@ DiskReader::DiskReader (Session& s, Track& t, string const& str, Temporal::TimeD
|
||||||
, _declick_offs (0)
|
, _declick_offs (0)
|
||||||
, _declick_enabled (false)
|
, _declick_enabled (false)
|
||||||
, last_refill_loop_start (0)
|
, last_refill_loop_start (0)
|
||||||
|
, _midi_catchup (false)
|
||||||
|
, _need_midi_catchup (false)
|
||||||
{
|
{
|
||||||
file_sample[DataType::AUDIO] = 0;
|
file_sample[DataType::AUDIO] = 0;
|
||||||
file_sample[DataType::MIDI] = 0;
|
file_sample[DataType::MIDI] = 0;
|
||||||
|
@ -1484,6 +1486,14 @@ DiskReader::get_midi_playback (MidiBuffer& dst, samplepos_t start_sample, sample
|
||||||
effective_end = min (effective_start + cnt, loop_end);
|
effective_end = min (effective_start + cnt, loop_end);
|
||||||
assert (effective_end > effective_start);
|
assert (effective_end > effective_start);
|
||||||
|
|
||||||
|
|
||||||
|
if (_midi_catchup && _need_midi_catchup) {
|
||||||
|
MidiStateTracker mst;
|
||||||
|
rtmb->track (mst, effective_start, effective_end);
|
||||||
|
mst.flush (dst, 0, false);
|
||||||
|
_need_midi_catchup = false;
|
||||||
|
}
|
||||||
|
|
||||||
const samplecnt_t this_read = effective_end - effective_start;
|
const samplecnt_t this_read = effective_end - effective_start;
|
||||||
|
|
||||||
DEBUG_TRACE (DEBUG::MidiDiskIO, string_compose ("playback buffer LOOP read, from %1 to %2 (%3)\n", effective_start, effective_end, this_read));
|
DEBUG_TRACE (DEBUG::MidiDiskIO, string_compose ("playback buffer LOOP read, from %1 to %2 (%3)\n", effective_start, effective_end, this_read));
|
||||||
|
@ -1491,7 +1501,7 @@ DiskReader::get_midi_playback (MidiBuffer& dst, samplepos_t start_sample, sample
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
size_t events_read =
|
size_t events_read =
|
||||||
#endif
|
#endif
|
||||||
rtmb->read (*target, effective_start, effective_end, _tracker, offset);
|
rtmb->read (*target, effective_start, effective_end, _tracker, offset);
|
||||||
|
|
||||||
cnt -= this_read;
|
cnt -= this_read;
|
||||||
effective_start += this_read;
|
effective_start += this_read;
|
||||||
|
@ -1511,6 +1521,12 @@ DiskReader::get_midi_playback (MidiBuffer& dst, samplepos_t start_sample, sample
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
DEBUG_TRACE (DEBUG::MidiDiskIO, string_compose ("playback buffer read, from %1 to %2 (%3)\n", start_sample, end_sample, nframes));
|
DEBUG_TRACE (DEBUG::MidiDiskIO, string_compose ("playback buffer read, from %1 to %2 (%3)\n", start_sample, end_sample, nframes));
|
||||||
|
if (_midi_catchup && _need_midi_catchup) {
|
||||||
|
MidiStateTracker mst;
|
||||||
|
rtmb->track (mst, start_sample, end_sample);
|
||||||
|
mst.flush (dst, 0, false);
|
||||||
|
_need_midi_catchup = false;
|
||||||
|
}
|
||||||
DEBUG_RESULT (size_t, events_read, rtmb->read (*target, start_sample, end_sample, _tracker));
|
DEBUG_RESULT (size_t, events_read, rtmb->read (*target, start_sample, end_sample, _tracker));
|
||||||
DEBUG_TRACE (DEBUG::MidiDiskIO, string_compose ("%1 MDS events read %2 range %3 .. %4\n", _name, events_read, playback_sample, playback_sample + nframes));
|
DEBUG_TRACE (DEBUG::MidiDiskIO, string_compose ("%1 MDS events read %2 range %3 .. %4\n", _name, events_read, playback_sample, playback_sample + nframes));
|
||||||
}
|
}
|
||||||
|
@ -1957,3 +1973,9 @@ DiskReader::setup_preloop_buffer ()
|
||||||
++channel;
|
++channel;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DiskReader::set_need_midi_catchup (bool yn)
|
||||||
|
{
|
||||||
|
_need_midi_catchup = yn;
|
||||||
|
}
|
||||||
|
|
|
@ -348,8 +348,6 @@ MidiStateTracker::track (const uint8_t* evbuf)
|
||||||
void
|
void
|
||||||
MidiStateTracker::flush (MidiBuffer& dst, samplepos_t time, bool reset)
|
MidiStateTracker::flush (MidiBuffer& dst, samplepos_t time, bool reset)
|
||||||
{
|
{
|
||||||
/* XXX implement me */
|
|
||||||
|
|
||||||
uint8_t buf[3];
|
uint8_t buf[3];
|
||||||
const size_t n_channels = 16;
|
const size_t n_channels = 16;
|
||||||
const size_t n_controls = 127;
|
const size_t n_controls = 127;
|
||||||
|
@ -377,6 +375,9 @@ MidiStateTracker::flush (MidiBuffer& dst, samplepos_t time, bool reset)
|
||||||
program[chn] = 0x80;
|
program[chn] = 0x80;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* XXX bender */
|
||||||
|
/* XXX pressure */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -251,6 +251,88 @@ item_item_earlier (ARDOUR::RTMidiBuffer::Item const & item, ARDOUR::RTMidiBuffer
|
||||||
return item.timestamp < other.timestamp;
|
return item.timestamp < other.timestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RTMidiBuffer::track (MidiStateTracker& mst, samplepos_t start, samplepos_t end)
|
||||||
|
{
|
||||||
|
Glib::Threads::RWLock::ReaderLock lm (_lock, Glib::Threads::TRY_LOCK);
|
||||||
|
|
||||||
|
if (!lm.locked()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool reverse;
|
||||||
|
Item foo;
|
||||||
|
Item* iend;
|
||||||
|
Item* item;
|
||||||
|
foo.timestamp = start;
|
||||||
|
|
||||||
|
if (start < end) {
|
||||||
|
iend = _data+_size;
|
||||||
|
item = lower_bound (_data, iend, foo, item_item_earlier);
|
||||||
|
reverse = false;
|
||||||
|
} else {
|
||||||
|
iend = _data;
|
||||||
|
--iend; /* yes, this is technically "illegal" but we will never indirect */
|
||||||
|
Item* uend = _data + _size;
|
||||||
|
item = upper_bound (_data, uend, foo, item_item_earlier);
|
||||||
|
|
||||||
|
if (item == uend) {
|
||||||
|
--item;
|
||||||
|
}
|
||||||
|
|
||||||
|
reverse = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((item != iend) && ((reverse && (item->timestamp > end)) || (!reverse && (item->timestamp < end)))) {
|
||||||
|
|
||||||
|
TimeType evtime = item->timestamp;
|
||||||
|
|
||||||
|
/* Adjust event times to be relative to 'start', taking
|
||||||
|
* 'offset' into account.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (reverse) {
|
||||||
|
if (evtime > start) {
|
||||||
|
--item;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (evtime < start) {
|
||||||
|
++item;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t size;
|
||||||
|
uint8_t* addr;
|
||||||
|
|
||||||
|
if (item->bytes[0]) {
|
||||||
|
|
||||||
|
/* more than 3 bytes ... indirect */
|
||||||
|
|
||||||
|
uint32_t offset = item->offset & ~(1<<(CHAR_BIT-1));
|
||||||
|
Blob* blob = reinterpret_cast<Blob*> (&_pool[offset]);
|
||||||
|
|
||||||
|
size = blob->size;
|
||||||
|
addr = blob->data;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
size = Evoral::midi_event_size (item->bytes[1]);
|
||||||
|
addr = &item->bytes[1];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
mst.track (addr);
|
||||||
|
|
||||||
|
if (reverse) {
|
||||||
|
--item;
|
||||||
|
} else {
|
||||||
|
++item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t
|
uint32_t
|
||||||
RTMidiBuffer::read (MidiBuffer& dst, samplepos_t start, samplepos_t end, MidiNoteTracker& tracker, samplecnt_t offset)
|
RTMidiBuffer::read (MidiBuffer& dst, samplepos_t start, samplepos_t end, MidiNoteTracker& tracker, samplecnt_t offset)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue
Block a user