Read from disk in larger chunks.
This commit is contained in:
parent
7793863d46
commit
f596d205db
|
@ -37,25 +37,24 @@
|
|||
that is, at startup time. The default is 5 seconds, which may or
|
||||
may not be excessive depending on various external factors. */
|
||||
|
||||
/* FIXME: handle termination of IO thread in destructor */
|
||||
/* FIXME: deal with (jack) buffer size changes */
|
||||
/* FIXME: needs error handling everywhere! */
|
||||
/* TODO: handle capture too. For this to work with some kind of
|
||||
* punch-in/out system, I believe we'll have to always keep at least
|
||||
* one buffer's worth of input. We would need this anyway in order to
|
||||
* pass input through to output (software monitoring). What about
|
||||
* looped recording? */
|
||||
/* TODO: latency compensation? Does this really apply to us? (we're
|
||||
* not hosting plugins here) */
|
||||
/* TODO: read/write data from/to disk in larger chunks to avoid
|
||||
* excessive seeking. 256k is supposedly the sweetspot. */
|
||||
|
||||
// float Disk_Stream::seconds_to_buffer = 5.0f;
|
||||
float Disk_Stream::seconds_to_buffer = 2.0f;
|
||||
// size_t Disk_Stream::disk_block_frames = 2048;
|
||||
float Disk_Stream::seconds_to_buffer = 5.0f;
|
||||
//float Disk_Stream::seconds_to_buffer = 2.0f;
|
||||
/* this is really only a rough estimate. The actual amount of data
|
||||
read depends on many factors. Overlapping regions, for example, will
|
||||
require more data to be read from disk, as will varying channel
|
||||
counts.*/
|
||||
size_t Disk_Stream::disk_io_kbytes = 256;
|
||||
|
||||
Disk_Stream::Disk_Stream ( Track *th, float frame_rate, nframes_t nframes, int channels ) : _th( th )
|
||||
{
|
||||
|
||||
assert( channels );
|
||||
|
||||
_frame = 0;
|
||||
_thread = 0;
|
||||
_terminate = false;
|
||||
|
@ -69,6 +68,10 @@ Disk_Stream::Disk_Stream ( Track *th, float frame_rate, nframes_t nframes, int c
|
|||
|
||||
size_t bufsize = _total_blocks * nframes * sizeof( sample_t );
|
||||
|
||||
_disk_io_blocks = ( bufsize * channels ) / ( disk_io_kbytes * 1024 );
|
||||
|
||||
assert( _disk_io_blocks );
|
||||
|
||||
for ( int i = channels; i--; )
|
||||
_rb.push_back( jack_ringbuffer_create( bufsize ) );
|
||||
|
||||
|
|
|
@ -53,6 +53,7 @@ protected:
|
|||
sem_t _blocks; /* semaphore to wake the IO thread with */
|
||||
|
||||
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 */
|
||||
|
||||
volatile nframes_t _pending_seek; /* absolute transport position to seek to */
|
||||
volatile int _terminate;
|
||||
|
@ -83,6 +84,7 @@ public:
|
|||
|
||||
/* must be set before any Disk_Streams are created */
|
||||
static float seconds_to_buffer;
|
||||
static size_t disk_io_kbytes;
|
||||
|
||||
Disk_Stream ( Track *th, float frame_rate, nframes_t nframes, int channels );
|
||||
|
||||
|
|
|
@ -109,9 +109,10 @@ Playback_DS::disk_thread ( void )
|
|||
printf( "IO thread running...\n" );
|
||||
|
||||
/* buffer to hold the interleaved data returned by the track reader */
|
||||
sample_t *buf = new sample_t[ _nframes * channels() ];
|
||||
sample_t *buf = new sample_t[ _nframes * channels() * _disk_io_blocks ];
|
||||
|
||||
const size_t block_size = _nframes * sizeof( sample_t );
|
||||
// const size_t block_size = _nframes * sizeof( sample_t );
|
||||
int blocks_ready = 1;
|
||||
|
||||
while ( wait_for_block() )
|
||||
{
|
||||
|
@ -126,6 +127,7 @@ Playback_DS::disk_thread ( void )
|
|||
printf( "performing seek\n" );
|
||||
_frame = _pending_seek;
|
||||
_pending_seek = -1;
|
||||
blocks_ready = 1;
|
||||
/* finish flushing the buffer */
|
||||
|
||||
/* for ( int i = channels(); i-- ) */
|
||||
|
@ -133,8 +135,20 @@ Playback_DS::disk_thread ( void )
|
|||
|
||||
}
|
||||
|
||||
if ( blocks_ready < _disk_io_blocks )
|
||||
{
|
||||
++blocks_ready;
|
||||
/* wait for more space */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* reset */
|
||||
blocks_ready = 1;
|
||||
|
||||
const nframes_t nframes = _nframes * _disk_io_blocks;
|
||||
|
||||
/* FIXME: should we not read from disk in larger-than-JACK-buffer blocks? */
|
||||
read_block( buf, _nframes );
|
||||
read_block( buf, nframes );
|
||||
|
||||
// unlock(); // for seeking
|
||||
|
||||
|
@ -157,22 +171,22 @@ Playback_DS::disk_thread ( void )
|
|||
|
||||
jack_ringbuffer_get_write_vector( _rb[ i ], rbd );
|
||||
|
||||
if ( rbd[ 0 ].len >= _nframes )
|
||||
if ( rbd[ 0 ].len >= nframes )
|
||||
/* it'll all fit in one go */
|
||||
buffer_deinterleave_one_channel( (sample_t*)rbd[ 0 ].buf, buf, i, channels(), _nframes );
|
||||
buffer_deinterleave_one_channel( (sample_t*)rbd[ 0 ].buf, buf, i, channels(), nframes );
|
||||
else if ( rbd[ 1 ].len )
|
||||
{
|
||||
/* there's enough space in the ringbuffer, but it's not contiguous */
|
||||
|
||||
/* do the first half */
|
||||
const nframes_t f = rbd[ 1 ].len / sizeof( sample_t );
|
||||
const nframes_t f = rbd[ 0 ].len / sizeof( sample_t );
|
||||
|
||||
buffer_deinterleave_one_channel( (sample_t*)rbd[ 0 ].buf, buf, i, channels(), f );
|
||||
|
||||
assert( rbd[ 1 ].len >= (_nframes - f) * sizeof( sample_t ) );
|
||||
assert( rbd[ 1 ].len >= (nframes - f) * sizeof( sample_t ) );
|
||||
|
||||
/* do the second half */
|
||||
buffer_deinterleave_one_channel( (sample_t*)rbd[ 1 ].buf, buf + f, i, channels(), _nframes - f );
|
||||
buffer_deinterleave_one_channel( (sample_t*)rbd[ 1 ].buf, buf + f, i, channels(), nframes - f );
|
||||
}
|
||||
else
|
||||
printf( "programming error: expected more space in ringbuffer\n" );
|
||||
|
@ -180,7 +194,7 @@ Playback_DS::disk_thread ( void )
|
|||
/* buffer_deinterleave_one_channel( (sample_t*)rbd.buf, buf, i, channels(), _nframes ); */
|
||||
/* jack_ringbuffer_write( _rb[ i ], (char*)cbuf, block_size ); */
|
||||
|
||||
jack_ringbuffer_write_advance( _rb[ i ], _nframes * sizeof( sample_t ) );
|
||||
jack_ringbuffer_write_advance( _rb[ i ], nframes * sizeof( sample_t ) );
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -55,16 +55,29 @@ Record_DS::disk_thread ( void )
|
|||
|
||||
printf( "IO thread running...\n" );
|
||||
|
||||
/* buffer to hold the interleaved data returned by the track reader */
|
||||
sample_t *buf = new sample_t[ _nframes * channels() ];
|
||||
sample_t *cbuf = new sample_t[ _nframes ];
|
||||
const nframes_t nframes = _nframes * _disk_io_blocks;
|
||||
|
||||
const size_t block_size = _nframes * sizeof( sample_t );
|
||||
/* buffer to hold the interleaved data returned by the track reader */
|
||||
sample_t *buf = new sample_t[ nframes * channels() ];
|
||||
sample_t *cbuf = new sample_t[ nframes ];
|
||||
|
||||
const size_t block_size = nframes * sizeof( sample_t );
|
||||
|
||||
int blocks_ready = 1;
|
||||
|
||||
while ( wait_for_block() )
|
||||
{
|
||||
/* pull data from the per-channel ringbuffers and interlace it */
|
||||
|
||||
if ( blocks_ready < _disk_io_blocks )
|
||||
{
|
||||
++blocks_ready;
|
||||
continue;
|
||||
}
|
||||
|
||||
blocks_ready = 1;
|
||||
|
||||
|
||||
/* pull data from the per-channel ringbuffers and interlace it */
|
||||
for ( int i = channels(); i--; )
|
||||
{
|
||||
|
||||
|
@ -79,7 +92,7 @@ Record_DS::disk_thread ( void )
|
|||
|
||||
jack_ringbuffer_read( _rb[ i ], (char*)cbuf, block_size );
|
||||
|
||||
buffer_interleave_one_channel( buf, cbuf, i, channels(), _nframes );
|
||||
buffer_interleave_one_channel( buf, cbuf, i, channels(), nframes );
|
||||
|
||||
|
||||
/* /\* deinterleave direcectly into the ringbuffer to avoid */
|
||||
|
@ -118,7 +131,7 @@ Record_DS::disk_thread ( void )
|
|||
|
||||
}
|
||||
|
||||
write_block( buf, _nframes );
|
||||
write_block( buf, nframes );
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -119,6 +119,9 @@ Track::init ( void )
|
|||
_show_all_takes = false;
|
||||
_size = 1;
|
||||
|
||||
record_ds = NULL;
|
||||
playback_ds = NULL;
|
||||
|
||||
labeltype( FL_NO_LABEL );
|
||||
|
||||
Fl_Group::size( timeline->w(), height() );
|
||||
|
@ -215,8 +218,6 @@ Track::init ( void )
|
|||
}
|
||||
end();
|
||||
|
||||
playback_ds = new Playback_DS( this, engine->frame_rate(), engine->nframes(), output.size() );
|
||||
record_ds = new Record_DS( this, engine->frame_rate(), engine->nframes(), input.size() );
|
||||
}
|
||||
|
||||
|
||||
|
@ -561,11 +562,14 @@ Track::configure_outputs ( int n )
|
|||
|
||||
// engine->lock();
|
||||
|
||||
if ( playback_ds )
|
||||
{
|
||||
Playback_DS *ds = playback_ds;
|
||||
playback_ds = NULL;
|
||||
|
||||
ds->shutdown();
|
||||
delete ds;
|
||||
}
|
||||
|
||||
if ( n > on )
|
||||
{
|
||||
|
@ -606,11 +610,14 @@ Track::configure_inputs ( int n )
|
|||
|
||||
// engine->lock();
|
||||
|
||||
if ( record_ds )
|
||||
{
|
||||
Record_DS *ds = record_ds;
|
||||
record_ds = NULL;
|
||||
|
||||
ds->shutdown();
|
||||
delete ds;
|
||||
}
|
||||
|
||||
if ( n > on )
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue