| @@ -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 ); | ||||