From 99e93c575eb3374087e0982a9abd3fff37afb2b9 Mon Sep 17 00:00:00 2001 From: Jonathan Moore Liles Date: Thu, 17 Apr 2008 14:19:41 -0500 Subject: [PATCH] Stream peaks to disk during capture. --- Timeline/Audio_File.H | 4 ++ Timeline/Audio_File_SF.C | 10 +++++ Timeline/Peaks.C | 86 +++++++++++++++++++++++++++++++++++----- Timeline/Peaks.H | 26 +++++++++++- Timeline/Record_DS.C | 1 - Timeline/Record_DS.H | 1 + 6 files changed, 115 insertions(+), 13 deletions(-) diff --git a/Timeline/Audio_File.H b/Timeline/Audio_File.H index d065c9f..e7a4a86 100644 --- a/Timeline/Audio_File.H +++ b/Timeline/Audio_File.H @@ -31,6 +31,8 @@ typedef float sample_t; #include using namespace std; +class Peak_Writer; + class Audio_File { static map _open_files; @@ -45,6 +47,8 @@ protected: Peaks *_peaks; + Peak_Writer *_peak_writer; + public: Audio_File ( ) diff --git a/Timeline/Audio_File_SF.C b/Timeline/Audio_File_SF.C index 0c271a5..4356121 100644 --- a/Timeline/Audio_File_SF.C +++ b/Timeline/Audio_File_SF.C @@ -27,6 +27,8 @@ #include +#include "Peaks.H" + Audio_File_SF * Audio_File_SF::from_file ( const char *filename ) { @@ -97,6 +99,9 @@ Audio_File_SF::create ( const char *filename, nframes_t samplerate, int channels c->_in = out; + /* FIXME: 256 ? */ + c->_peak_writer = new Peak_Writer( filename, 256, channels ); + return c; } @@ -127,6 +132,9 @@ Audio_File_SF::close ( void ) if ( _in ) sf_close( _in ); + if ( _peak_writer ) + delete _peak_writer; + _in = NULL; } @@ -194,5 +202,7 @@ Audio_File_SF::read ( sample_t *buf, int channel, nframes_t start, nframes_t end nframes_t Audio_File_SF::write ( sample_t *buf, nframes_t nframes ) { + _peak_writer->write( buf, nframes ); + return sf_writef_float( _in, buf, nframes ); } diff --git a/Timeline/Peaks.C b/Timeline/Peaks.C index f5d5e93..9fbbe5c 100644 --- a/Timeline/Peaks.C +++ b/Timeline/Peaks.C @@ -43,6 +43,17 @@ Peaks::peakbuffer Peaks::_peakbuf; +static +const char * +peakname ( const char *filename ) +{ + static char file[512]; + + snprintf( file, 512, "%s.peak", filename ); + + return (const char*)&file; +} + /** Prepare a buffer of peaks from /s/ to /e/ for reading. Must be * called before any calls to operator[] */ int @@ -253,15 +264,6 @@ Peaks::read_peaks ( nframes_t s, nframes_t e, int npeaks, int chunksize ) const /* return p; */ /* } */ -const char * -Peaks::peakname ( const char *filename ) const -{ - static char file[512]; - - snprintf( file, 512, "%s.peak", filename ); - - return (const char*)&file; -} bool Peaks::open ( void ) @@ -271,7 +273,7 @@ Peaks::open ( void ) int fd; if ( ! current() ) - /* Build peaks asyncronously */ + /* Build peaks asyncronously */ if ( ! fork() ) exit( make_peaks( 256 ) ); @@ -318,7 +320,7 @@ Peaks::current ( void ) const /* FIXME: we need to work out a way to run this in another thread and - possibly stream back the data to the GUI */ + possibly stream back the data to the GUI */ /** build peaks file for /filename/ if necessary */ bool Peaks::make_peaks ( int chunksize ) @@ -387,3 +389,65 @@ Peaks::make_peaks ( int chunksize ) /* return s; */ /* } */ + + + + + + +Peak_Writer::Peak_Writer ( const char *filename, int chunksize, int channels ) +{ + + _channels = channels; + _chunksize = chunksize; + + _peak = new Peak[ channels ]; + memset( _peak, 0, sizeof( Peak ) * channels ); + + if ( ! ( _fp = fopen( peakname( filename ), "w" ) ) ) + /* error! */; + + write_header(); +} + +Peak_Writer::~Peak_Writer ( ) +{ + fclose( _fp ); + delete _peak; +} + +void +Peak_Writer::write_header ( void ) +{ + fprintf( _fp, "NON-PEAKS%2d%2d", VERSION_MAJOR, VERSION_MINOR ); + + int data[] = { _chunksize, _channels, sizeof( Peak ) }; + + fwrite( &data, sizeof( data ), 1, _fp ); +} + +/** append peaks for samples in /buf/ to peakfile */ +void +Peak_Writer::write ( sample_t *buf, nframes_t nframes ) +{ + for ( int i = _chunksize; nframes--; --i, buf += _channels ) + { + for ( int j = 0; j < _channels; ++j ) + { + Peak *p = _peak + j; + + if ( *buf > p->max ) + p->max = *buf; + if ( *buf < p->min ) + p->min = *buf; + } + + if ( ! i ) + { + fwrite( _peak, sizeof( Peak ), _channels, _fp ); + memset( _peak, 0, sizeof( Peak ) * _channels ); + i = _chunksize; + } + + } +} diff --git a/Timeline/Peaks.H b/Timeline/Peaks.H index 87a6c74..6acac27 100644 --- a/Timeline/Peaks.H +++ b/Timeline/Peaks.H @@ -67,7 +67,7 @@ class Peaks int read_source_peaks ( Peak *peaks, int npeaks, int chunksize ) const; int read_peakfile_peaks ( Peak *peaks, nframes_t s, int npeaks, int chunksize ) const; - const char *peakname ( const char *filename ) const; +// const char *peakname ( const char *filename ) const; // Peaks ( ); @@ -104,3 +104,27 @@ public: Peak & operator[] ( int X ) const; }; + +#include + +class Peak_Writer +{ + + static const int VERSION_MAJOR = 0; + static const int VERSION_MINOR = 1; + + FILE *_fp; + Peak *_peak; + int _chunksize; + int _channels; + +public: + + Peak_Writer ( const char *filename, int chunksize, int channels ); + ~Peak_Writer ( ); + + void write_header ( void ); + void write ( sample_t *buf, nframes_t nframes ); + + +}; diff --git a/Timeline/Record_DS.C b/Timeline/Record_DS.C index fed14e7..6c8f672 100644 --- a/Timeline/Record_DS.C +++ b/Timeline/Record_DS.C @@ -142,7 +142,6 @@ Record_DS::start ( nframes_t frame ) } _af = Audio_File_SF::create( "testing.wav", 48000, channels(), "Wav/24" ); - _frame = frame; run(); diff --git a/Timeline/Record_DS.H b/Timeline/Record_DS.H index 238c0ec..6ef5554 100644 --- a/Timeline/Record_DS.H +++ b/Timeline/Record_DS.H @@ -23,6 +23,7 @@ #include "Audio_File_SF.H" class Audio_File; +class Peak_Writer; class Record_DS : public Disk_Stream {