diff options
author | Paul Davis <paul@linuxaudiosystems.com> | 2009-09-11 13:25:31 +0000 |
---|---|---|
committer | Paul Davis <paul@linuxaudiosystems.com> | 2009-09-11 13:25:31 +0000 |
commit | d98302ae2c9040dd61573739b3bbdc708d1dd54e (patch) | |
tree | 21081910c79cccea718bf2f07d630f9242f5b359 | |
parent | 65c5e7ae47fca8a38c35def99a28e99dc18fa52d (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.cc | 1 | ||||
-rw-r--r-- | libs/ardour/ardour/midi_diskstream.h | 3 | ||||
-rw-r--r-- | libs/ardour/ardour/midi_state_tracker.h | 4 | ||||
-rw-r--r-- | libs/ardour/ardour/midi_track.h | 5 | ||||
-rw-r--r-- | libs/ardour/midi_diskstream.cc | 9 | ||||
-rw-r--r-- | libs/ardour/midi_state_tracker.cc | 35 | ||||
-rw-r--r-- | libs/ardour/midi_track.cc | 31 |
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) { |