diff options
author | Carl Hetherington <carl@carlh.net> | 2010-07-14 00:58:15 +0000 |
---|---|---|
committer | Carl Hetherington <carl@carlh.net> | 2010-07-14 00:58:15 +0000 |
commit | 593b421180290f46f39efcb21ed8192b624bbc73 (patch) | |
tree | f8a81aad5fae8683818103b192d3c53a26110728 /libs/evoral | |
parent | b75977920e7cb02ae31bca0379dd3aa4d82f9cbc (diff) |
A few fixes to interpolation of MIDI controller data. Don't interpolate
when writing these data back to a source, otherwise surprising new
interpolated points appear in MIDI automation. Similarly don't interpolate
when reading the model during MIDI stretch. Fix handling of interpolation state;
controllers that have been set by the user to use a different interpolation style
are noted in the <Source> tag of the session file and this state is sprayed around
to MidiModel and the GUI as necessary.
git-svn-id: svn://localhost/ardour2/branches/3.0@7409 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs/evoral')
-rw-r--r-- | libs/evoral/evoral/ControlList.hpp | 6 | ||||
-rw-r--r-- | libs/evoral/evoral/ControlSet.hpp | 5 | ||||
-rw-r--r-- | libs/evoral/evoral/Sequence.hpp | 7 | ||||
-rw-r--r-- | libs/evoral/src/ControlList.cpp | 16 | ||||
-rw-r--r-- | libs/evoral/src/ControlSet.cpp | 7 | ||||
-rw-r--r-- | libs/evoral/src/Sequence.cpp | 23 |
6 files changed, 49 insertions, 15 deletions
diff --git a/libs/evoral/evoral/ControlList.hpp b/libs/evoral/evoral/ControlList.hpp index 5f842775ee..d207c76925 100644 --- a/libs/evoral/evoral/ControlList.hpp +++ b/libs/evoral/evoral/ControlList.hpp @@ -218,6 +218,7 @@ public: bool rt_safe_earliest_event (double start, double end, double& x, double& y, bool start_inclusive=false) const; bool rt_safe_earliest_event_unlocked (double start, double end, double& x, double& y, bool start_inclusive=false) const; + bool rt_safe_earliest_event_discrete_unlocked (double start, double end, double& x, double& y, bool inclusive) const; void create_curve(); void destroy_curve(); @@ -234,10 +235,12 @@ public: }; InterpolationStyle interpolation() const { return _interpolation; } - void set_interpolation(InterpolationStyle style) { _interpolation = style; } + void set_interpolation (InterpolationStyle); /** Emitted when mark_dirty() is called on this object */ mutable PBD::Signal0<void> Dirty; + /** Emitted when our interpolation style changes */ + PBD::Signal1<void, InterpolationStyle> InterpolationChanged; protected: @@ -246,7 +249,6 @@ protected: void build_search_cache_if_necessary(double start, double end) const; - bool rt_safe_earliest_event_discrete_unlocked (double start, double end, double& x, double& y, bool inclusive) const; bool rt_safe_earliest_event_linear_unlocked (double start, double end, double& x, double& y, bool inclusive) const; boost::shared_ptr<ControlList> cut_copy_clear (double, double, int op); diff --git a/libs/evoral/evoral/ControlSet.hpp b/libs/evoral/evoral/ControlSet.hpp index b775bb3b4b..95de58dead 100644 --- a/libs/evoral/evoral/ControlSet.hpp +++ b/libs/evoral/evoral/ControlSet.hpp @@ -27,11 +27,11 @@ #include "pbd/signals.h" #include "evoral/types.hpp" #include "evoral/Parameter.hpp" +#include "evoral/ControlList.hpp" namespace Evoral { class Control; -class ControlList; class ControlEvent; class ControlSet : public boost::noncopyable { @@ -69,12 +69,15 @@ public: protected: virtual void control_list_marked_dirty () {} + virtual void control_list_interpolation_changed (Parameter, ControlList::InterpolationStyle) {} mutable Glib::Mutex _control_lock; Controls _controls; private: + PBD::ScopedConnectionList _control_connections; + PBD::ScopedConnectionList _list_connections; }; diff --git a/libs/evoral/evoral/Sequence.hpp b/libs/evoral/evoral/Sequence.hpp index 3cddeb38ca..24a3c44625 100644 --- a/libs/evoral/evoral/Sequence.hpp +++ b/libs/evoral/evoral/Sequence.hpp @@ -185,7 +185,7 @@ public: class const_iterator { public: const_iterator(); - const_iterator(const Sequence<Time>& seq, Time t, std::set<Evoral::Parameter> const &); + const_iterator(const Sequence<Time>& seq, Time t, bool, std::set<Evoral::Parameter> const &); ~const_iterator(); inline bool valid() const { return !_is_end && _event; } @@ -220,10 +220,11 @@ public: typename SysExes::const_iterator _sysex_iter; ControlIterators _control_iters; ControlIterators::iterator _control_iter; + bool _force_discrete; }; - const_iterator begin (Time t=0, std::set<Evoral::Parameter> const & f = std::set<Evoral::Parameter> ()) const { - return const_iterator (*this, t, f); + const_iterator begin (Time t = 0, bool force_discrete = false, std::set<Evoral::Parameter> const & f = std::set<Evoral::Parameter> ()) const { + return const_iterator (*this, t, force_discrete, f); } const const_iterator& end() const { return _end_iter; } diff --git a/libs/evoral/src/ControlList.cpp b/libs/evoral/src/ControlList.cpp index 3eb6c7d4ce..bfe4c95365 100644 --- a/libs/evoral/src/ControlList.cpp +++ b/libs/evoral/src/ControlList.cpp @@ -954,10 +954,11 @@ ControlList::rt_safe_earliest_event(double start, double end, double& x, double& bool ControlList::rt_safe_earliest_event_unlocked(double start, double end, double& x, double& y, bool inclusive) const { - if (_interpolation == Discrete) + if (_interpolation == Discrete) { return rt_safe_earliest_event_discrete_unlocked(start, end, x, y, inclusive); - else + } else { return rt_safe_earliest_event_linear_unlocked(start, end, x, y, inclusive); + } } @@ -1356,5 +1357,16 @@ ControlList::move_ranges (const list< RangeMove<double> >& movements) maybe_signal_changed (); } +void +ControlList::set_interpolation (InterpolationStyle s) +{ + if (_interpolation == s) { + return; + } + + _interpolation = s; + InterpolationChanged (s); /* EMIT SIGNAL */ +} + } // namespace Evoral diff --git a/libs/evoral/src/ControlSet.cpp b/libs/evoral/src/ControlSet.cpp index d985e347d7..6142f08870 100644 --- a/libs/evoral/src/ControlSet.cpp +++ b/libs/evoral/src/ControlSet.cpp @@ -16,6 +16,7 @@ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include <iostream> #include <limits> #include "evoral/ControlSet.hpp" #include "evoral/ControlList.hpp" @@ -43,6 +44,10 @@ ControlSet::add_control(boost::shared_ptr<Control> ac) _controls[ac->parameter()] = ac; ac->ListMarkedDirty.connect_same_thread (_control_connections, boost::bind (&ControlSet::control_list_marked_dirty, this)); + + ac->list()->InterpolationChanged.connect_same_thread ( + _list_connections, boost::bind (&ControlSet::control_list_interpolation_changed, this, ac->parameter(), _1) + ); } void @@ -111,10 +116,10 @@ ControlSet::clear_controls () Glib::Mutex::Lock lm (_control_lock); _control_connections.drop_connections (); + _list_connections.drop_connections (); for (Controls::iterator li = _controls.begin(); li != _controls.end(); ++li) li->second->list()->clear(); } - } // namespace Evoral diff --git a/libs/evoral/src/Sequence.cpp b/libs/evoral/src/Sequence.cpp index a67f32e993..a9d55056bd 100644 --- a/libs/evoral/src/Sequence.cpp +++ b/libs/evoral/src/Sequence.cpp @@ -52,14 +52,16 @@ Sequence<Time>::const_iterator::const_iterator() _event = boost::shared_ptr< Event<Time> >(new Event<Time>()); } +/** @param force_discrete true to force ControlLists to use discrete evaluation, otherwise false to get them to use their configured mode */ template<typename Time> -Sequence<Time>::const_iterator::const_iterator(const Sequence<Time>& seq, Time t, std::set<Evoral::Parameter> const & filtered) +Sequence<Time>::const_iterator::const_iterator(const Sequence<Time>& seq, Time t, bool force_discrete, std::set<Evoral::Parameter> const & filtered) : _seq(&seq) , _type(NIL) , _is_end((t == DBL_MAX) || seq.empty()) , _note_iter(seq.notes().end()) , _sysex_iter(seq.sysexes().end()) , _control_iter(_control_iters.end()) + , _force_discrete (force_discrete) { DEBUG_TRACE (DEBUG::Sequence, string_compose ("Created Iterator @ %1 (is end: %2)\n)", t, _is_end)); @@ -98,7 +100,12 @@ Sequence<Time>::const_iterator::const_iterator(const Sequence<Time>& seq, Time t DEBUG_TRACE (DEBUG::Sequence, string_compose ("Iterator: control: %1\n", seq._type_map.to_symbol(i->first))); double x, y; - bool ret = i->second->list()->rt_safe_earliest_event_unlocked(t, DBL_MAX, x, y, true); + bool ret; + if (_force_discrete) { + ret = i->second->list()->rt_safe_earliest_event_discrete_unlocked (t, DBL_MAX, x, y, true); + } else { + ret = i->second->list()->rt_safe_earliest_event_unlocked(t, DBL_MAX, x, y, true); + } if (!ret) { DEBUG_TRACE (DEBUG::Sequence, string_compose ("Iterator: CC %1 (size %2) has no events past %3\n", i->first.id(), i->second->list()->size(), t)); @@ -246,8 +253,11 @@ Sequence<Time>::const_iterator::operator++() break; case CONTROL: // Increment current controller iterator - ret = _control_iter->list->rt_safe_earliest_event_unlocked( - _control_iter->x, DBL_MAX, x, y, false); + if (_force_discrete) { + ret = _control_iter->list->rt_safe_earliest_event_discrete_unlocked (_control_iter->x, DBL_MAX, x, y, false); + } else { + ret = _control_iter->list->rt_safe_earliest_event_unlocked (_control_iter->x, DBL_MAX, x, y, false); + } assert(!ret || x > _control_iter->x); if (ret) { _control_iter->x = x; @@ -366,6 +376,7 @@ Sequence<Time>::const_iterator::operator=(const const_iterator& other) _note_iter = other._note_iter; _sysex_iter = other._sysex_iter; _control_iters = other._control_iters; + _force_discrete = other._force_discrete; if (other._lock) _lock = _seq->read_lock(); @@ -391,7 +402,7 @@ Sequence<Time>::Sequence(const TypeMap& type_map) , _overlap_pitch_resolution (FirstOnFirstOff) , _writing(false) , _type_map(type_map) - , _end_iter(*this, DBL_MAX, std::set<Evoral::Parameter> ()) + , _end_iter(*this, DBL_MAX, false, std::set<Evoral::Parameter> ()) , _percussive(false) , _lowest_note(127) , _highest_note(0) @@ -409,7 +420,7 @@ Sequence<Time>::Sequence(const Sequence<Time>& other) , _overlap_pitch_resolution (other._overlap_pitch_resolution) , _writing(false) , _type_map(other._type_map) - , _end_iter(*this, DBL_MAX, std::set<Evoral::Parameter> ()) + , _end_iter(*this, DBL_MAX, false, std::set<Evoral::Parameter> ()) , _percussive(other._percussive) , _lowest_note(other._lowest_note) , _highest_note(other._highest_note) |