diff --git a/Timeline/Engine/Disk_Stream.H b/Timeline/Engine/Disk_Stream.H index 356de56..594a171 100644 --- a/Timeline/Engine/Disk_Stream.H +++ b/Timeline/Engine/Disk_Stream.H @@ -51,7 +51,6 @@ protected: nframes_t _nframes; /* buffer size */ - nframes_t _frame; /* location of disk read */ 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 */ + volatile nframes_t _frame; /* location of disk read */ volatile nframes_t _pending_seek; /* absolute transport position to seek to */ volatile int _terminate; diff --git a/Timeline/Engine/Playback_DS.C b/Timeline/Engine/Playback_DS.C index ff049ec..9802339 100644 --- a/Timeline/Engine/Playback_DS.C +++ b/Timeline/Engine/Playback_DS.C @@ -49,7 +49,8 @@ Playback_DS::seek ( nframes_t frame ) { THREAD_ASSERT( RT ); - DMESSAGE( "requesting seek" ); + /* FIXME: non-RT-safe IO */ + DMESSAGE( "requesting seek to frame %lu", (unsigned long)frame ); if ( seek_pending() ) 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 ]; #endif - int blocks_ready = 1; + int blocks_ready = 0; const nframes_t nframes = _nframes * _disk_io_blocks; @@ -115,27 +116,22 @@ Playback_DS::disk_thread ( void ) if ( seek_pending() ) { - DMESSAGE( "performing seek" ); + /* FIXME: non-RT-safe IO */ + DMESSAGE( "performing seek to frame %lu", (unsigned long)_pending_seek ); _frame = _pending_seek; _pending_seek = -1; - blocks_ready = 1; - /* finish flushing the buffer */ - -/* for ( int i = channels(); i-- ) */ -/* jack_ringbuffer_write_advance( _rb[ i ], jack_ringbuffer_write_space( _rb[ i ] ) ); */ - + blocks_ready = 0; } - if ( blocks_ready < _disk_io_blocks ) + if ( ++blocks_ready < _disk_io_blocks ) { - ++blocks_ready; /* wait for more space */ continue; } /* reset */ - blocks_ready = 1; + blocks_ready = 0; read_block( buf, nframes ); @@ -211,6 +207,7 @@ Playback_DS::process ( nframes_t nframes ) { THREAD_ASSERT( RT ); + const size_t block_size = nframes * sizeof( sample_t ); // printf( "process: %lu %lu %lu\n", _frame, _frame + nframes, nframes ); diff --git a/Timeline/Engine/Record_DS.C b/Timeline/Engine/Record_DS.C index 13305dd..890af8e 100644 --- a/Timeline/Engine/Record_DS.C +++ b/Timeline/Engine/Record_DS.C @@ -72,7 +72,6 @@ Record_DS::disk_thread ( void ) DMESSAGE( "capture thread running..." ); - const nframes_t nframes = _nframes * _disk_io_blocks; /* 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 ); - int blocks_ready = 1; + int blocks_ready = 0; while ( wait_for_block() ) { - - if ( blocks_ready < _disk_io_blocks ) - { - ++blocks_ready; + if ( ++blocks_ready < _disk_io_blocks ) continue; - } - - blocks_ready = 1; + else + blocks_ready = 0; /* pull data from the per-channel ringbuffers and interlace it */ for ( int i = channels(); i--; ) @@ -204,6 +199,7 @@ Record_DS::disk_thread ( void ) _capture = NULL; /* now finalize the recording */ + track()->finalize( c, _stop_frame ); delete c; @@ -228,6 +224,8 @@ Record_DS::start ( nframes_t frame ) /* /\* FIXME: safe to do this here? *\/ */ /* flush(); */ + DMESSAGE( "recording started at frame %lu", (unsigned long)frame); + _frame = frame; _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 */ nframes_t Record_DS::process ( nframes_t nframes ) @@ -269,13 +270,40 @@ Record_DS::process ( nframes_t nframes ) if ( ! _recording ) 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--; ) { + /* read the entire input buffer */ 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; memset( buf, 0, block_size ); diff --git a/Timeline/Engine/Timeline.C b/Timeline/Engine/Timeline.C index c23edbd..8c980cc 100644 --- a/Timeline/Engine/Timeline.C +++ b/Timeline/Engine/Timeline.C @@ -38,6 +38,8 @@ Timeline::record ( void ) nframes_t frame = transport->frame; + DMESSAGE( "Going to record starting at frame %lu", (unsigned long)frame ); + for ( int i = tracks->children(); i-- ; ) { Track *t = (Track*)tracks->child( i ); @@ -85,7 +87,14 @@ Timeline::process ( nframes_t nframes ) { 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 */ diff --git a/Timeline/Engine/Track.C b/Timeline/Engine/Track.C index bf3e0d0..23d4122 100644 --- a/Timeline/Engine/Track.C +++ b/Timeline/Engine/Track.C @@ -151,33 +151,50 @@ Track::configure_inputs ( int n ) } nframes_t -Track::process ( nframes_t nframes ) +Track::process_input ( nframes_t nframes ) { THREAD_ASSERT( RT ); if ( ! transport->rolling ) { - for ( int i = output.size(); i--; ) - output[ i ].silence( nframes ); - 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 ); + + if ( ! transport->rolling ) + { + for ( int i = output.size(); i--; ) + output[ i ].silence( nframes ); + + return 0; + } + + /* FIXME: should we blank the control output here or leave it floating? */ for ( int i = control->children(); i--; ) ((Control_Sequence*)control->child( i ))->process( nframes ); if ( playback_ds ) - { - record_ds->process( nframes ); return playback_ds->process( nframes ); - } else return 0; } + + void Track::seek ( nframes_t frame ) { diff --git a/Timeline/Engine/dsp.C b/Timeline/Engine/dsp.C index 5145111..1745886 100644 --- a/Timeline/Engine/dsp.C +++ b/Timeline/Engine/dsp.C @@ -95,3 +95,15 @@ buffer_fill_with_silence ( sample_t *buf, nframes_t nframes ) { 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; +} diff --git a/Timeline/Engine/dsp.h b/Timeline/Engine/dsp.h index 716fd2a..d13ea05 100644 --- a/Timeline/Engine/dsp.h +++ b/Timeline/Engine/dsp.h @@ -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_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 ); +bool buffer_is_digital_black ( sample_t *buf, nframes_t nframes ); diff --git a/Timeline/Track.H b/Timeline/Track.H index 060da3d..28e894c 100644 --- a/Timeline/Track.H +++ b/Timeline/Track.H @@ -207,7 +207,8 @@ public: const Audio_Region *capture_region ( void ) const; 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 record ( Capture *c, nframes_t frame );