summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2009-09-11 13:25:31 +0000
committerPaul Davis <paul@linuxaudiosystems.com>2009-09-11 13:25:31 +0000
commitd98302ae2c9040dd61573739b3bbdc708d1dd54e (patch)
tree21081910c79cccea718bf2f07d630f9242f5b359
parent65c5e7ae47fca8a38c35def99a28e99dc18fa52d (diff)
track note on/off and send appropriate note offs at transport stop
git-svn-id: svn://localhost/ardour2/branches/3.0@5655 d708f5d6-7413-0410-9779-e7cbd77b26cf
-rw-r--r--gtk2_ardour/midi_region_view.cc1
-rw-r--r--libs/ardour/ardour/midi_diskstream.h3
-rw-r--r--libs/ardour/ardour/midi_state_tracker.h4
-rw-r--r--libs/ardour/ardour/midi_track.h5
-rw-r--r--libs/ardour/midi_diskstream.cc9
-rw-r--r--libs/ardour/midi_state_tracker.cc35
-rw-r--r--libs/ardour/midi_track.cc31
7 files changed, 54 insertions, 34 deletions
diff --git a/gtk2_ardour/midi_region_view.cc b/gtk2_ardour/midi_region_view.cc
index 6acbacc439..9fdd71922e 100644
--- a/gtk2_ardour/midi_region_view.cc
+++ b/gtk2_ardour/midi_region_view.cc
@@ -585,6 +585,7 @@ MidiRegionView::display_model(boost::shared_ptr<MidiModel> model)
_model = model;
content_connection.disconnect ();
content_connection = _model->ContentsChanged.connect(sigc::mem_fun(this, &MidiRegionView::redisplay_model));
+ clear_events ();
if (_enable_display) {
redisplay_model();
diff --git a/libs/ardour/ardour/midi_diskstream.h b/libs/ardour/ardour/midi_diskstream.h
index 872ffb78e3..730d6c0276 100644
--- a/libs/ardour/ardour/midi_diskstream.h
+++ b/libs/ardour/ardour/midi_diskstream.h
@@ -39,7 +39,6 @@
#include "ardour/diskstream.h"
#include "ardour/midi_playlist.h"
#include "ardour/midi_ring_buffer.h"
-#include "ardour/midi_state_tracker.h"
#include "ardour/utils.h"
struct tm;
@@ -178,8 +177,6 @@ class MidiDiskstream : public Diskstream
boost::shared_ptr<SMFSource> _write_source;
nframes_t _last_flush_frame;
NoteMode _note_mode;
- MidiStateTracker _midi_state_tracker;
- MidiStateTracker _incoming_midi_state_tracker;
volatile gint _frames_written_to_ringbuffer;
volatile gint _frames_read_from_ringbuffer;
};
diff --git a/libs/ardour/ardour/midi_state_tracker.h b/libs/ardour/ardour/midi_state_tracker.h
index 4c15ab1e0f..f9b39f9295 100644
--- a/libs/ardour/ardour/midi_state_tracker.h
+++ b/libs/ardour/ardour/midi_state_tracker.h
@@ -35,7 +35,7 @@ class MidiStateTracker
public:
MidiStateTracker();
- bool track (const MidiBuffer::iterator& from, const MidiBuffer::iterator& to);
+ void track (const MidiBuffer::iterator& from, const MidiBuffer::iterator& to, bool& looped);
void resolve_notes (MidiBuffer& buffer, nframes_t time);
void dump (std::ostream&);
void reset ();
@@ -43,7 +43,7 @@ public:
private:
void track_note_onoffs(const Evoral::MIDIEvent<MidiBuffer::TimeType>& event);
- std::bitset<128*16> _active_notes;
+ uint8_t _active_notes[128*16];
};
diff --git a/libs/ardour/ardour/midi_track.h b/libs/ardour/ardour/midi_track.h
index 0030fdc520..a1b0d2003e 100644
--- a/libs/ardour/ardour/midi_track.h
+++ b/libs/ardour/ardour/midi_track.h
@@ -22,6 +22,7 @@
#include "ardour/track.h"
#include "ardour/midi_ring_buffer.h"
+#include "ardour/midi_state_tracker.h"
namespace ARDOUR
{
@@ -41,6 +42,8 @@ public:
int roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame,
int declick, bool can_record, bool rec_monitors_input);
+ void handle_transport_stopped (bool abort, bool did_locate, bool flush_processors);
+
boost::shared_ptr<MidiDiskstream> midi_diskstream() const;
int use_diskstream (string name);
@@ -96,6 +99,8 @@ private:
void set_state_part_two ();
void set_state_part_three ();
+ MidiStateTracker _midi_state_tracker;
+
MidiRingBuffer<nframes_t> _immediate_events;
MidiRingBuffer<nframes_t> _step_edit_ring_buffer;
NoteMode _note_mode;
diff --git a/libs/ardour/midi_diskstream.cc b/libs/ardour/midi_diskstream.cc
index 3d4b188a8b..b486a0fce0 100644
--- a/libs/ardour/midi_diskstream.cc
+++ b/libs/ardour/midi_diskstream.cc
@@ -1648,9 +1648,6 @@ MidiDiskstream::get_playback (MidiBuffer& dst, nframes_t start, nframes_t end)
return;
}
- // Check only events added this offset cycle
- MidiBuffer::iterator this_cycle_start = dst.end();
-
// Translates stamps to be relative to start
_playback_buf->read(dst, start, end);
@@ -1664,11 +1661,5 @@ MidiDiskstream::get_playback (MidiBuffer& dst, nframes_t start, nframes_t end)
gint32 frames_read = end - start;
g_atomic_int_add(&_frames_read_from_ringbuffer, frames_read);
-
- // Feed the data through the MidiStateTracker
- // If it detects a LoopEvent it will add necessary note offs
- if (_midi_state_tracker.track(this_cycle_start, dst.end())) {
- _midi_state_tracker.resolve_notes(dst, end-start - 1);
- }
}
diff --git a/libs/ardour/midi_state_tracker.cc b/libs/ardour/midi_state_tracker.cc
index 66d356f9a6..e25dbdd094 100644
--- a/libs/ardour/midi_state_tracker.cc
+++ b/libs/ardour/midi_state_tracker.cc
@@ -27,59 +27,55 @@ using namespace ARDOUR;
MidiStateTracker::MidiStateTracker ()
{
- _active_notes.reset();
+ reset ();
}
void
MidiStateTracker::reset ()
{
- _active_notes.reset ();
+ memset (_active_notes, 0, sizeof (_active_notes));
}
void
MidiStateTracker::track_note_onoffs (const Evoral::MIDIEvent<MidiBuffer::TimeType>& event)
{
if (event.is_note_on()) {
- _active_notes [event.note() + 128 * event.channel()] = true;
+ _active_notes [event.note() + 128 * event.channel()]++;
} else if (event.is_note_off()){
- _active_notes [event.note() + 128 * event.channel()] = false;
+ if (_active_notes[event.note() + 128 * event.channel()]) {
+ _active_notes [event.note() + 128 * event.channel()]--;
+ }
}
}
-bool
-MidiStateTracker::track (const MidiBuffer::iterator &from, const MidiBuffer::iterator &to)
+void
+MidiStateTracker::track (const MidiBuffer::iterator &from, const MidiBuffer::iterator &to, bool& looped)
{
- bool ret = false;
+ looped = false;
for (MidiBuffer::iterator i = from; i != to; ++i) {
const Evoral::MIDIEvent<MidiBuffer::TimeType> ev(*i, false);
if (ev.event_type() == LoopEventType) {
- ret = true;
+ looped = true;
continue;
}
track_note_onoffs (ev);
}
- return ret;
}
void
MidiStateTracker::resolve_notes (MidiBuffer &dst, nframes_t time)
{
- // Dunno if this is actually faster but at least it fills our cacheline.
- if (_active_notes.none ())
- return;
-
for (int channel = 0; channel < 16; ++channel) {
for (int note = 0; note < 128; ++note) {
- if (_active_notes[channel * 128 + note]) {
+ while (_active_notes[channel * 128 + note]) {
uint8_t buffer[3] = { MIDI_CMD_NOTE_OFF | channel, note, 0 };
Evoral::MIDIEvent<MidiBuffer::TimeType> noteoff
- (time, MIDI_CMD_NOTE_OFF, 3, buffer, false);
-
+ (time, MIDI_CMD_NOTE_OFF, 3, buffer, false);
+
dst.push_back (noteoff);
-
- _active_notes [channel * 128 + note] = false;
+ _active_notes[channel * 128 + note]--;
}
}
}
@@ -92,7 +88,8 @@ MidiStateTracker::dump (ostream& o)
for (int c = 0; c < 16; ++c) {
for (int x = 0; x < 128; ++x) {
if (_active_notes[c * 128 + x]) {
- o << "Channel " << c+1 << " Note " << x << " is on\n";
+ o << "Channel " << c+1 << " Note " << x << " is on ("
+ << (int) _active_notes[c*128+x] << "times)\n";
}
}
}
diff --git a/libs/ardour/midi_track.cc b/libs/ardour/midi_track.cc
index 876187656c..7324196512 100644
--- a/libs/ardour/midi_track.cc
+++ b/libs/ardour/midi_track.cc
@@ -441,15 +441,27 @@ MidiTrack::roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame,
//const size_t limit = n_process_buffers().n_audio();
BufferSet& bufs = _session.get_scratch_buffers (n_process_buffers());
+ MidiBuffer& mbuf (bufs.get_midi (0));
- diskstream->get_playback (bufs.get_midi(0), start_frame, end_frame);
+ diskstream->get_playback (mbuf, start_frame, end_frame);
/* append immediate messages to the first MIDI buffer (thus sending it to the first output port) */
write_out_of_band_data (bufs, start_frame, end_frame, nframes);
+ // Feed the data through the MidiStateTracker
+ bool did_loop;
+
+ _midi_state_tracker.track (mbuf.begin(), mbuf.end(), did_loop);
+
+ if (did_loop) {
+ /* add necessary note offs */
+ _midi_state_tracker.resolve_notes (mbuf, end_frame-start_frame - 1);
+ }
+
process_output_buffers (bufs, start_frame, end_frame, nframes,
(!_session.get_record_enabled() || !Config->get_do_not_record_plugins()), declick);
+
}
_main_outs->flush (nframes);
@@ -470,6 +482,23 @@ MidiTrack::no_roll (nframes_t nframes, sframes_t start_frame, sframes_t end_fram
return ret;
}
+void
+MidiTrack::handle_transport_stopped (bool abort, bool did_locate, bool flush_processors)
+{
+ /* turn off any notes that are on */
+
+ MidiBuffer buf (1024); // XXX is this a reasonable size ?
+
+ _midi_state_tracker.resolve_notes (buf, 0); // time is zero because notes are immediate
+
+ for (MidiBuffer::iterator i = buf.begin(); i != buf.end(); ++i) {
+ write_immediate_event ((*i).size(), (*i).buffer());
+ }
+
+ Route::handle_transport_stopped (abort, did_locate, flush_processors);
+}
+
+
void
MidiTrack::push_midi_input_to_step_edit_ringbuffer (nframes_t nframes)
{