summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--SConstruct4
-rw-r--r--libs/ardour/SConscript1
-rw-r--r--libs/ardour/ardour/event_type_map.h4
-rw-r--r--libs/ardour/ardour/midi_diskstream.h8
-rw-r--r--libs/ardour/ardour/midi_ring_buffer.h14
-rw-r--r--libs/ardour/jack_midi_port.cc6
-rw-r--r--libs/ardour/midi_buffer.cc10
-rw-r--r--libs/ardour/midi_diskstream.cc29
-rw-r--r--libs/ardour/midi_track.cc2
-rw-r--r--libs/ardour/panner.cc6
10 files changed, 61 insertions, 23 deletions
diff --git a/SConstruct b/SConstruct
index 4cd0bc8b53..5c6acea587 100644
--- a/SConstruct
+++ b/SConstruct
@@ -262,9 +262,9 @@ def fetch_git_revision (path):
cmd += "git log --abbrev HEAD^..HEAD "
cmd += path
output = commands.getoutput (cmd)
- output = output.splitlines()
+ output = output.splitlines ()
- rev = output[0].replace( "commit", "git")[0:7]
+ rev = output[0].replace ("commit", "git")[0:10]
for line in output:
try:
if "git-svn-id" in line:
diff --git a/libs/ardour/SConscript b/libs/ardour/SConscript
index fb1d052418..2abf18cd55 100644
--- a/libs/ardour/SConscript
+++ b/libs/ardour/SConscript
@@ -110,6 +110,7 @@ midi_playlist.cc
midi_port.cc
midi_region.cc
midi_source.cc
+midi_state_tracker.cc
midi_stretch.cc
midi_track.cc
mix.cc
diff --git a/libs/ardour/ardour/event_type_map.h b/libs/ardour/ardour/event_type_map.h
index 99911121c5..dfa11d6408 100644
--- a/libs/ardour/ardour/event_type_map.h
+++ b/libs/ardour/ardour/event_type_map.h
@@ -46,6 +46,10 @@ private:
static EventTypeMap event_type_map;
};
+enum InternalEventType {
+ LoopEventType = 1000
+};
+
} // namespace ARDOUR
#endif /* __ardour_event_type_map_h__ */
diff --git a/libs/ardour/ardour/midi_diskstream.h b/libs/ardour/ardour/midi_diskstream.h
index 28e80816a8..a3d4d6d0a4 100644
--- a/libs/ardour/ardour/midi_diskstream.h
+++ b/libs/ardour/ardour/midi_diskstream.h
@@ -46,6 +46,7 @@
#include <ardour/diskstream.h>
#include <ardour/midi_playlist.h>
#include <ardour/midi_ring_buffer.h>
+#include <ardour/midi_state_tracker.h>
struct tm;
@@ -68,7 +69,7 @@ class MidiDiskstream : public Diskstream
float playback_buffer_load() const;
float capture_buffer_load() const;
- void get_playback(MidiBuffer& dst, nframes_t start, nframes_t end);
+ void get_playback(MidiBuffer& dst, nframes_t start, nframes_t end, nframes_t offset);
void set_record_enabled (bool yn);
@@ -170,13 +171,16 @@ class MidiDiskstream : public Diskstream
void engage_record_enable ();
void disengage_record_enable ();
-
+ void check_note_onoffs(Evoral::MIDIEvent &event);
+ void emit_pending_note_offs(MidiBuffer &dst, nframes_t time);
+
MidiRingBuffer* _playback_buf;
MidiRingBuffer* _capture_buf;
MidiPort* _source_port;
boost::shared_ptr<SMFSource> _write_source;
nframes_t _last_flush_frame;
NoteMode _note_mode;
+ MidiStateTracker _midistate_tracker;
};
}; /* namespace ARDOUR */
diff --git a/libs/ardour/ardour/midi_ring_buffer.h b/libs/ardour/ardour/midi_ring_buffer.h
index d1acb9b235..6e827d2852 100644
--- a/libs/ardour/ardour/midi_ring_buffer.h
+++ b/libs/ardour/ardour/midi_ring_buffer.h
@@ -23,6 +23,7 @@
#include <algorithm>
#include <ardour/types.h>
#include <ardour/buffer.h>
+#include <ardour/event_type_map.h>
#include <evoral/EventSink.hpp>
#include <evoral/EventRingBuffer.hpp>
@@ -148,6 +149,18 @@ MidiRingBuffer::read(MidiBuffer& dst, nframes_t start, nframes_t end, nframes_t
continue;
}
+ // This event marks a loop happening. this means that
+ // the next events timestamp will be non-monotonic.
+ if (ev_type == LoopEventType) {
+ ev_time -= start;
+ Evoral::MIDIEvent loopevent(LoopEventType, ev_time);
+ dst.push_back(loopevent);
+
+ // We can safely return, without reading the data, because
+ // a LoopEvent does not have data.
+ return count + 1;
+ }
+
uint8_t status;
success = full_peek(sizeof(uint8_t), &status);
assert(success); // If this failed, buffer is corrupt, all hope is lost
@@ -168,6 +181,7 @@ MidiRingBuffer::read(MidiBuffer& dst, nframes_t start, nframes_t end, nframes_t
assert(ev_time >= start);
ev_time -= start;
+ ev_time += offset;
uint8_t* write_loc = dst.reserve(ev_time, ev_size);
if (write_loc == NULL) {
diff --git a/libs/ardour/jack_midi_port.cc b/libs/ardour/jack_midi_port.cc
index 3c3f50c9bb..4b7b66c659 100644
--- a/libs/ardour/jack_midi_port.cc
+++ b/libs/ardour/jack_midi_port.cc
@@ -110,6 +110,7 @@ JackMidiPort::cycle_end (nframes_t nframes, nframes_t offset)
for (MidiBuffer::iterator i = _buffer->begin(); i != _buffer->end(); ++i) {
const Evoral::Event& ev = *i;
+
// event times should be frames, relative to cycle start
assert(ev.time() >= 0);
assert(ev.time() < nframes);
@@ -133,7 +134,8 @@ JackMidiPort::flush_buffers (nframes_t nframes, nframes_t offset)
const Evoral::Event& ev = *i;
// event times should be frames, relative to cycle start
assert(ev.time() >= 0);
- assert(ev.time() < nframes);
- jack_midi_event_write (jack_buffer, (jack_nframes_t) ev.time(), ev.buffer(), ev.size());
+ assert(ev.time() < (nframes+offset));
+ if (ev.time() >= offset)
+ jack_midi_event_write (jack_buffer, (jack_nframes_t) ev.time(), ev.buffer(), ev.size());
}
}
diff --git a/libs/ardour/midi_buffer.cc b/libs/ardour/midi_buffer.cc
index 6f0620cae1..ae370cdef7 100644
--- a/libs/ardour/midi_buffer.cc
+++ b/libs/ardour/midi_buffer.cc
@@ -110,13 +110,17 @@ MidiBuffer::read_from(const Buffer& src, nframes_t nframes, nframes_t offset)
assert(_capacity >= msrc.size());
- clear();
- assert(_size == 0);
+ if (offset == 0) {
+ clear();
+ assert(_size == 0);
+ }
// FIXME: slow
for (size_t i=0; i < msrc.size(); ++i) {
const Evoral::MIDIEvent& ev = msrc[i];
- if (ev.time() >= offset && ev.time() < offset+nframes) {
+ if (ev.time() < offset)
+ continue;
+ if (ev.time() < (nframes + offset)) {
//cout << "MidiBuffer::read_from got event, " << int(ev.type()) << " time: " << ev.time() << " buffer size: " << _size << endl;
push_back(ev);
} else {
diff --git a/libs/ardour/midi_diskstream.cc b/libs/ardour/midi_diskstream.cc
index 0b79213a23..2372d91c5d 100644
--- a/libs/ardour/midi_diskstream.cc
+++ b/libs/ardour/midi_diskstream.cc
@@ -728,7 +728,7 @@ MidiDiskstream::read (nframes_t& start, nframes_t dur, bool reversed)
position within the loop.
*/
- if (loc && start >= loop_end) {
+ if (loc && (start >= loop_end)) {
//cerr << "start adjusted from " << start;
start = loop_start + ((start - loop_start) % loop_length);
//cerr << "to " << start << endl;
@@ -774,6 +774,9 @@ MidiDiskstream::read (nframes_t& start, nframes_t dur, bool reversed)
/* if we read to the end of the loop, go back to the beginning */
if (reloop) {
+ // Synthesize LoopEvent here, because the next events
+ // written will have non-monotonic timestamps.
+ _playback_buf->write(loop_end - 1, LoopEventType, 0, 0);
start = loop_start;
} else {
start += this_read;
@@ -1435,7 +1438,6 @@ MidiDiskstream::capture_buffer_load () const
(double) _capture_buf->capacity());
}
-
int
MidiDiskstream::use_pending_capture_data (XMLNode& node)
{
@@ -1446,16 +1448,29 @@ MidiDiskstream::use_pending_capture_data (XMLNode& node)
* so that an event at \a start has time = 0
*/
void
-MidiDiskstream::get_playback(MidiBuffer& dst, nframes_t start, nframes_t end)
+MidiDiskstream::get_playback(MidiBuffer& dst, nframes_t start, nframes_t end, nframes_t offset)
{
- dst.clear();
- assert(dst.size() == 0);
+ if (offset == 0) {
+ dst.clear();
+ assert(dst.size() == 0);
+ }
// Reverse. ... We just don't do reverse, ok? Back off.
if (end <= start) {
return;
}
- // Translates stamps to be relative to start
- _playback_buf->read(dst, start, end);
+ // Check only events added this offset cycle
+ MidiBuffer::iterator this_cycle_start = dst.end();
+
+ // Translates stamps to be relative to start, but add offset.
+ _playback_buf->read(dst, start, end, offset);
+
+
+ // Now feed the data through the MidiStateTracker.
+ // In case it detects a LoopEvent it will add necessary note
+ // offs.
+
+ if (_midistate_tracker.track(this_cycle_start, dst.end()))
+ _midistate_tracker.resolve_notes(dst, end-start - 1 + offset);
}
diff --git a/libs/ardour/midi_track.cc b/libs/ardour/midi_track.cc
index 662d19df3c..0a253f3963 100644
--- a/libs/ardour/midi_track.cc
+++ b/libs/ardour/midi_track.cc
@@ -510,7 +510,7 @@ MidiTrack::roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
//const size_t limit = n_process_buffers().n_audio();
BufferSet& bufs = _session.get_scratch_buffers (n_process_buffers());
- diskstream->get_playback(bufs.get_midi(0), start_frame, end_frame);
+ diskstream->get_playback(bufs.get_midi(0), start_frame, end_frame, offset);
process_output_buffers (bufs, start_frame, end_frame, nframes, offset,
(!_session.get_record_enabled() || !Config->get_do_not_record_plugins()), declick, (_meter_point != MeterInput));
diff --git a/libs/ardour/panner.cc b/libs/ardour/panner.cc
index 6a6a840407..fe0a792b6b 100644
--- a/libs/ardour/panner.cc
+++ b/libs/ardour/panner.cc
@@ -970,12 +970,6 @@ Panner::state (bool full)
node.add_property (X_("link_direction"), enum_2_string (_link_direction));
node.add_property (X_("bypassed"), (bypassed() ? "yes" : "no"));
- snprintf (buf, sizeof (buf), "%d", _streampanners.size());
- node.add_property (X_("ins"), buf);
- snprintf (buf, sizeof (buf), "%d", outputs.size());
- node.add_property (X_("outs"), buf);
- /* add each output */
-
for (vector<Panner::Output>::iterator o = outputs.begin(); o != outputs.end(); ++o) {
XMLNode* onode = new XMLNode (X_("Output"));
snprintf (buf, sizeof (buf), "%.12g", (*o).x);