@@ -131,7 +131,7 @@ Audio_Sequence::play ( sample_t *buf, nframes_t frame, nframes_t nframes, int ch | |||||
/* quick and dirty--let the regions figure out coverage for themselves */ | /* quick and dirty--let the regions figure out coverage for themselves */ | ||||
for ( list <Sequence_Widget *>::const_iterator i = _widgets.begin(); | for ( list <Sequence_Widget *>::const_iterator i = _widgets.begin(); | ||||
i != _widgets.end(); i++ ) | |||||
i != _widgets.end(); ++i ) | |||||
{ | { | ||||
const Region *r = (Region*)(*i); | const Region *r = (Region*)(*i); | ||||
@@ -110,6 +110,9 @@ public: | |||||
float control ( void ) const { return _y; } | float control ( void ) const { return _y; } | ||||
void control ( float v ) { _y = v; } | void control ( float v ) { _y = v; } | ||||
/* only for playback thread */ | |||||
nframes_t when ( void ) const { return _range.offset; } | |||||
int | int | ||||
handle ( int m ) | handle ( int m ) | ||||
@@ -20,11 +20,14 @@ | |||||
#include "Control_Sequence.H" | #include "Control_Sequence.H" | ||||
#include "Track.H" | #include "Track.H" | ||||
#include "Transport.H" // for transport->frame | |||||
bool Control_Sequence::draw_with_gradient = true; | bool Control_Sequence::draw_with_gradient = true; | ||||
bool Control_Sequence::draw_with_polygon = true; | bool Control_Sequence::draw_with_polygon = true; | ||||
bool Control_Sequence::draw_with_grid = true; | bool Control_Sequence::draw_with_grid = true; | ||||
Control_Sequence::Control_Sequence ( Track *track ) : Sequence( 0, 0, 0, 0 ) | |||||
Control_Sequence::Control_Sequence ( Track *track ) : Sequence( 0, 0, 0, 0 ), output( "foo", Port::Output ) | |||||
{ | { | ||||
init(); | init(); | ||||
@@ -267,3 +270,72 @@ Control_Sequence::handle ( int m ) | |||||
return 0; | return 0; | ||||
} | } | ||||
} | } | ||||
/**********/ | |||||
/* Engine */ | |||||
/**********/ | |||||
static inline float | |||||
linear_interpolate ( float y1, float y2, float mu ) | |||||
{ | |||||
return y1 * (1 - mu) + y2 * mu; | |||||
} | |||||
static inline float | |||||
sigmoid_interpolate ( float y1, float y2, float mu ) | |||||
{ | |||||
return linear_interpolate( y1, y2, ( 1 - cos( mu * M_PI ) ) / 2 ); | |||||
} | |||||
/* static inline float */ | |||||
/* exponential_interpolate ( float y1, float y2, float mu ) */ | |||||
/* { */ | |||||
/* } */ | |||||
/* THREAD: ?? */ | |||||
/** fill buf with /nframes/ of interpolated control curve values | |||||
* starting at /frame/ */ | |||||
nframes_t | |||||
Control_Sequence::play ( sample_t *buf, nframes_t frame, nframes_t nframes ) | |||||
{ | |||||
Control_Point *p2, *p1 = (Control_Point*)&_widgets.front(); | |||||
nframes_t n = nframes; | |||||
for ( list <Sequence_Widget *>::const_iterator i = _widgets.begin(); | |||||
i != _widgets.end(); ++i, p1 = p2 ) | |||||
{ | |||||
p2 = (Control_Point*)(*i); | |||||
if ( p2->when() < frame ) | |||||
continue; | |||||
nframes_t d = p2->when() - p1->when(); | |||||
for ( nframes_t i = frame - p1->when(); i < d; ++i ) | |||||
{ | |||||
*(buf++) = 1.0f - ( 2 * sigmoid_interpolate( p1->control(), p2->control(), i / (float)d ) ); | |||||
if ( ! n-- ) | |||||
return nframes; | |||||
frame++; | |||||
} | |||||
} | |||||
return frame; | |||||
} | |||||
/* THREAD: RT */ | |||||
nframes_t | |||||
Control_Sequence::process ( nframes_t nframes ) | |||||
{ | |||||
void *buf = output.buffer( nframes ); | |||||
return play( (sample_t*)buf, transport->frame, nframes ); | |||||
} |
@@ -21,6 +21,7 @@ | |||||
#include "Sequence.H" | #include "Sequence.H" | ||||
#include "Control_Point.H" | #include "Control_Point.H" | ||||
#include "Port.H" | |||||
class Control_Sequence : public Sequence | class Control_Sequence : public Sequence | ||||
{ | { | ||||
@@ -29,13 +30,15 @@ class Control_Sequence : public Sequence | |||||
void init ( void ); | void init ( void ); | ||||
Port output; | |||||
protected: | protected: | ||||
virtual void get ( Log_Entry &e ) const; | virtual void get ( Log_Entry &e ) const; | ||||
void set ( Log_Entry &e ); | void set ( Log_Entry &e ); | ||||
Control_Sequence ( ) : Sequence( 0, 0, 0, 1 ) | |||||
Control_Sequence ( ) : Sequence( 0, 0, 0, 1 ), output( "foo", Port::Output ) | |||||
{ | { | ||||
init(); | init(); | ||||
} | } | ||||
@@ -60,4 +63,9 @@ public: | |||||
void draw ( void ); | void draw ( void ); | ||||
int handle ( int m ); | int handle ( int m ); | ||||
/* Engine */ | |||||
nframes_t play ( sample_t *buf, nframes_t frame, nframes_t nframes ); | |||||
nframes_t process ( nframes_t nframes ); | |||||
}; | }; |
@@ -615,6 +615,9 @@ Track::configure_inputs ( int n ) | |||||
nframes_t | nframes_t | ||||
Track::process ( nframes_t nframes ) | Track::process ( nframes_t nframes ) | ||||
{ | { | ||||
for ( int i = control->children(); i--; ) | |||||
((Control_Sequence*)control->child( i ))->process( nframes ); | |||||
if ( playback_ds ) | if ( playback_ds ) | ||||
{ | { | ||||
record_ds->process( nframes ); | record_ds->process( nframes ); | ||||