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;
|
||||
|
||||
void set_need_midi_catchup (bool);
|
||||
|
||||
/* 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
|
||||
* transport (and thus effective read position for DiskReaders) to keep
|
||||
|
@ -248,6 +250,9 @@ private:
|
|||
|
||||
samplepos_t last_refill_loop_start;
|
||||
void setup_preloop_buffer ();
|
||||
|
||||
bool _midi_catchup;
|
||||
bool _need_midi_catchup;
|
||||
};
|
||||
|
||||
} // namespace ARDOUR
|
||||
|
|
|
@ -37,6 +37,7 @@ namespace ARDOUR {
|
|||
|
||||
class MidiBuffer;
|
||||
class MidiNoteTracker;
|
||||
class MidiStateTracker;
|
||||
|
||||
/** */
|
||||
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 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 reverse ();
|
||||
|
|
|
@ -65,6 +65,8 @@ DiskReader::DiskReader (Session& s, Track& t, string const& str, Temporal::TimeD
|
|||
, _declick_offs (0)
|
||||
, _declick_enabled (false)
|
||||
, last_refill_loop_start (0)
|
||||
, _midi_catchup (false)
|
||||
, _need_midi_catchup (false)
|
||||
{
|
||||
file_sample[DataType::AUDIO] = 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);
|
||||
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;
|
||||
|
||||
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
|
||||
size_t events_read =
|
||||
#endif
|
||||
rtmb->read (*target, effective_start, effective_end, _tracker, offset);
|
||||
rtmb->read (*target, effective_start, effective_end, _tracker, offset);
|
||||
|
||||
cnt -= this_read;
|
||||
effective_start += this_read;
|
||||
|
@ -1511,6 +1521,12 @@ DiskReader::get_midi_playback (MidiBuffer& dst, samplepos_t start_sample, sample
|
|||
|
||||
} else {
|
||||
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_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;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DiskReader::set_need_midi_catchup (bool yn)
|
||||
{
|
||||
_need_midi_catchup = yn;
|
||||
}
|
||||
|
|
|
@ -348,8 +348,6 @@ MidiStateTracker::track (const uint8_t* evbuf)
|
|||
void
|
||||
MidiStateTracker::flush (MidiBuffer& dst, samplepos_t time, bool reset)
|
||||
{
|
||||
/* XXX implement me */
|
||||
|
||||
uint8_t buf[3];
|
||||
const size_t n_channels = 16;
|
||||
const size_t n_controls = 127;
|
||||
|
@ -377,6 +375,9 @@ MidiStateTracker::flush (MidiBuffer& dst, samplepos_t time, bool reset)
|
|||
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;
|
||||
}
|
||||
|
||||
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
|
||||
RTMidiBuffer::read (MidiBuffer& dst, samplepos_t start, samplepos_t end, MidiNoteTracker& tracker, samplecnt_t offset)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue
Block a user