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
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;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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