start removal of NoteFixer code
authorPaul Davis <paul@linuxaudiosystems.com>
Fri, 18 Oct 2019 05:16:55 +0000 (23:16 -0600)
committerPaul Davis <paul@linuxaudiosystems.com>
Sat, 2 Nov 2019 22:32:18 +0000 (16:32 -0600)
Plan is to always read MIDI directly from rendered version. MidiPlaylistSource needs
attention before MidiPlaylist::read() can be removed

libs/ardour/ardour/midi_playlist.h
libs/ardour/ardour/note_fixer.h [deleted file]
libs/ardour/midi_playlist.cc
libs/ardour/note_fixer.cc [deleted file]
libs/ardour/wscript

index ddbbcf7b5e002d70909197546420398aafd0b166..83ba5ecb613a553dedf5e122d99cc55f9cae42e0 100644 (file)
 
 #include <boost/utility.hpp>
 
+#include "evoral/Parameter.hpp"
+
 #include "ardour/ardour.h"
 #include "ardour/midi_cursor.h"
 #include "ardour/midi_model.h"
 #include "ardour/midi_state_tracker.h"
-#include "ardour/note_fixer.h"
 #include "ardour/playlist.h"
 #include "evoral/Note.hpp"
 #include "evoral/Parameter.hpp"
@@ -116,20 +117,8 @@ protected:
        void region_going_away (boost::weak_ptr<Region> region);
 
 private:
-       typedef Evoral::Note<Temporal::Beats> Note;
-       typedef Evoral::Event<samplepos_t>   Event;
-
-       struct RegionTracker : public boost::noncopyable {
-               MidiCursor       cursor;   ///< Cursor (iterator and read state)
-               MidiStateTracker tracker;  ///< Active note tracker
-               NoteFixer        fixer;    ///< Edit compensation
-       };
-
-       typedef std::map< Region*, boost::shared_ptr<RegionTracker> > NoteTrackers;
-
        void dump () const;
 
-       NoteTrackers _note_trackers;
        NoteMode     _note_mode;
        samplepos_t  _read_end;
 
diff --git a/libs/ardour/ardour/note_fixer.h b/libs/ardour/ardour/note_fixer.h
deleted file mode 100644 (file)
index 3e6fea6..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (C) 2017 Paul Davis <paul@linuxaudiosystems.com>
- * Copyright (C) 2019 Robin Gareus <robin@gareus.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef __ardour_note_fixer_h__
-#define __ardour_note_fixer_h__
-
-#include <list>
-
-#include <boost/utility.hpp>
-
-#include "temporal/beats.h"
-
-#include "evoral/Note.hpp"
-
-#include "ardour/midi_model.h"
-#include "ardour/types.h"
-
-namespace Evoral { template<typename Time> class EventSink; }
-
-namespace ARDOUR {
-
-class BeatsSamplesConverter;
-class MidiStateTracker;
-class TempoMap;
-
-/** A tracker and compensator for note edit operations.
- *
- * This monitors edit operations sent to a model that affect active notes
- * during a read, and maintains a queue of synthetic events that should be sent
- * at the start of the next read to maintain coherent MIDI state.
- */
-class NoteFixer : public boost::noncopyable
-{
-public:
-       typedef Evoral::Note<Temporal::Beats> Note;
-
-       ~NoteFixer();
-
-       /** Clear all internal state. */
-       void clear();
-
-       /** Handle a region edit during read.
-        *
-        * This must be called before the command is applied to the model.  Events
-        * are enqueued to compensate for edits which should be later sent with
-        * emit() at the start of the next read.
-        *
-        * @param tempo_map The tempo-map
-        * @param cmd Command to compensate for.
-        * @param origin Timeline position of edited source.
-        * @param pos Current read position (last read end).
-        * @param active_notes currently active notes (read/write)
-        */
-       void prepare(TempoMap&                          tempo_map,
-                    const MidiModel::NoteDiffCommand*  cmd,
-                    samplepos_t                        origin,
-                    samplepos_t                        pos,
-                    std::set< boost::weak_ptr<Note> >& active_notes);
-
-       /** Emit any pending edit compensation events.
-        *
-        * @param dst Destination for events.
-        * @param pos Timestamp to be used for every event, should be the start of
-        * the read block immediately following any calls to prepare().
-        * @param tracker Tracker to update with emitted events.
-        */
-       void emit(Evoral::EventSink<samplepos_t>& dst,
-                 samplepos_t                     pos,
-                 MidiStateTracker&               tracker);
-
-private:
-       typedef Evoral::Event<samplepos_t> Event;
-       typedef std::list<Event*>         Events;
-
-       /** Copy a beats event to a samples event with the given time stamp. */
-       Event* copy_event(samplepos_t time, const Evoral::Event<Temporal::Beats>& ev);
-
-       /** Return true iff `note` is active at `pos`. */
-       bool note_is_active(const BeatsSamplesConverter& converter,
-                           boost::shared_ptr<Note>      note,
-                           samplepos_t                  pos);
-
-       Events _events;
-};
-
-} /* namespace ARDOUR */
-
-#endif /* __ardour_note_fixer_h__ */
index 9144742510378dd1a7d03427338787fa3dbd2850..a7092c45ba12d6708f9c3e92e69af62ccabfb303 100644 (file)
@@ -123,14 +123,7 @@ MidiPlaylist::read (Evoral::EventSink<samplepos_t>& dst,
 
        Playlist::RegionReadLock rl (this);
 
-       DEBUG_TRACE (DEBUG::MidiPlaylistIO,
-                    string_compose ("---- MidiPlaylist::read %1 .. %2 (%3 trackers) ----\n",
-                                    start, start + dur, _note_trackers.size()));
-
-       /* First, emit any queued edit fixup events at start. */
-       for (NoteTrackers::iterator t = _note_trackers.begin(); t != _note_trackers.end(); ++t) {
-               t->second->fixer.emit(dst, _read_end, t->second->tracker);
-       }
+       DEBUG_TRACE (DEBUG::MidiPlaylistIO, string_compose ("---- MidiPlaylist::read %1 .. %2 ----\n", start, start + dur));
 
        /* Find relevant regions that overlap [start..end] */
        const samplepos_t                         end = start + dur - 1;
@@ -184,52 +177,20 @@ MidiPlaylist::read (Evoral::EventSink<samplepos_t>& dst,
                        continue;
                }
 
-               /* Get the existing note tracker for this region, or create a new one. */
-               NoteTrackers::iterator           t           = _note_trackers.find (mr.get());
-               bool                             new_tracker = false;
-               boost::shared_ptr<RegionTracker> tracker;
-               if (t == _note_trackers.end()) {
-                       tracker     = boost::shared_ptr<RegionTracker>(new RegionTracker);
-                       new_tracker = true;
-                       DEBUG_TRACE (DEBUG::MidiPlaylistIO,
-                                    string_compose ("\tPre-read %1 (%2 .. %3): new tracker\n",
-                                                    mr->name(), mr->position(), mr->last_sample()));
-               } else {
-                       tracker = t->second;
-                       DEBUG_TRACE (DEBUG::MidiPlaylistIO,
-                                    string_compose ("\tPre-read %1 (%2 .. %3): %4 active notes\n",
-                                                    mr->name(), mr->position(), mr->last_sample(), tracker->tracker.on()));
-               }
+               MidiCursor cursor; // XXX remove me
 
                /* Read from region into target. */
                DEBUG_TRACE (DEBUG::MidiPlaylistIO, string_compose ("read from %1 at %2 for %3 LR %4 .. %5\n",
                                                                    mr->name(), start, dur,
                                                                    (loop_range ? loop_range->from : -1),
                                                                    (loop_range ? loop_range->to : -1)));
-               mr->read_at (tgt, start, dur, loop_range, tracker->cursor, chan_n, _note_mode, &tracker->tracker, filter);
-               DEBUG_TRACE (DEBUG::MidiPlaylistIO,
-                            string_compose ("\tPost-read: %1 active notes\n", tracker->tracker.on()));
+               mr->read_at (tgt, start, dur, loop_range, cursor, chan_n, _note_mode, 0, filter);
 
                if (find (ended.begin(), ended.end(), *i) != ended.end()) {
                        /* Region ended within the read range, so resolve any active notes
                           (either stuck notes in the data, or notes that end after the end
                           of the region). */
-                       DEBUG_TRACE (DEBUG::MidiPlaylistIO,
-                                    string_compose ("\t%1 ended, resolve notes and delete (%2) tracker\n",
-                                                    mr->name(), ((new_tracker) ? "new" : "old")));
-
-                       tracker->tracker.resolve_notes (tgt, loop_range ? loop_range->squish ((*i)->last_sample()) : (*i)->last_sample());
-                       tracker->cursor.invalidate (false);
-                       if (!new_tracker) {
-                               _note_trackers.erase (t);
-                       }
-
-               } else {
-
-                       if (new_tracker) {
-                               _note_trackers.insert (make_pair (mr.get(), tracker));
-                               DEBUG_TRACE (DEBUG::MidiPlaylistIO, "\tadded tracker to trackers\n");
-                       }
+                       DEBUG_TRACE (DEBUG::MidiPlaylistIO, string_compose ("\t%1 ended, resolve notes and delete\n", mr->name()));
                }
        }
 
@@ -254,29 +215,16 @@ MidiPlaylist::read (Evoral::EventSink<samplepos_t>& dst,
 void
 MidiPlaylist::reset_note_trackers ()
 {
-       Playlist::RegionWriteLock rl (this, false);
-
-       DEBUG_TRACE (DEBUG::MidiTrackers, string_compose ("%1 reset all note trackers\n", name()));
-       _note_trackers.clear ();
 }
 
 void
 MidiPlaylist::resolve_note_trackers (Evoral::EventSink<samplepos_t>& dst, samplepos_t time)
 {
-       Playlist::RegionWriteLock rl (this, false);
-
-       for (NoteTrackers::iterator n = _note_trackers.begin(); n != _note_trackers.end(); ++n) {
-               n->second->tracker.resolve_notes(dst, time);
-       }
-       DEBUG_TRACE (DEBUG::MidiTrackers, string_compose ("%1 resolve all note trackers\n", name()));
-       _note_trackers.clear ();
 }
 
 void
 MidiPlaylist::remove_dependents (boost::shared_ptr<Region> region)
 {
-       /* MIDI regions have no dependents (crossfades) but we might be tracking notes */
-       _note_trackers.erase(region.get());
 }
 
 void
@@ -353,11 +301,6 @@ MidiPlaylist::destroy_region (boost::shared_ptr<Region> region)
 
                        i = tmp;
                }
-
-               NoteTrackers::iterator t = _note_trackers.find(region.get());
-               if (t != _note_trackers.end()) {
-                       _note_trackers.erase(t);
-               }
        }
 
        if (changed) {
diff --git a/libs/ardour/note_fixer.cc b/libs/ardour/note_fixer.cc
deleted file mode 100644 (file)
index 0c6c94b..0000000
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright (C) 2017 Paul Davis <paul@linuxaudiosystems.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include "evoral/EventList.hpp"
-
-#include "ardour/beats_samples_converter.h"
-#include "ardour/midi_state_tracker.h"
-#include "ardour/note_fixer.h"
-#include "ardour/tempo.h"
-
-namespace ARDOUR {
-
-NoteFixer::~NoteFixer()
-{
-       clear();
-}
-
-void
-NoteFixer::clear()
-{
-       for (Events::iterator i = _events.begin(); i != _events.end(); ++i) {
-               delete *i;
-       }
-}
-
-void
-NoteFixer::prepare(TempoMap&                          tempo_map,
-                   const MidiModel::NoteDiffCommand*  cmd,
-                   const samplepos_t                  origin,
-                   const samplepos_t                  pos,
-                   std::set< boost::weak_ptr<Note> >& active_notes)
-{
-       typedef MidiModel::NoteDiffCommand Command;
-
-       BeatsSamplesConverter converter(tempo_map, origin);
-
-       for (Command::NoteList::const_iterator i = cmd->removed_notes().begin();
-            i != cmd->removed_notes().end(); ++i) {
-               if (note_is_active(converter, *i, pos)) {
-                       /* Deleted note spans the end of the latest read, so we will never
-                          read its off event.  Emit a note off to prevent a stuck note. */
-                       _events.push_back(copy_event(pos, (*i)->off_event()));
-                       active_notes.erase(*i);
-               }
-       }
-
-       for (Command::NoteList::const_iterator i = cmd->added_notes().begin();
-            i != cmd->added_notes().end(); ++i) {
-               if (note_is_active(converter, *i, pos)) {
-                       /* Added note spans the end of the latest read, so we missed its on
-                          event.  Emit note on immediately to make the state consistent. */
-                       _events.push_back(copy_event(pos, (*i)->on_event()));
-                       active_notes.insert(*i);
-               }
-       }
-
-       for (Command::ChangeList::const_iterator i = cmd->changes().begin();
-            i != cmd->changes().end(); ++i) {
-               if (!note_is_active(converter, i->note, pos)) {
-                       /* Note is not currently active, no compensation needed. */
-                       continue;
-               }
-
-               /* Changed note spans the end of the latest read. */
-               if (i->property == Command::NoteNumber) {
-                       /* Note number has changed, end the old note. */
-                       _events.push_back(copy_event(pos, i->note->off_event()));
-
-                       /* Start a new note on the new note number.  The same note object
-                          is active, so we leave active_notes alone. */
-                       Event* on = copy_event(pos, i->note->on_event());
-                       on->buffer()[1] = (uint8_t)i->new_value.get_int();
-                       _events.push_back(on);
-               } else if (i->property == Command::StartTime &&
-                          converter.to(i->new_value.get_beats()) >= pos) {
-                       /* Start time has moved from before to after the end of the
-                          latest read, end the old note. */
-                       _events.push_back(copy_event(pos, i->note->off_event()));
-                       active_notes.erase(i->note);
-               } else if (i->property == Command::Length &&
-                          converter.to(i->note->time() + i->new_value.get_beats()) < pos) {
-                       /* Length has shortened to before the end of the latest read,
-                          end the note. */
-                       _events.push_back(copy_event(pos, i->note->off_event()));
-                       active_notes.erase(i->note);
-               } else if (i->property == Command::Channel) {
-                       /* Channel has changed, end the old note. */
-                       _events.push_back(copy_event(pos, i->note->off_event()));
-
-                       /* Start a new note on the new channel.  See number change above. */
-                       Event* on = copy_event(pos, i->note->on_event());
-                       on->buffer()[0] &= 0xF0;
-                       on->buffer()[0] |= (uint8_t)i->new_value.get_int();
-                       _events.push_back(on);
-               }
-       }
-}
-
-void
-NoteFixer::emit(Evoral::EventSink<samplepos_t>& dst,
-                samplepos_t                     pos,
-                MidiStateTracker&               tracker)
-{
-       for (Events::iterator i = _events.begin(); i != _events.end(); ++i) {
-               dst.write(pos, (*i)->event_type(), (*i)->size(), (*i)->buffer());
-               tracker.track(**i);
-               delete *i;
-       }
-       _events.clear();
-}
-
-NoteFixer::Event*
-NoteFixer::copy_event(samplepos_t time, const Evoral::Event<Temporal::Beats>& ev)
-{
-       return new Event(ev.event_type(), time, ev.size(), ev.buffer());
-}
-
-bool
-NoteFixer::note_is_active(const BeatsSamplesConverter& converter,
-                          boost::shared_ptr<Note>      note,
-                          samplepos_t                  pos)
-{
-       const samplepos_t start_time = converter.to(note->time());
-       const samplepos_t end_time   = converter.to(note->end_time());
-
-       return (start_time < pos && end_time >= pos);
-}
-
-} // namespace ARDOUR
index b66c3cf8c0da530745b6c9db996dc7f312d325b0..27fc0ba3e8d532d9d71dcf3a7daf3fe313ac7353 100644 (file)
@@ -153,7 +153,6 @@ libardour_sources = [
         'muteable.cc',
         'mute_control.cc',
         'mute_master.cc',
-        'note_fixer.cc',
         'onset_detector.cc',
         'operations.cc',
         'pan_controllable.cc',