summaryrefslogtreecommitdiff
path: root/libs/evoral
diff options
context:
space:
mode:
authorCarl Hetherington <carl@carlh.net>2010-07-14 00:58:15 +0000
committerCarl Hetherington <carl@carlh.net>2010-07-14 00:58:15 +0000
commit593b421180290f46f39efcb21ed8192b624bbc73 (patch)
treef8a81aad5fae8683818103b192d3c53a26110728 /libs/evoral
parentb75977920e7cb02ae31bca0379dd3aa4d82f9cbc (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.hpp6
-rw-r--r--libs/evoral/evoral/ControlSet.hpp5
-rw-r--r--libs/evoral/evoral/Sequence.hpp7
-rw-r--r--libs/evoral/src/ControlList.cpp16
-rw-r--r--libs/evoral/src/ControlSet.cpp7
-rw-r--r--libs/evoral/src/Sequence.cpp23
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)