Browse Source

Read from disk in larger chunks.

tags/non-daw-v1.1.0
Jonathan Moore Liles 17 years ago
parent
commit
f596d205db
5 changed files with 75 additions and 36 deletions
  1. +14
    -11
      Timeline/Disk_Stream.C
  2. +2
    -0
      Timeline/Disk_Stream.H
  3. +23
    -9
      Timeline/Playback_DS.C
  4. +19
    -6
      Timeline/Record_DS.C
  5. +17
    -10
      Timeline/Track.C

+ 14
- 11
Timeline/Disk_Stream.C View File

@@ -37,25 +37,24 @@
that is, at startup time. The default is 5 seconds, which may or that is, at startup time. The default is 5 seconds, which may or
may not be excessive depending on various external factors. */ 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: deal with (jack) buffer size changes */
/* FIXME: needs error handling everywhere! */ /* 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 /* TODO: read/write data from/to disk in larger chunks to avoid
* excessive seeking. 256k is supposedly the sweetspot. */ * 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 ) Disk_Stream::Disk_Stream ( Track *th, float frame_rate, nframes_t nframes, int channels ) : _th( th )
{ {

assert( channels );

_frame = 0; _frame = 0;
_thread = 0; _thread = 0;
_terminate = false; _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 ); 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--; ) for ( int i = channels; i--; )
_rb.push_back( jack_ringbuffer_create( bufsize ) ); _rb.push_back( jack_ringbuffer_create( bufsize ) );




+ 2
- 0
Timeline/Disk_Stream.H View File

@@ -53,6 +53,7 @@ protected:
sem_t _blocks; /* semaphore to wake the IO thread with */ sem_t _blocks; /* semaphore to wake the IO thread with */


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 */


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;
@@ -83,6 +84,7 @@ public:


/* must be set before any Disk_Streams are created */ /* must be set before any Disk_Streams are created */
static float seconds_to_buffer; static float seconds_to_buffer;
static size_t disk_io_kbytes;


Disk_Stream ( Track *th, float frame_rate, nframes_t nframes, int channels ); Disk_Stream ( Track *th, float frame_rate, nframes_t nframes, int channels );




+ 23
- 9
Timeline/Playback_DS.C View File

@@ -109,9 +109,10 @@ Playback_DS::disk_thread ( void )
printf( "IO thread running...\n" ); printf( "IO thread running...\n" );


/* buffer to hold the interleaved data returned by the track reader */ /* 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() ) while ( wait_for_block() )
{ {
@@ -126,6 +127,7 @@ Playback_DS::disk_thread ( void )
printf( "performing seek\n" ); printf( "performing seek\n" );
_frame = _pending_seek; _frame = _pending_seek;
_pending_seek = -1; _pending_seek = -1;
blocks_ready = 1;
/* finish flushing the buffer */ /* finish flushing the buffer */


/* for ( int i = channels(); i-- ) */ /* 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? */ /* FIXME: should we not read from disk in larger-than-JACK-buffer blocks? */
read_block( buf, _nframes );
read_block( buf, nframes );


// unlock(); // for seeking // unlock(); // for seeking


@@ -157,22 +171,22 @@ Playback_DS::disk_thread ( void )


jack_ringbuffer_get_write_vector( _rb[ i ], rbd ); 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 */ /* 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 ) else if ( rbd[ 1 ].len )
{ {
/* there's enough space in the ringbuffer, but it's not contiguous */ /* there's enough space in the ringbuffer, but it's not contiguous */


/* do the first half */ /* 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 ); 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 */ /* 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 else
printf( "programming error: expected more space in ringbuffer\n" ); 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 ); */ /* buffer_deinterleave_one_channel( (sample_t*)rbd.buf, buf, i, channels(), _nframes ); */
/* jack_ringbuffer_write( _rb[ i ], (char*)cbuf, block_size ); */ /* 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 ) );








+ 19
- 6
Timeline/Record_DS.C View File

@@ -55,16 +55,29 @@ Record_DS::disk_thread ( void )


printf( "IO thread running...\n" ); printf( "IO thread running...\n" );


const nframes_t nframes = _nframes * _disk_io_blocks;

/* buffer to hold the interleaved data returned by the track reader */ /* 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 ];
sample_t *buf = new sample_t[ nframes * channels() ];
sample_t *cbuf = new sample_t[ nframes ];

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() ) 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--; ) for ( int i = channels(); i--; )
{ {


@@ -79,7 +92,7 @@ Record_DS::disk_thread ( void )


jack_ringbuffer_read( _rb[ i ], (char*)cbuf, block_size ); 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 */ /* /\* deinterleave direcectly into the ringbuffer to avoid */
@@ -118,7 +131,7 @@ Record_DS::disk_thread ( void )


} }


write_block( buf, _nframes );
write_block( buf, nframes );


} }




+ 17
- 10
Timeline/Track.C View File

@@ -119,6 +119,9 @@ Track::init ( void )
_show_all_takes = false; _show_all_takes = false;
_size = 1; _size = 1;


record_ds = NULL;
playback_ds = NULL;

labeltype( FL_NO_LABEL ); labeltype( FL_NO_LABEL );


Fl_Group::size( timeline->w(), height() ); Fl_Group::size( timeline->w(), height() );
@@ -215,8 +218,6 @@ Track::init ( void )
} }
end(); 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(); // engine->lock();


Playback_DS *ds = playback_ds;
playback_ds = NULL;
if ( playback_ds )
{
Playback_DS *ds = playback_ds;
playback_ds = NULL;


ds->shutdown();
delete ds;
ds->shutdown();
delete ds;
}


if ( n > on ) if ( n > on )
{ {
@@ -606,11 +610,14 @@ Track::configure_inputs ( int n )


// engine->lock(); // engine->lock();


Record_DS *ds = record_ds;
record_ds = NULL;
if ( record_ds )
{
Record_DS *ds = record_ds;
record_ds = NULL;


ds->shutdown();
delete ds;
ds->shutdown();
delete ds;
}


if ( n > on ) if ( n > on )
{ {


Loading…
Cancel
Save