Cleanup capture code and eliminate off-by-one-buffer bug when bouncing tracks.
This commit is contained in:
parent
f3226cd1a0
commit
fed042950f
|
@ -51,7 +51,6 @@ protected:
|
||||||
|
|
||||||
nframes_t _nframes; /* buffer size */
|
nframes_t _nframes; /* buffer size */
|
||||||
|
|
||||||
nframes_t _frame; /* location of disk read */
|
|
||||||
|
|
||||||
std::vector < jack_ringbuffer_t * >_rb; /* one ringbuffer for each channel */
|
std::vector < jack_ringbuffer_t * >_rb; /* one ringbuffer for each channel */
|
||||||
|
|
||||||
|
@ -63,6 +62,7 @@ protected:
|
||||||
|
|
||||||
nframes_t _frame_rate; /* used for buffer size calculations */
|
nframes_t _frame_rate; /* used for buffer size calculations */
|
||||||
|
|
||||||
|
volatile nframes_t _frame; /* location of disk read */
|
||||||
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;
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,8 @@ Playback_DS::seek ( nframes_t frame )
|
||||||
{
|
{
|
||||||
THREAD_ASSERT( RT );
|
THREAD_ASSERT( RT );
|
||||||
|
|
||||||
DMESSAGE( "requesting seek" );
|
/* FIXME: non-RT-safe IO */
|
||||||
|
DMESSAGE( "requesting seek to frame %lu", (unsigned long)frame );
|
||||||
|
|
||||||
if ( seek_pending() )
|
if ( seek_pending() )
|
||||||
printf( "seek error, attempt to seek while seek is pending\n" );
|
printf( "seek error, attempt to seek while seek is pending\n" );
|
||||||
|
@ -104,7 +105,7 @@ Playback_DS::disk_thread ( void )
|
||||||
sample_t *cbuf = new sample_t[ _nframes * _disk_io_blocks ];
|
sample_t *cbuf = new sample_t[ _nframes * _disk_io_blocks ];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int blocks_ready = 1;
|
int blocks_ready = 0;
|
||||||
|
|
||||||
const nframes_t nframes = _nframes * _disk_io_blocks;
|
const nframes_t nframes = _nframes * _disk_io_blocks;
|
||||||
|
|
||||||
|
@ -115,27 +116,22 @@ Playback_DS::disk_thread ( void )
|
||||||
|
|
||||||
if ( seek_pending() )
|
if ( seek_pending() )
|
||||||
{
|
{
|
||||||
DMESSAGE( "performing seek" );
|
/* FIXME: non-RT-safe IO */
|
||||||
|
DMESSAGE( "performing seek to frame %lu", (unsigned long)_pending_seek );
|
||||||
|
|
||||||
_frame = _pending_seek;
|
_frame = _pending_seek;
|
||||||
_pending_seek = -1;
|
_pending_seek = -1;
|
||||||
blocks_ready = 1;
|
blocks_ready = 0;
|
||||||
/* finish flushing the buffer */
|
|
||||||
|
|
||||||
/* for ( int i = channels(); i-- ) */
|
|
||||||
/* jack_ringbuffer_write_advance( _rb[ i ], jack_ringbuffer_write_space( _rb[ i ] ) ); */
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( blocks_ready < _disk_io_blocks )
|
if ( ++blocks_ready < _disk_io_blocks )
|
||||||
{
|
{
|
||||||
++blocks_ready;
|
|
||||||
/* wait for more space */
|
/* wait for more space */
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* reset */
|
/* reset */
|
||||||
blocks_ready = 1;
|
blocks_ready = 0;
|
||||||
|
|
||||||
read_block( buf, nframes );
|
read_block( buf, nframes );
|
||||||
|
|
||||||
|
@ -211,6 +207,7 @@ Playback_DS::process ( nframes_t nframes )
|
||||||
{
|
{
|
||||||
THREAD_ASSERT( RT );
|
THREAD_ASSERT( RT );
|
||||||
|
|
||||||
|
|
||||||
const size_t block_size = nframes * sizeof( sample_t );
|
const size_t block_size = nframes * sizeof( sample_t );
|
||||||
|
|
||||||
// printf( "process: %lu %lu %lu\n", _frame, _frame + nframes, nframes );
|
// printf( "process: %lu %lu %lu\n", _frame, _frame + nframes, nframes );
|
||||||
|
|
|
@ -72,7 +72,6 @@ Record_DS::disk_thread ( void )
|
||||||
|
|
||||||
DMESSAGE( "capture thread running..." );
|
DMESSAGE( "capture thread running..." );
|
||||||
|
|
||||||
|
|
||||||
const nframes_t nframes = _nframes * _disk_io_blocks;
|
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 */
|
||||||
|
@ -83,18 +82,14 @@ Record_DS::disk_thread ( void )
|
||||||
|
|
||||||
const size_t block_size = nframes * sizeof( sample_t );
|
const size_t block_size = nframes * sizeof( sample_t );
|
||||||
|
|
||||||
int blocks_ready = 1;
|
int blocks_ready = 0;
|
||||||
|
|
||||||
while ( wait_for_block() )
|
while ( wait_for_block() )
|
||||||
{
|
{
|
||||||
|
if ( ++blocks_ready < _disk_io_blocks )
|
||||||
if ( blocks_ready < _disk_io_blocks )
|
|
||||||
{
|
|
||||||
++blocks_ready;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
else
|
||||||
|
blocks_ready = 0;
|
||||||
blocks_ready = 1;
|
|
||||||
|
|
||||||
/* pull data from the per-channel ringbuffers and interlace it */
|
/* pull data from the per-channel ringbuffers and interlace it */
|
||||||
for ( int i = channels(); i--; )
|
for ( int i = channels(); i--; )
|
||||||
|
@ -204,6 +199,7 @@ Record_DS::disk_thread ( void )
|
||||||
_capture = NULL;
|
_capture = NULL;
|
||||||
|
|
||||||
/* now finalize the recording */
|
/* now finalize the recording */
|
||||||
|
|
||||||
track()->finalize( c, _stop_frame );
|
track()->finalize( c, _stop_frame );
|
||||||
|
|
||||||
delete c;
|
delete c;
|
||||||
|
@ -228,6 +224,8 @@ Record_DS::start ( nframes_t frame )
|
||||||
/* /\* FIXME: safe to do this here? *\/ */
|
/* /\* FIXME: safe to do this here? *\/ */
|
||||||
/* flush(); */
|
/* flush(); */
|
||||||
|
|
||||||
|
DMESSAGE( "recording started at frame %lu", (unsigned long)frame);
|
||||||
|
|
||||||
_frame = frame;
|
_frame = frame;
|
||||||
|
|
||||||
_capture = new Track::Capture;
|
_capture = new Track::Capture;
|
||||||
|
@ -260,6 +258,9 @@ Record_DS::stop ( nframes_t frame )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#include "../Transport.H"
|
||||||
|
extern Transport *transport;
|
||||||
|
|
||||||
/** read from the attached track's ports and stuff the ringbuffers */
|
/** read from the attached track's ports and stuff the ringbuffers */
|
||||||
nframes_t
|
nframes_t
|
||||||
Record_DS::process ( nframes_t nframes )
|
Record_DS::process ( nframes_t nframes )
|
||||||
|
@ -269,13 +270,40 @@ Record_DS::process ( nframes_t nframes )
|
||||||
if ( ! _recording )
|
if ( ! _recording )
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
const size_t block_size = nframes * sizeof( sample_t );
|
if ( transport->frame < _frame )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* DMESSAGE( "recording actually happening at %lu (start frame %lu)", (unsigned long)transport->frame, (unsigned long)_frame); */
|
||||||
|
|
||||||
|
nframes_t offset = 0;
|
||||||
|
|
||||||
|
if ( _frame > transport->frame &&
|
||||||
|
_frame < transport->frame + nframes )
|
||||||
|
{
|
||||||
|
/* The record start frame falls somewhere within the current
|
||||||
|
buffer. We must discard the unneeded portion and only
|
||||||
|
stuff the part requested into the ringbuffer. */
|
||||||
|
|
||||||
|
offset = _frame - transport->frame;
|
||||||
|
|
||||||
|
/* DMESSAGE( "offset = %lu", (unsigned long)offset ); */
|
||||||
|
}
|
||||||
|
|
||||||
|
const size_t offset_size = offset * sizeof( sample_t );
|
||||||
|
const size_t block_size = ( nframes * sizeof( sample_t ) ) - offset_size;
|
||||||
|
|
||||||
for ( int i = channels(); i--; )
|
for ( int i = channels(); i--; )
|
||||||
{
|
{
|
||||||
|
/* read the entire input buffer */
|
||||||
void *buf = track()->input[ i ].buffer( nframes );
|
void *buf = track()->input[ i ].buffer( nframes );
|
||||||
|
|
||||||
if ( jack_ringbuffer_write( _rb[ i ], (char*)buf, block_size ) < block_size )
|
/* if ( buffer_is_digital_black( (sample_t*)buf, nframes ) ) */
|
||||||
|
/* DWARNING( "recording an entirely blank buffer" ); */
|
||||||
|
|
||||||
|
/* FIXME: this results in a ringbuffer size that is no longer
|
||||||
|
necessarily a multiple of nframes... how will the other side
|
||||||
|
handle that? */
|
||||||
|
if ( jack_ringbuffer_write( _rb[ i ], (char*)buf + offset, block_size ) < block_size )
|
||||||
{
|
{
|
||||||
++_xruns;
|
++_xruns;
|
||||||
memset( buf, 0, block_size );
|
memset( buf, 0, block_size );
|
||||||
|
|
|
@ -38,6 +38,8 @@ Timeline::record ( void )
|
||||||
|
|
||||||
nframes_t frame = transport->frame;
|
nframes_t frame = transport->frame;
|
||||||
|
|
||||||
|
DMESSAGE( "Going to record starting at frame %lu", (unsigned long)frame );
|
||||||
|
|
||||||
for ( int i = tracks->children(); i-- ; )
|
for ( int i = tracks->children(); i-- ; )
|
||||||
{
|
{
|
||||||
Track *t = (Track*)tracks->child( i );
|
Track *t = (Track*)tracks->child( i );
|
||||||
|
@ -85,7 +87,14 @@ Timeline::process ( nframes_t nframes )
|
||||||
{
|
{
|
||||||
Track *t = (Track*)tracks->child( i );
|
Track *t = (Track*)tracks->child( i );
|
||||||
|
|
||||||
t->process( nframes );
|
t->process_output( nframes );
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( int i = tracks->children(); i-- ; )
|
||||||
|
{
|
||||||
|
Track *t = (Track*)tracks->child( i );
|
||||||
|
|
||||||
|
t->process_input( nframes );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: BOGUS */
|
/* FIXME: BOGUS */
|
||||||
|
|
|
@ -151,7 +151,27 @@ Track::configure_inputs ( int n )
|
||||||
}
|
}
|
||||||
|
|
||||||
nframes_t
|
nframes_t
|
||||||
Track::process ( nframes_t nframes )
|
Track::process_input ( nframes_t nframes )
|
||||||
|
{
|
||||||
|
THREAD_ASSERT( RT );
|
||||||
|
|
||||||
|
if ( ! transport->rolling )
|
||||||
|
{
|
||||||
|
for ( int i = input.size(); i--; )
|
||||||
|
input[ i ].silence( nframes );
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( record_ds )
|
||||||
|
return record_ds->process( nframes );
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
nframes_t
|
||||||
|
Track::process_output ( nframes_t nframes )
|
||||||
{
|
{
|
||||||
THREAD_ASSERT( RT );
|
THREAD_ASSERT( RT );
|
||||||
|
|
||||||
|
@ -160,24 +180,21 @@ Track::process ( nframes_t nframes )
|
||||||
for ( int i = output.size(); i--; )
|
for ( int i = output.size(); i--; )
|
||||||
output[ i ].silence( nframes );
|
output[ i ].silence( nframes );
|
||||||
|
|
||||||
for ( int i = input.size(); i--; )
|
|
||||||
input[ i ].silence( nframes );
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* FIXME: should we blank the control output here or leave it floating? */
|
||||||
for ( int i = control->children(); i--; )
|
for ( int i = control->children(); i--; )
|
||||||
((Control_Sequence*)control->child( i ))->process( nframes );
|
((Control_Sequence*)control->child( i ))->process( nframes );
|
||||||
|
|
||||||
if ( playback_ds )
|
if ( playback_ds )
|
||||||
{
|
|
||||||
record_ds->process( nframes );
|
|
||||||
return playback_ds->process( nframes );
|
return playback_ds->process( nframes );
|
||||||
}
|
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Track::seek ( nframes_t frame )
|
Track::seek ( nframes_t frame )
|
||||||
{
|
{
|
||||||
|
|
|
@ -95,3 +95,15 @@ buffer_fill_with_silence ( sample_t *buf, nframes_t nframes )
|
||||||
{
|
{
|
||||||
memset( buf, 0, nframes * sizeof( sample_t ) );
|
memset( buf, 0, nframes * sizeof( sample_t ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
buffer_is_digital_black ( sample_t *buf, nframes_t nframes )
|
||||||
|
{
|
||||||
|
while ( nframes-- )
|
||||||
|
{
|
||||||
|
if ( 0 != buf[nframes] )
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
|
@ -29,3 +29,4 @@ void buffer_interleave_one_channel ( sample_t *dst, sample_t *src, int channel,
|
||||||
void buffer_interleave_one_channel_and_mix ( sample_t *dst, sample_t *src, int channel, int channels, nframes_t nframes );
|
void buffer_interleave_one_channel_and_mix ( sample_t *dst, sample_t *src, int channel, int channels, nframes_t nframes );
|
||||||
void buffer_deinterleave_one_channel ( sample_t *dst, sample_t *src, int channel, int channels, nframes_t nframes );
|
void buffer_deinterleave_one_channel ( sample_t *dst, sample_t *src, int channel, int channels, nframes_t nframes );
|
||||||
void buffer_fill_with_silence ( sample_t *buf, nframes_t nframes );
|
void buffer_fill_with_silence ( sample_t *buf, nframes_t nframes );
|
||||||
|
bool buffer_is_digital_black ( sample_t *buf, nframes_t nframes );
|
||||||
|
|
|
@ -207,7 +207,8 @@ public:
|
||||||
const Audio_Region *capture_region ( void ) const;
|
const Audio_Region *capture_region ( void ) const;
|
||||||
|
|
||||||
void resize_buffers ( nframes_t nframes );
|
void resize_buffers ( nframes_t nframes );
|
||||||
nframes_t process ( nframes_t nframes );
|
nframes_t process_input ( nframes_t nframes );
|
||||||
|
nframes_t process_output ( nframes_t nframes );
|
||||||
void seek ( nframes_t frame );
|
void seek ( nframes_t frame );
|
||||||
|
|
||||||
void record ( Capture *c, nframes_t frame );
|
void record ( Capture *c, nframes_t frame );
|
||||||
|
|
Loading…
Reference in New Issue