Timeline: Add option for per-track delay-free playback latency compensation. Disabled by default.

pull/116/head
Jonathan Moore Liles 2013-09-09 18:46:28 -07:00
parent 795249a612
commit eb482d3a36
7 changed files with 41 additions and 20 deletions

View File

@ -66,9 +66,9 @@ Playback_DS::seek ( nframes_t frame )
/** set the playback delay to /frames/ frames. This be called prior to /** set the playback delay to /frames/ frames. This be called prior to
a seek. */ a seek. */
void 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/ */ /** read /nframes/ from the attached track into /buf/ */
@ -94,13 +94,8 @@ Playback_DS::read_block ( sample_t *buf, nframes_t nframes )
if ( sequence() ) if ( sequence() )
{ {
/* FIXME: how does this work if _delay is not a multiple of bufsize? */ if ( ! sequence()->play( buf, _frame + _undelay, nframes, channels() ) )
WARNING( "Programming error?" );
if ( _frame >= _delay )
{
if ( ! sequence()->play( buf, _frame - _delay, nframes, channels() ) )
WARNING( "Programming error?" );
}
_frame += nframes; _frame += nframes;
} }

View File

@ -27,14 +27,15 @@ class Playback_DS : public Disk_Stream
void flush ( void ) { base_flush( true ); } 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: public:
Playback_DS ( Track *th, float frame_rate, nframes_t nframes, int channels ) : Playback_DS ( Track *th, float frame_rate, nframes_t nframes, int channels ) :
Disk_Stream( th, frame_rate, nframes, channels ) Disk_Stream( th, frame_rate, nframes, channels )
{ {
_delay = 0; _undelay = 0;
run(); run();
} }
@ -45,6 +46,6 @@ public:
void seek ( nframes_t frame ); void seek ( nframes_t frame );
nframes_t process ( nframes_t nframes ); nframes_t process ( nframes_t nframes );
void delay ( nframes_t v ); void undelay ( nframes_t v );
}; };

View File

@ -234,17 +234,19 @@ Track::seek ( nframes_t frame )
{ {
THREAD_ASSERT( RT ); THREAD_ASSERT( RT );
compute_latency_compensation();
if ( playback_ds ) if ( playback_ds )
return playback_ds->seek( frame ); return playback_ds->seek( frame );
} }
void void
Track::delay ( nframes_t frames ) Track::undelay ( nframes_t nframes )
{ {
// THREAD_ASSERT( RT ); // THREAD_ASSERT( RT );
if ( playback_ds ) if ( playback_ds )
playback_ds->delay( frames ); playback_ds->undelay( nframes );
} }
/* THREAD: RT (non-RT) */ /* THREAD: RT (non-RT) */
@ -360,3 +362,21 @@ Track::finalize ( Capture *c, nframes_t frame )
timeline->unlock(); 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 );
}
}

View File

@ -325,6 +325,11 @@ pi.run();}
label {Capture Format} open label {Capture Format} open
xywh {25 25 74 25} 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 {} { MenuItem {} {
label {&New} label {&New}
@ -364,9 +369,7 @@ main_window->redraw();}
} }
MenuItem {} { MenuItem {} {
label {&Open} label {&Open}
callback { callback {char *path = read_line( user_config_dir, "default_path" );
char *path = read_line( user_config_dir, "default_path" );
const char *name = fl_dir_chooser( "Open Project", path ); const char *name = fl_dir_chooser( "Open Project", path );
@ -1107,7 +1110,7 @@ if ( logo_box->image() )
code1 {o->label( NULL );} code1 {o->label( NULL );}
} }
Fl_Text_Editor notes_field { 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 private xywh {20 420 480 245} color 47 selection_color 31 textsize 18 textcolor 92
code0 {o->buffer( new Fl_Text_Buffer() );} code0 {o->buffer( new Fl_Text_Buffer() );}
code1 {o->buffer()->loadfile( "notes" );} code1 {o->buffer()->loadfile( "notes" );}

View File

@ -73,6 +73,7 @@ bool Timeline::snapping_on_hold = false;
bool Timeline::snap_magnetic = true; bool Timeline::snap_magnetic = true;
bool Timeline::follow_playhead = true; bool Timeline::follow_playhead = true;
bool Timeline::center_playhead = true; bool Timeline::center_playhead = true;
bool Timeline::playback_latency_compensation = false;
const float UPDATE_FREQ = 1.0f / 18.0f; const float UPDATE_FREQ = 1.0f / 18.0f;

View File

@ -155,6 +155,7 @@ public:
static bool snap_magnetic; static bool snap_magnetic;
static bool follow_playhead; static bool follow_playhead;
static bool center_playhead; static bool center_playhead;
static bool playback_latency_compensation;
Tempo_Sequence *tempo_track; Tempo_Sequence *tempo_track;
Time_Sequence *time_track; Time_Sequence *time_track;

View File

@ -253,8 +253,8 @@ public:
nframes_t process_input ( nframes_t nframes ); nframes_t process_input ( nframes_t nframes );
nframes_t process_output ( nframes_t nframes ); nframes_t process_output ( nframes_t nframes );
void seek ( nframes_t frame ); 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 record ( Capture *c, nframes_t frame );
void write ( Capture *c, sample_t *buf, nframes_t nframes ); void write ( Capture *c, sample_t *buf, nframes_t nframes );
void finalize ( Capture *c, nframes_t frame ); void finalize ( Capture *c, nframes_t frame );