/*
- Copyright (C) 2001-2003 Paul Davis
+ Copyright (C) 2001-2007 Paul Davis
Contains ideas derived from "Constrained Cubic Spline Interpolation"
by CJC Kruger (www.korf.co.uk/spline.pdf).
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <iostream>
#include <sigc++/bind.h>
#include "ardour/curve.h"
+#include "ardour/automation_event.h"
#include "i18n.h"
using namespace sigc;
using namespace PBD;
-Curve::Curve (double minv, double maxv, double canv, bool nostate)
- : AutomationList (canv, nostate)
-{
- min_yval = minv;
- max_yval = maxv;
- CurveCreated(this);
-}
-
-Curve::Curve (const Curve& other)
- : AutomationList (other)
-{
- min_yval = other.min_yval;
- max_yval = other.max_yval;
- CurveCreated(this);
-}
-
-Curve::Curve (const Curve& other, double start, double end)
- : AutomationList (other, start, end)
-{
- min_yval = other.min_yval;
- max_yval = other.max_yval;
- CurveCreated(this);
-}
-
-Curve::~Curve ()
+Curve::Curve (const AutomationList& al)
+ : _dirty (true)
+ , _list (al)
{
+ _list.Dirty.connect(mem_fun(*this, &Curve::on_list_dirty));
}
void
return;
}
- if ((npoints = events.size()) > 2) {
+ if ((npoints = _list.events().size()) > 2) {
/* Compute coefficients needed to efficiently compute a constrained spline
curve. See "Constrained Cubic Spline Interpolation" by CJC Kruger
double x[npoints];
double y[npoints];
uint32_t i;
- AutomationEventList::iterator xx;
+ AutomationList::EventList::const_iterator xx;
- for (i = 0, xx = events.begin(); xx != events.end(); ++xx, ++i) {
+ for (i = 0, xx = _list.events().begin(); xx != _list.events().end(); ++xx, ++i) {
x[i] = (double) (*xx)->when;
y[i] = (double) (*xx)->value;
}
double lp0, lp1, fpone;
- lp0 =(x[1] - x[0])/(y[1] - y[0]);
+ lp0 = (x[1] - x[0])/(y[1] - y[0]);
lp1 = (x[2] - x[1])/(y[2] - y[1]);
if (lp0*lp1 < 0) {
double fplast = 0;
- for (i = 0, xx = events.begin(); xx != events.end(); ++xx, ++i) {
-
- CurvePoint* cp = dynamic_cast<CurvePoint*>(*xx);
-
- if (cp == 0) {
- fatal << _("programming error: ")
- << X_("non-CurvePoint event found in event list for a Curve")
- << endmsg;
- /*NOTREACHED*/
- }
+ for (i = 0, xx = _list.events().begin(); xx != _list.events().end(); ++xx, ++i) {
double xdelta; /* gcc is wrong about possible uninitialized use */
double xdelta2; /* ditto */
/* store */
- cp->coeff[0] = y[i-1] - (b * x[i-1]) - (c * xim12) - (d * xim13);
- cp->coeff[1] = b;
- cp->coeff[2] = c;
- cp->coeff[3] = d;
+ (*xx)->create_coeffs();
+ (*xx)->coeff[0] = y[i-1] - (b * x[i-1]) - (c * xim12) - (d * xim13);
+ (*xx)->coeff[1] = b;
+ (*xx)->coeff[2] = c;
+ (*xx)->coeff[3] = d;
fplast = fpi;
}
bool
Curve::rt_safe_get_vector (double x0, double x1, float *vec, int32_t veclen)
{
- Glib::Mutex::Lock lm (lock, Glib::TRY_LOCK);
+ Glib::Mutex::Lock lm(_list.lock(), Glib::TRY_LOCK);
if (!lm.locked()) {
return false;
void
Curve::get_vector (double x0, double x1, float *vec, int32_t veclen)
{
- Glib::Mutex::Lock lm (lock);
+ Glib::Mutex::Lock lm(_list.lock());
_get_vector (x0, x1, vec, veclen);
}
int32_t original_veclen;
int32_t npoints;
- if ((npoints = events.size()) == 0) {
- for (i = 0; i < veclen; ++i) {
- vec[i] = default_value;
- }
- return;
+ if ((npoints = _list.events().size()) == 0) {
+ for (i = 0; i < veclen; ++i) {
+ vec[i] = _list.default_value();
+ }
+ return;
}
/* events is now known not to be empty */
- max_x = events.back()->when;
- min_x = events.front()->when;
+ max_x = _list.events().back()->when;
+ min_x = _list.events().front()->when;
lx = max (min_x, x0);
if (x1 < 0) {
- x1 = events.back()->when;
+ x1 = _list.events().back()->when;
}
hx = min (max_x, x1);
subveclen = min (subveclen, veclen);
for (i = 0; i < subveclen; ++i) {
- vec[i] = events.front()->value;
+ vec[i] = _list.events().front()->value;
}
veclen -= subveclen;
subveclen = min (subveclen, veclen);
- val = events.back()->value;
+ val = _list.events().back()->value;
i = veclen - subveclen;
if (npoints == 1 ) {
for (i = 0; i < veclen; ++i) {
- vec[i] = events.front()->value;
+ vec[i] = _list.events().front()->value;
}
return;
}
dx = 0; // not used
}
- double slope = (events.back()->value - events.front()->value)/
- (events.back()->when - events.front()->when);
+ double slope = (_list.events().back()->value - _list.events().front()->value)/
+ (_list.events().back()->when - _list.events().front()->when);
double yfrac = dx*slope;
- vec[0] = events.front()->value + slope * (lx - events.front()->when);
+ vec[0] = _list.events().front()->value + slope * (lx - _list.events().front()->when);
for (i = 1; i < veclen; ++i) {
vec[i] = vec[i-1] + yfrac;
double
Curve::unlocked_eval (double x)
{
+ // I don't see the point of this...
+
if (_dirty) {
solve ();
}
- return shared_eval (x);
+ return _list.unlocked_eval (x);
}
double
Curve::multipoint_eval (double x)
{
- pair<AutomationEventList::iterator,AutomationEventList::iterator> range;
+ pair<AutomationList::EventList::const_iterator,AutomationList::EventList::const_iterator> range;
+
+ AutomationList::LookupCache& lookup_cache = _list.lookup_cache();
if ((lookup_cache.left < 0) ||
((lookup_cache.left > x) ||
- (lookup_cache.range.first == events.end()) ||
+ (lookup_cache.range.first == _list.events().end()) ||
((*lookup_cache.range.second)->when < x))) {
- TimeComparator cmp;
ControlEvent cp (x, 0.0);
- lookup_cache.range = equal_range (events.begin(), events.end(), &cp, cmp);
+ lookup_cache.range = equal_range (_list.events().begin(), _list.events().end(), &cp, AutomationList::time_comparator);
}
range = lookup_cache.range;
lookup_cache.left = x;
- if (range.first == events.begin()) {
+ if (range.first == _list.events().begin()) {
/* we're before the first point */
// return default_value;
- events.front()->value;
+ _list.events().front()->value;
}
- if (range.second == events.end()) {
+ if (range.second == _list.events().end()) {
/* we're after the last point */
- return events.back()->value;
+ return _list.events().back()->value;
}
double x2 = x * x;
- CurvePoint* cp = dynamic_cast<CurvePoint*> (*range.second);
+ ControlEvent* ev = *range.second;
- return cp->coeff[0] + (cp->coeff[1] * x) + (cp->coeff[2] * x2) + (cp->coeff[3] * x2 * x);
+ return ev->coeff[0] + (ev->coeff[1] * x) + (ev->coeff[2] * x2) + (ev->coeff[3] * x2 * x);
}
/* x is a control point in the data */
return (*range.first)->value;
}
-ControlEvent*
-Curve::point_factory (double when, double val) const
-{
- return new CurvePoint (when, val);
-}
-
-ControlEvent*
-Curve::point_factory (const ControlEvent& other) const
-{
- return new CurvePoint (other.when, other.value);
-}
-
-Change
-Curve::restore_state (StateManager::State& state)
-{
- mark_dirty ();
- return AutomationList::restore_state (state);
-}
-
-
extern "C" {
void