#include <unistd.h>
#include <errno.h>
-#include <pbd/mountpoint.h>
-#include <pbd/pathscanner.h>
-#include <pbd/stl_delete.h>
-#include <pbd/strsplit.h>
+#include "pbd/mountpoint.h"
+#include "pbd/pathscanner.h"
+#include "pbd/stl_delete.h"
+#include "pbd/strsplit.h"
#include <glibmm/miscutils.h>
-#include <evoral/SMFReader.hpp>
-#include <evoral/Control.hpp>
+#include "evoral/SMFReader.hpp"
+#include "evoral/Control.hpp"
-#include <ardour/audioengine.h>
-#include <ardour/event_type_map.h>
-#include <ardour/midi_model.h>
-#include <ardour/midi_ring_buffer.h>
-#include <ardour/session.h>
-#include <ardour/smf_source.h>
+#include "ardour/audioengine.h"
+#include "ardour/event_type_map.h"
+#include "ardour/midi_model.h"
+#include "ardour/midi_ring_buffer.h"
+#include "ardour/session.h"
+#include "ardour/smf_source.h"
#include "i18n.h"
/** All stamps in audio frames */
nframes_t
-SMFSource::read_unlocked (MidiRingBuffer<nframes_t>& dst, nframes_t start, nframes_t dur,
- nframes_t stamp_offset, nframes_t negative_stamp_offset) const
+SMFSource::read_unlocked (MidiRingBuffer<nframes_t>& destination, sframes_t source_start,
+ sframes_t start, nframes_t duration,
+ sframes_t stamp_offset, sframes_t negative_stamp_offset) const
{
int ret = 0;
uint64_t time = 0; // in SMF ticks, 1 tick per _ppqn
uint8_t* ev_buffer = 0;
size_t scratch_size = 0; // keep track of scratch to minimize reallocs
+
+ BeatsFramesConverter converter(_session, source_start);
- const uint64_t start_ticks = (uint64_t)(_converter.from(start) * ppqn());
+ const uint64_t start_ticks = (uint64_t)(converter.from(start) * ppqn());
if (_last_read_end == 0 || start != _last_read_end) {
- cerr << "SMFSource::read_unlocked seeking to " << start << endl;
+ //cerr << "SMFSource::read_unlocked seeking to " << start << endl;
Evoral::SMF::seek_to_start();
while (time < start_ticks) {
ret = read_event(&ev_delta_t, &ev_size, &ev_buffer);
if (ret == -1) { // EOF
- _last_read_end = start + dur;
- return dur;
+ _last_read_end = start + duration;
+ return duration;
}
time += ev_delta_t; // accumulate delta time
}
}
- _last_read_end = start + dur;
+ _last_read_end = start + duration;
while (true) {
ret = read_event(&ev_delta_t, &ev_size, &ev_buffer);
ev_type = EventTypeMap::instance().midi_event_type(ev_buffer[0]);
assert(time >= start_ticks);
- const nframes_t ev_frame_time = _converter.to(time / (double)ppqn()) + stamp_offset;
+ const sframes_t ev_frame_time = converter.to(time / (double)ppqn()) + stamp_offset;
- if (ev_frame_time < start + dur) {
- dst.write(ev_frame_time - negative_stamp_offset, ev_type, ev_size, ev_buffer);
+ if (ev_frame_time < start + duration) {
+ destination.write(ev_frame_time - negative_stamp_offset, ev_type, ev_size, ev_buffer);
} else {
break;
}
ev_size = scratch_size; // ensure read_event only allocates if necessary
}
- return dur;
+ return duration;
}
/** All stamps in audio frames */
nframes_t
-SMFSource::write_unlocked (MidiRingBuffer<nframes_t>& src, nframes_t dur)
+SMFSource::write_unlocked (MidiRingBuffer<nframes_t>& source, sframes_t position, nframes_t duration)
{
_write_data_count = 0;
_model->start_write();
}
- Evoral::MIDIEvent<nframes_t> ev(0, 0.0, 4, NULL, true);
+ Evoral::MIDIEvent<nframes_t> ev;
while (true) {
- bool ret = src.peek_time(&time);
- if (!ret || time - _timeline_position > _length + dur) {
+ bool ret = source.peek_time(&time);
+ if (!ret || time > _last_write_end + duration) {
break;
}
- ret = src.read_prefix(&time, &type, &size);
+ ret = source.read_prefix(&time, &type, &size);
if (!ret) {
+ cerr << "ERROR: Unable to read event prefix, corrupt MIDI ring buffer" << endl;
break;
}
buf = (uint8_t*)realloc(buf, size);
}
- ret = src.read_contents(size, buf);
+ ret = source.read_contents(size, buf);
if (!ret) {
cerr << "ERROR: Read time/size but not buffer, corrupt MIDI ring buffer" << endl;
break;
}
- assert(time >= _timeline_position);
- time -= _timeline_position;
+ assert(time >= position);
+ time -= position;
ev.set(buf, size, time);
ev.set_event_type(EventTypeMap::instance().midi_event_type(ev.buffer()[0]));
continue;
}
- append_event_unlocked_frames(ev);
+ append_event_unlocked_frames(ev, position);
}
if (_model) {
Evoral::SMF::flush();
free(buf);
- const nframes_t oldlen = _length;
- update_length(oldlen, dur);
-
- ViewDataRangeReady(_timeline_position + oldlen, dur); /* EMIT SIGNAL */
+ ViewDataRangeReady(position + _last_write_end, duration); /* EMIT SIGNAL */
- return dur;
+ return duration;
}
return;
}
+ _length_beats = max(_length_beats, ev.time());
+
const double delta_time_beats = ev.time() - _last_ev_time_beats;
const uint32_t delta_time_ticks = (uint32_t)lrint(delta_time_beats * (double)ppqn());
/** Append an event with a timestamp in frames (nframes_t) */
void
-SMFSource::append_event_unlocked_frames (const Evoral::Event<nframes_t>& ev)
+SMFSource::append_event_unlocked_frames (const Evoral::Event<nframes_t>& ev, sframes_t position)
{
if (ev.size() == 0) {
return;
name().c_str(), ev.time(), ev.size());
for (size_t i=0; i < ev.size(); ++i) printf("%X ", ev.buffer()[i]); printf("\n");*/
- assert(ev.time() >= 0);
if (ev.time() < _last_ev_time_frames) {
cerr << "SMFSource: Warning: Skipping event with non-monotonic time" << endl;
return;
}
- const nframes_t delta_time_frames = ev.time() - _last_ev_time_frames;
- const double delta_time_beats = _converter.from(delta_time_frames);
+ BeatsFramesConverter converter(_session, position);
+
+ _length_beats = max(_length_beats, converter.from(ev.time()));
+
+ const sframes_t delta_time_frames = ev.time() - _last_ev_time_frames;
+ const double delta_time_beats = converter.from(delta_time_frames);
const uint32_t delta_time_ticks = (uint32_t)(lrint(delta_time_beats * (double)ppqn()));
Evoral::SMF::append_event_delta(delta_time_ticks, ev.size(), ev.buffer());
_write_data_count += ev.size();
if (_model) {
- const double ev_time_beats = _converter.from(ev.time());
+ const double ev_time_beats = converter.from(ev.time());
const Evoral::Event<double> beat_ev(
ev.event_type(), ev_time_beats, ev.size(), (uint8_t*)ev.buffer());
_model->append(beat_ev);
}
void
-SMFSource::mark_streaming_midi_write_started (NoteMode mode, nframes_t start_frame)
+SMFSource::mark_streaming_midi_write_started (NoteMode mode, sframes_t start_frame)
{
MidiSource::mark_streaming_midi_write_started (mode, start_frame);
Evoral::SMF::begin_write ();
if (! _model) {
_model = boost::shared_ptr<MidiModel>(new MidiModel(this));
- cerr << _name << " loaded new model " << _model.get() << endl;
+ //cerr << _name << " loaded new model " << _model.get() << endl;
} else {
- cerr << _name << " reloading model " << _model.get()
- << " (" << _model->n_notes() << " notes)" <<endl;
+ /*cerr << _name << " reloading model " << _model.get()
+ << " (" << _model->n_notes() << " notes)" << endl;*/
_model->clear();
}
scratch_size = ev.size();
}
ev.size() = scratch_size; // ensure read_event only allocates if necessary
+
+ _length_beats = max(_length_beats, ev.time());
}
set_default_controls_interpolation();