Respond appropriately to changes in JACK buffer size.
This commit is contained in:
parent
97f0283780
commit
48d7f61f8a
|
@ -52,7 +52,6 @@ size_t Disk_Stream::disk_io_kbytes = 256;
|
||||||
|
|
||||||
Disk_Stream::Disk_Stream ( Track *track, float frame_rate, nframes_t nframes, int channels ) : _track( track )
|
Disk_Stream::Disk_Stream ( Track *track, float frame_rate, nframes_t nframes, int channels ) : _track( track )
|
||||||
{
|
{
|
||||||
|
|
||||||
assert( channels );
|
assert( channels );
|
||||||
|
|
||||||
_frame = 0;
|
_frame = 0;
|
||||||
|
@ -60,20 +59,9 @@ Disk_Stream::Disk_Stream ( Track *track, float frame_rate, nframes_t nframes, in
|
||||||
_terminate = false;
|
_terminate = false;
|
||||||
_pending_seek = -1;
|
_pending_seek = -1;
|
||||||
_xruns = 0;
|
_xruns = 0;
|
||||||
|
_frame_rate = frame_rate;
|
||||||
|
|
||||||
_total_blocks = frame_rate * seconds_to_buffer / nframes;
|
_resize_buffers( nframes, channels );
|
||||||
|
|
||||||
_nframes = nframes;
|
|
||||||
|
|
||||||
size_t bufsize = _total_blocks * nframes * sizeof( sample_t );
|
|
||||||
|
|
||||||
if ( disk_io_kbytes )
|
|
||||||
_disk_io_blocks = ( bufsize * channels ) / ( disk_io_kbytes * 1024 );
|
|
||||||
else
|
|
||||||
_disk_io_blocks = 1;
|
|
||||||
|
|
||||||
for ( int i = channels; i--; )
|
|
||||||
_rb.push_back( jack_ringbuffer_create( bufsize ) );
|
|
||||||
|
|
||||||
sem_init( &_blocks, 0, _total_blocks );
|
sem_init( &_blocks, 0, _total_blocks );
|
||||||
}
|
}
|
||||||
|
@ -97,14 +85,13 @@ Disk_Stream::~Disk_Stream ( )
|
||||||
/* THREAD: RT */
|
/* THREAD: RT */
|
||||||
/** flush buffers and reset. Must only be called from the RT thread. */
|
/** flush buffers and reset. Must only be called from the RT thread. */
|
||||||
void
|
void
|
||||||
Disk_Stream::flush ( bool is_output )
|
Disk_Stream::base_flush ( bool is_output )
|
||||||
{
|
{
|
||||||
|
|
||||||
/* flush buffers */
|
/* flush buffers */
|
||||||
for ( int i = channels(); i--; )
|
for ( int i = _rb.size(); i--; )
|
||||||
jack_ringbuffer_read_advance( _rb[ i ], jack_ringbuffer_read_space( _rb[ i ] ) );
|
jack_ringbuffer_read_advance( _rb[ i ], jack_ringbuffer_read_space( _rb[ i ] ) );
|
||||||
|
|
||||||
|
|
||||||
/* sem_destroy( &_blocks ); */
|
/* sem_destroy( &_blocks ); */
|
||||||
|
|
||||||
/* if ( is_output ) */
|
/* if ( is_output ) */
|
||||||
|
@ -114,7 +101,6 @@ Disk_Stream::flush ( bool is_output )
|
||||||
|
|
||||||
if ( is_output )
|
if ( is_output )
|
||||||
{
|
{
|
||||||
|
|
||||||
int n;
|
int n;
|
||||||
sem_getvalue( &_blocks, &n );
|
sem_getvalue( &_blocks, &n );
|
||||||
|
|
||||||
|
@ -145,6 +131,7 @@ Disk_Stream::shutdown ( void )
|
||||||
if ( _thread )
|
if ( _thread )
|
||||||
pthread_join( _thread, NULL );
|
pthread_join( _thread, NULL );
|
||||||
|
|
||||||
|
_thread = 0;
|
||||||
_terminate = false;
|
_terminate = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,12 +155,50 @@ Disk_Stream::run ( void )
|
||||||
FATAL( "Could not create IO thread!" );
|
FATAL( "Could not create IO thread!" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Disk_Stream::_resize_buffers ( nframes_t nframes, int channels )
|
||||||
|
{
|
||||||
|
for ( int i = _rb.size(); i--; )
|
||||||
|
jack_ringbuffer_free( _rb[ i ] );
|
||||||
|
|
||||||
|
_rb.clear();
|
||||||
|
|
||||||
|
_nframes = nframes;
|
||||||
|
|
||||||
|
_total_blocks = _frame_rate * seconds_to_buffer / nframes;
|
||||||
|
|
||||||
|
size_t bufsize = _total_blocks * nframes * sizeof( sample_t );
|
||||||
|
|
||||||
|
if ( disk_io_kbytes )
|
||||||
|
_disk_io_blocks = ( bufsize * channels ) / ( disk_io_kbytes * 1024 );
|
||||||
|
else
|
||||||
|
_disk_io_blocks = 1;
|
||||||
|
|
||||||
|
for ( int i = channels; i--; )
|
||||||
|
_rb.push_back( jack_ringbuffer_create( bufsize ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* THREAD: RT (non-RT) */
|
||||||
/* to be called when the JACK buffer size changes. */
|
/* to be called when the JACK buffer size changes. */
|
||||||
void
|
void
|
||||||
Disk_Stream::resize ( nframes_t nframes )
|
Disk_Stream::resize_buffers ( nframes_t nframes )
|
||||||
{
|
{
|
||||||
if ( nframes != _nframes )
|
if ( nframes != _nframes )
|
||||||
/* FIXME: to something here! */;
|
{
|
||||||
|
DMESSAGE( "resizing buffers" );
|
||||||
|
|
||||||
|
const bool was_running = _thread;
|
||||||
|
|
||||||
|
if ( was_running )
|
||||||
|
shutdown();
|
||||||
|
|
||||||
|
flush();
|
||||||
|
|
||||||
|
_resize_buffers( nframes, channels() );
|
||||||
|
|
||||||
|
if ( was_running )
|
||||||
|
run();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -59,6 +59,9 @@ protected:
|
||||||
int _total_blocks; /* total number of blocks that we can buffer */
|
int _total_blocks; /* total number of blocks that we can buffer */
|
||||||
int _disk_io_blocks; /* the number of blocks to read/write to/from disk at once */
|
int _disk_io_blocks; /* the number of blocks to read/write to/from disk at once */
|
||||||
|
|
||||||
|
|
||||||
|
nframes_t _frame_rate; /* used for buffer size calculations */
|
||||||
|
|
||||||
volatile nframes_t _pending_seek; /* absolute transport position to seek to */
|
volatile nframes_t _pending_seek; /* absolute transport position to seek to */
|
||||||
volatile int _terminate;
|
volatile int _terminate;
|
||||||
|
|
||||||
|
@ -71,6 +74,8 @@ protected:
|
||||||
|
|
||||||
static void *disk_thread ( void *arg );
|
static void *disk_thread ( void *arg );
|
||||||
|
|
||||||
|
void _resize_buffers ( nframes_t nframes, int channels );
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
void block_processed ( void ) { sem_post( &_blocks ); }
|
void block_processed ( void ) { sem_post( &_blocks ); }
|
||||||
|
@ -86,7 +91,8 @@ protected:
|
||||||
|
|
||||||
virtual void disk_thread ( void ) = 0;
|
virtual void disk_thread ( void ) = 0;
|
||||||
|
|
||||||
void flush ( bool is_output );
|
void base_flush ( bool is_output );
|
||||||
|
virtual void flush ( void ) = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -100,7 +106,7 @@ public:
|
||||||
|
|
||||||
virtual ~Disk_Stream ( );
|
virtual ~Disk_Stream ( );
|
||||||
|
|
||||||
void resize ( nframes_t nframes );
|
void resize_buffers ( nframes_t nframes );
|
||||||
|
|
||||||
/* void seek ( nframes_t frame ); */
|
/* void seek ( nframes_t frame ); */
|
||||||
/* bool seek_pending ( void ); */
|
/* bool seek_pending ( void ); */
|
||||||
|
|
|
@ -70,6 +70,12 @@ Engine::freewheel ( int starting, void *arg )
|
||||||
((Engine*)arg)->freewheel( starting );
|
((Engine*)arg)->freewheel( starting );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
Engine::buffer_size ( nframes_t nframes, void *arg )
|
||||||
|
{
|
||||||
|
return ((Engine*)arg)->buffer_size( nframes );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -101,6 +107,16 @@ Engine::freewheel ( bool starting )
|
||||||
DMESSAGE( "leaving freewheeling mode" );
|
DMESSAGE( "leaving freewheeling mode" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* THREAD: RT (non-RT) */
|
||||||
|
int
|
||||||
|
Engine::buffer_size ( nframes_t nframes )
|
||||||
|
{
|
||||||
|
/* TODO: inform all disktreams the the buffer size has changed */
|
||||||
|
timeline->resize_buffers( nframes );
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* THREAD: RT */
|
/* THREAD: RT */
|
||||||
/** This is the jack slow-sync callback. */
|
/** This is the jack slow-sync callback. */
|
||||||
int
|
int
|
||||||
|
@ -232,6 +248,7 @@ Engine::init ( void )
|
||||||
set_callback( process );
|
set_callback( process );
|
||||||
set_callback( xrun );
|
set_callback( xrun );
|
||||||
set_callback( freewheel );
|
set_callback( freewheel );
|
||||||
|
set_callback( buffer_size );
|
||||||
|
|
||||||
/* FIXME: should we wait to register this until after the project
|
/* FIXME: should we wait to register this until after the project
|
||||||
has been loaded (and we have disk threads running)? */
|
has been loaded (and we have disk threads running)? */
|
||||||
|
|
|
@ -55,6 +55,8 @@ class Engine : public Mutex
|
||||||
void timebase ( jack_transport_state_t state, jack_nframes_t nframes, jack_position_t *pos, int new_pos );
|
void timebase ( jack_transport_state_t state, jack_nframes_t nframes, jack_position_t *pos, int new_pos );
|
||||||
static void freewheel ( int yes, void *arg );
|
static void freewheel ( int yes, void *arg );
|
||||||
void freewheel ( bool yes );
|
void freewheel ( bool yes );
|
||||||
|
static int buffer_size ( nframes_t nframes, void *arg );
|
||||||
|
int buffer_size ( nframes_t nframes );
|
||||||
|
|
||||||
Engine ( const Engine &rhs );
|
Engine ( const Engine &rhs );
|
||||||
Engine & operator = ( const Engine &rhs );
|
Engine & operator = ( const Engine &rhs );
|
||||||
|
|
|
@ -54,7 +54,7 @@ Playback_DS::seek ( nframes_t frame )
|
||||||
|
|
||||||
_pending_seek = frame;
|
_pending_seek = frame;
|
||||||
|
|
||||||
flush( true );
|
flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* THREAD: IO */
|
/* THREAD: IO */
|
||||||
|
@ -93,7 +93,6 @@ Playback_DS::read_block ( sample_t *buf, nframes_t nframes )
|
||||||
void
|
void
|
||||||
Playback_DS::disk_thread ( void )
|
Playback_DS::disk_thread ( void )
|
||||||
{
|
{
|
||||||
|
|
||||||
DMESSAGE( "playback thread running" );
|
DMESSAGE( "playback thread running" );
|
||||||
|
|
||||||
/* buffer to hold the interleaved data returned by the track reader */
|
/* buffer to hold the interleaved data returned by the track reader */
|
||||||
|
|
|
@ -25,6 +25,8 @@ class Playback_DS : public Disk_Stream
|
||||||
void read_block ( sample_t *buf, nframes_t nframes );
|
void read_block ( sample_t *buf, nframes_t nframes );
|
||||||
void disk_thread ( void );
|
void disk_thread ( void );
|
||||||
|
|
||||||
|
void flush ( void ) { base_flush( true ); }
|
||||||
|
|
||||||
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 ) :
|
||||||
|
|
|
@ -199,7 +199,7 @@ Record_DS::start ( nframes_t frame )
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: safe to do this here? */
|
/* FIXME: safe to do this here? */
|
||||||
flush( false );
|
flush();
|
||||||
|
|
||||||
_frame = frame;
|
_frame = frame;
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,8 @@ class Record_DS : public Disk_Stream
|
||||||
void write_block ( sample_t *buf, nframes_t nframes );
|
void write_block ( sample_t *buf, nframes_t nframes );
|
||||||
void disk_thread ( void );
|
void disk_thread ( void );
|
||||||
|
|
||||||
|
void flush ( void ) { base_flush( false ); }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Record_DS ( Track *th, float frame_rate, nframes_t nframes, int channels ) :
|
Record_DS ( Track *th, float frame_rate, nframes_t nframes, int channels ) :
|
||||||
|
|
|
@ -1233,6 +1233,18 @@ Timeline::seek ( nframes_t frame )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* THREAD: RT (non-RT) */
|
||||||
|
void
|
||||||
|
Timeline::resize_buffers ( nframes_t nframes )
|
||||||
|
{
|
||||||
|
for ( int i = tracks->children(); i-- ; )
|
||||||
|
{
|
||||||
|
Track *t = (Track*)tracks->child( i );
|
||||||
|
|
||||||
|
t->resize_buffers( nframes );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* THREAD: RT */
|
/* THREAD: RT */
|
||||||
int
|
int
|
||||||
Timeline::seek_pending ( void )
|
Timeline::seek_pending ( void )
|
||||||
|
|
|
@ -210,6 +210,7 @@ private:
|
||||||
char * get_unique_track_name ( const char *name );
|
char * get_unique_track_name ( const char *name );
|
||||||
|
|
||||||
/* Engine */
|
/* Engine */
|
||||||
|
void resize_buffers ( nframes_t nframes );
|
||||||
nframes_t process ( nframes_t nframes );
|
nframes_t process ( nframes_t nframes );
|
||||||
void seek ( nframes_t frame );
|
void seek ( nframes_t frame );
|
||||||
int seek_pending ( void );
|
int seek_pending ( void );
|
||||||
|
|
|
@ -745,7 +745,15 @@ Track::seek ( nframes_t frame )
|
||||||
return playback_ds->seek( frame );
|
return playback_ds->seek( frame );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* THREAD: RT (non-RT) */
|
||||||
|
void
|
||||||
|
Track::resize_buffers ( nframes_t nframes )
|
||||||
|
{
|
||||||
|
if ( record_ds )
|
||||||
|
record_ds->resize_buffers( nframes );
|
||||||
|
if ( playback_ds )
|
||||||
|
playback_ds->resize_buffers( nframes );
|
||||||
|
}
|
||||||
|
|
||||||
/* FIXME: what about theading issues with this region/audiofile being
|
/* FIXME: what about theading issues with this region/audiofile being
|
||||||
accessible from the UI thread? Need locking? */
|
accessible from the UI thread? Need locking? */
|
||||||
|
|
|
@ -265,6 +265,7 @@ public:
|
||||||
const Audio_Region *capture ( void ) const { return _capture; }
|
const Audio_Region *capture ( void ) const { return _capture; }
|
||||||
|
|
||||||
/* Engine */
|
/* Engine */
|
||||||
|
void resize_buffers ( nframes_t nframes );
|
||||||
nframes_t process ( nframes_t nframes );
|
nframes_t process ( nframes_t nframes );
|
||||||
void seek ( nframes_t frame );
|
void seek ( nframes_t frame );
|
||||||
void record ( nframes_t nframes );
|
void record ( nframes_t nframes );
|
||||||
|
|
Loading…
Reference in New Issue