From eb482d3a36d7e2da87bf1584e6ed03c0e04eae77 Mon Sep 17 00:00:00 2001 From: Jonathan Moore Liles Date: Mon, 9 Sep 2013 18:46:28 -0700 Subject: [PATCH] Timeline: Add option for per-track delay-free playback latency compensation. Disabled by default. --- timeline/src/Engine/Playback_DS.C | 13 ++++--------- timeline/src/Engine/Playback_DS.H | 7 ++++--- timeline/src/Engine/Track.C | 24 ++++++++++++++++++++++-- timeline/src/TLE.fl | 11 +++++++---- timeline/src/Timeline.C | 1 + timeline/src/Timeline.H | 1 + timeline/src/Track.H | 4 ++-- 7 files changed, 41 insertions(+), 20 deletions(-) diff --git a/timeline/src/Engine/Playback_DS.C b/timeline/src/Engine/Playback_DS.C index 5c59c8b..ce05c52 100644 --- a/timeline/src/Engine/Playback_DS.C +++ b/timeline/src/Engine/Playback_DS.C @@ -66,9 +66,9 @@ Playback_DS::seek ( nframes_t frame ) /** set the playback delay to /frames/ frames. This be called prior to a seek. */ void -Playback_DS::delay ( nframes_t frames ) +Playback_DS::undelay ( nframes_t delay ) { - _delay = frames; + _undelay = delay; } /** read /nframes/ from the attached track into /buf/ */ @@ -94,13 +94,8 @@ Playback_DS::read_block ( sample_t *buf, nframes_t nframes ) if ( sequence() ) { - /* FIXME: how does this work if _delay is not a multiple of bufsize? */ - - if ( _frame >= _delay ) - { - if ( ! sequence()->play( buf, _frame - _delay, nframes, channels() ) ) - WARNING( "Programming error?" ); - } + if ( ! sequence()->play( buf, _frame + _undelay, nframes, channels() ) ) + WARNING( "Programming error?" ); _frame += nframes; } diff --git a/timeline/src/Engine/Playback_DS.H b/timeline/src/Engine/Playback_DS.H index 408b9c9..128a745 100644 --- a/timeline/src/Engine/Playback_DS.H +++ b/timeline/src/Engine/Playback_DS.H @@ -27,14 +27,15 @@ class Playback_DS : public Disk_Stream void flush ( void ) { base_flush( true ); } - volatile nframes_t _delay; /* number of frames this diskstream should be delayed by */ + volatile nframes_t _undelay; /* number of frames this diskstream + * should be undelayed by */ public: Playback_DS ( Track *th, float frame_rate, nframes_t nframes, int channels ) : Disk_Stream( th, frame_rate, nframes, channels ) { - _delay = 0; + _undelay = 0; run(); } @@ -45,6 +46,6 @@ public: void seek ( nframes_t frame ); nframes_t process ( nframes_t nframes ); - void delay ( nframes_t v ); + void undelay ( nframes_t v ); }; diff --git a/timeline/src/Engine/Track.C b/timeline/src/Engine/Track.C index 5fa84e6..0273ad5 100644 --- a/timeline/src/Engine/Track.C +++ b/timeline/src/Engine/Track.C @@ -234,17 +234,19 @@ Track::seek ( nframes_t frame ) { THREAD_ASSERT( RT ); + compute_latency_compensation(); + if ( playback_ds ) return playback_ds->seek( frame ); } void -Track::delay ( nframes_t frames ) +Track::undelay ( nframes_t nframes ) { // THREAD_ASSERT( RT ); if ( playback_ds ) - playback_ds->delay( frames ); + playback_ds->undelay( nframes ); } /* THREAD: RT (non-RT) */ @@ -360,3 +362,21 @@ Track::finalize ( Capture *c, nframes_t frame ) timeline->unlock(); } + +void +Track::compute_latency_compensation ( void ) +{ + if ( Timeline::playback_latency_compensation && output.size() ) + { + nframes_t min,max; + output[0].get_latency( JACK::Port::Output, &min, &max ); + + DMESSAGE( "Track %s, setting undelay to %lu", name(), (unsigned long)min); + + undelay( min ); + } + else + { + undelay( 0 ); + } +} diff --git a/timeline/src/TLE.fl b/timeline/src/TLE.fl index 73cf67c..e54de7f 100644 --- a/timeline/src/TLE.fl +++ b/timeline/src/TLE.fl @@ -325,6 +325,11 @@ pi.run();} label {Capture Format} open xywh {25 25 74 25} } {} + MenuItem {} { + label {Playback Latency Compensation} + callback {Timeline::playback_latency_compensation = menu_picked_value( o );} selected + xywh {55 55 40 25} type Toggle + } } MenuItem {} { label {&New} @@ -364,9 +369,7 @@ main_window->redraw();} } MenuItem {} { label {&Open} - callback { - -char *path = read_line( user_config_dir, "default_path" ); + callback {char *path = read_line( user_config_dir, "default_path" ); const char *name = fl_dir_chooser( "Open Project", path ); @@ -1107,7 +1110,7 @@ if ( logo_box->image() ) code1 {o->label( NULL );} } Fl_Text_Editor notes_field { - label {Notes:} selected + label {Notes:} private xywh {20 420 480 245} color 47 selection_color 31 textsize 18 textcolor 92 code0 {o->buffer( new Fl_Text_Buffer() );} code1 {o->buffer()->loadfile( "notes" );} diff --git a/timeline/src/Timeline.C b/timeline/src/Timeline.C index 51ee4d4..c280ecd 100644 --- a/timeline/src/Timeline.C +++ b/timeline/src/Timeline.C @@ -73,6 +73,7 @@ bool Timeline::snapping_on_hold = false; bool Timeline::snap_magnetic = true; bool Timeline::follow_playhead = true; bool Timeline::center_playhead = true; +bool Timeline::playback_latency_compensation = false; const float UPDATE_FREQ = 1.0f / 18.0f; diff --git a/timeline/src/Timeline.H b/timeline/src/Timeline.H index e21fde7..943dbfb 100644 --- a/timeline/src/Timeline.H +++ b/timeline/src/Timeline.H @@ -155,6 +155,7 @@ public: static bool snap_magnetic; static bool follow_playhead; static bool center_playhead; + static bool playback_latency_compensation; Tempo_Sequence *tempo_track; Time_Sequence *time_track; diff --git a/timeline/src/Track.H b/timeline/src/Track.H index 8e7df31..b2e0134 100644 --- a/timeline/src/Track.H +++ b/timeline/src/Track.H @@ -253,8 +253,8 @@ public: nframes_t process_input ( nframes_t nframes ); nframes_t process_output ( nframes_t nframes ); void seek ( nframes_t frame ); - void delay ( nframes_t frames ); - + void undelay ( nframes_t frames ); + void compute_latency_compensation ( void ); void record ( Capture *c, nframes_t frame ); void write ( Capture *c, sample_t *buf, nframes_t nframes ); void finalize ( Capture *c, nframes_t frame );