Attempt to get rid of missing samples in playback for good.

This commit is contained in:
Jonathan Moore Liles 2008-05-01 21:19:12 -05:00
parent ea057edddc
commit 14a891e462
2 changed files with 31 additions and 11 deletions

View File

@ -42,8 +42,8 @@
/* 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 = 5.0f;
//float Disk_Stream::seconds_to_buffer = 2.0f; float Disk_Stream::seconds_to_buffer = 2.0f;
/* this is really only a rough estimate. The actual amount of data /* this is really only a rough estimate. The actual amount of data
read depends on many factors. Overlapping regions, for example, will read depends on many factors. Overlapping regions, for example, will
require more data to be read from disk, as will varying channel require more data to be read from disk, as will varying channel
@ -59,8 +59,7 @@ Disk_Stream::Disk_Stream ( Track *th, float frame_rate, nframes_t nframes, int c
_thread = 0; _thread = 0;
_terminate = false; _terminate = false;
_pending_seek = -1; _pending_seek = -1;
_xruns = 0;
printf( "nframes %lu\n", nframes );
_total_blocks = frame_rate * seconds_to_buffer / nframes; _total_blocks = frame_rate * seconds_to_buffer / nframes;
@ -77,8 +76,6 @@ Disk_Stream::Disk_Stream ( Track *th, float frame_rate, nframes_t nframes, int c
_rb.push_back( jack_ringbuffer_create( bufsize ) ); _rb.push_back( jack_ringbuffer_create( bufsize ) );
sem_init( &_blocks, 0, _total_blocks ); sem_init( &_blocks, 0, _total_blocks );
// run();
} }
Disk_Stream::~Disk_Stream ( ) Disk_Stream::~Disk_Stream ( )

View File

@ -85,6 +85,8 @@ Playback_DS::read_block ( sample_t *buf, nframes_t nframes )
timeline->unlock(); timeline->unlock();
} }
#define AVOID_UNNECESSARY_COPYING 1
/* THREAD: IO */ /* THREAD: IO */
void void
Playback_DS::disk_thread ( void ) Playback_DS::disk_thread ( void )
@ -94,6 +96,9 @@ Playback_DS::disk_thread ( void )
/* 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() * _disk_io_blocks ]; sample_t *buf = new sample_t[ _nframes * channels() * _disk_io_blocks ];
#ifndef AVOID_UNNECESSARY_COPYING
sample_t *cbuf = new sample_t[ _nframes * _disk_io_blocks ];
#endif
int blocks_ready = 1; int blocks_ready = 1;
@ -133,29 +138,40 @@ Playback_DS::disk_thread ( void )
/* deinterleave the buffer and stuff it into the per-channel ringbuffers */ /* deinterleave the buffer and stuff it into the per-channel ringbuffers */
const size_t block_size = nframes * sizeof( sample_t );
for ( int i = channels(); i--; ) for ( int i = channels(); i--; )
{ {
#ifdef AVOID_UNNECESSARY_COPYING
/* deinterleave direcectly into the ringbuffer to avoid /* deinterleave direcectly into the ringbuffer to avoid
* unnecessary copying */ * unnecessary copying */
jack_ringbuffer_data_t rbd[2]; jack_ringbuffer_data_t rbd[2];
memset( rbd, 0, sizeof( rbd ) );
jack_ringbuffer_get_write_vector( _rb[ i ], rbd ); jack_ringbuffer_get_write_vector( _rb[ i ], rbd );
const size_t block_size = nframes * sizeof( sample_t );
if ( rbd[ 0 ].len >= block_size ) if ( rbd[ 0 ].len >= block_size )
{
/* 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[ 0 ].len + rbd[ 1 ].len >= block_size ) else if ( rbd[ 0 ].len + rbd[ 1 ].len >= block_size )
{ {
/* there's enough space in the ringbuffer, but it's not contiguous */ /* there's enough space in the ringbuffer, but it's not contiguous */
assert( ! ( rbd[ 0 ].len % sizeof( sample_t ) ) );
// assert( ! ( rbd[ 1 ].len % sizeof( sample_t ) ) );
const nframes_t f = rbd[ 0 ].len / sizeof( sample_t ); const nframes_t f = rbd[ 0 ].len / sizeof( sample_t );
/* do the first half */ /* do the first half */
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 ) );
/* 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 );
} }
@ -164,16 +180,24 @@ Playback_DS::disk_thread ( void )
++_xruns; ++_xruns;
} }
/* 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 ], block_size ); jack_ringbuffer_write_advance( _rb[ i ], block_size );
#else
buffer_deinterleave_one_channel( cbuf, buf, i, channels(), nframes );
jack_ringbuffer_write( _rb[ i ], (char*)cbuf, block_size );
#endif
} }
} }
printf( "IO thread terminating.\n" ); printf( "IO thread terminating.\n" );
delete[] buf; delete[] buf;
#ifndef AVOID_UNNECESSARY_COPYING
delete[] cbuf;
#endif
} }
/* THREAD: RT */ /* THREAD: RT */
@ -194,7 +218,6 @@ Playback_DS::process ( nframes_t nframes )
if ( jack_ringbuffer_read( _rb[ i ], (char*)buf, block_size ) < block_size ) if ( jack_ringbuffer_read( _rb[ i ], (char*)buf, block_size ) < block_size )
{ {
++_xruns; ++_xruns;
printf( "RT: buffer underrun (disk can't keep up).\n" );
memset( buf, 0, block_size ); memset( buf, 0, block_size );
/* FIXME: we need to resync somehow */ /* FIXME: we need to resync somehow */
} }