| @@ -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; | |||
| @@ -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 ); | |||
| @@ -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 ); | |||
| @@ -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 */ | |||
| @@ -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 ) | |||
| { | |||
| @@ -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; | |||
| } | |||
| @@ -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 ); | |||
| @@ -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 ); | |||