Add a new ::render() method to MidiSource that writes to an EventSink
This commit is contained in:
parent
0986b8d1e8
commit
b693d07fcb
@ -109,6 +109,7 @@ class LIBARDOUR_API MidiSource : virtual public Source
|
|||||||
MidiNoteTracker* tracker,
|
MidiNoteTracker* tracker,
|
||||||
MidiChannelFilter* filter,
|
MidiChannelFilter* filter,
|
||||||
const std::set<Evoral::Parameter>& filtered);
|
const std::set<Evoral::Parameter>& filtered);
|
||||||
|
virtual void render (const ReaderLock& lock, Evoral::EventSink<Temporal::Beats>& dst) = 0;
|
||||||
|
|
||||||
/** Write data from a MidiRingBuffer to this source.
|
/** Write data from a MidiRingBuffer to this source.
|
||||||
* @param lock Reference to the Mutex to lock before modification
|
* @param lock Reference to the Mutex to lock before modification
|
||||||
|
@ -79,6 +79,8 @@ public:
|
|||||||
/** Query the smf file for its channel info */
|
/** Query the smf file for its channel info */
|
||||||
SMF::UsedChannels used_midi_channels();
|
SMF::UsedChannels used_midi_channels();
|
||||||
|
|
||||||
|
void render (const ReaderLock& lock, Evoral::EventSink<Temporal::Beats>& dst);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void close ();
|
void close ();
|
||||||
void flush_midi (const WriterLock& lock);
|
void flush_midi (const WriterLock& lock);
|
||||||
|
@ -217,6 +217,62 @@ SMFSource::close ()
|
|||||||
|
|
||||||
extern PBD::Timing minsert;
|
extern PBD::Timing minsert;
|
||||||
|
|
||||||
|
void
|
||||||
|
SMFSource::render (const ReaderLock& lock, Evoral::EventSink<Temporal::Beats>& destination)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
Temporal::Beats time; // in SMF ticks, 1 tick per _ppqn
|
||||||
|
|
||||||
|
if (writable() && !_open) {
|
||||||
|
/* nothing to read since nothing has ben written */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output parameters for read_event (which will allocate scratch in buffer as needed)
|
||||||
|
uint32_t ev_delta_t = 0;
|
||||||
|
uint32_t ev_size = 0;
|
||||||
|
uint8_t* ev_buffer = 0;
|
||||||
|
size_t scratch_size = 0; // keep track of scratch to minimize reallocs
|
||||||
|
|
||||||
|
/* start of read in SMF ticks (which may differ from our own musical ticks */
|
||||||
|
|
||||||
|
Evoral::SMF::seek_to_start();
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
|
||||||
|
Evoral::event_id_t ignored; /* XXX don't ignore note id's ??*/
|
||||||
|
|
||||||
|
ret = read_event (&ev_delta_t, &ev_size, &ev_buffer, &ignored);
|
||||||
|
|
||||||
|
if (ret == -1) { // EOF
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret == 0) { // meta-event (skipped, just accumulate time)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
time += Temporal::Beats::ticks_at_rate (ev_delta_t, ppqn()); // accumulate delta time
|
||||||
|
|
||||||
|
DEBUG_TRACE (DEBUG::MidiSourceIO, string_compose ("SMF render delta %1, time %2, buf[0] %3\n",
|
||||||
|
ev_delta_t, time, ev_buffer[0]));
|
||||||
|
|
||||||
|
/* Note that we add on the source start time (in session samples) here so that ev_sample_time
|
||||||
|
is in session samples.
|
||||||
|
*/
|
||||||
|
destination.write (time, Evoral::MIDI_EVENT, ev_size, ev_buffer);
|
||||||
|
|
||||||
|
if (ev_size > scratch_size) {
|
||||||
|
scratch_size = ev_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
ev_size = scratch_size; // ensure read_event only allocates if necessary
|
||||||
|
}
|
||||||
|
|
||||||
|
_smf_last_read_end = time;
|
||||||
|
_smf_last_read_time = time;
|
||||||
|
}
|
||||||
|
|
||||||
timecnt_t
|
timecnt_t
|
||||||
SMFSource::read_unlocked (const ReaderLock& lock,
|
SMFSource::read_unlocked (const ReaderLock& lock,
|
||||||
Evoral::EventSink<samplepos_t>& destination,
|
Evoral::EventSink<samplepos_t>& destination,
|
||||||
|
Loading…
Reference in New Issue
Block a user