| @@ -31,6 +31,8 @@ typedef float sample_t; | |||||
| #include <map> | #include <map> | ||||
| using namespace std; | using namespace std; | ||||
| class Peak_Writer; | |||||
| class Audio_File | class Audio_File | ||||
| { | { | ||||
| static map <string, Audio_File*> _open_files; | static map <string, Audio_File*> _open_files; | ||||
| @@ -45,6 +47,8 @@ protected: | |||||
| Peaks *_peaks; | Peaks *_peaks; | ||||
| Peak_Writer *_peak_writer; | |||||
| public: | public: | ||||
| Audio_File ( ) | Audio_File ( ) | ||||
| @@ -27,6 +27,8 @@ | |||||
| #include <assert.h> | #include <assert.h> | ||||
| #include "Peaks.H" | |||||
| Audio_File_SF * | Audio_File_SF * | ||||
| Audio_File_SF::from_file ( const char *filename ) | 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; | c->_in = out; | ||||
| /* FIXME: 256 ? */ | |||||
| c->_peak_writer = new Peak_Writer( filename, 256, channels ); | |||||
| return c; | return c; | ||||
| } | } | ||||
| @@ -127,6 +132,9 @@ Audio_File_SF::close ( void ) | |||||
| if ( _in ) | if ( _in ) | ||||
| sf_close( _in ); | sf_close( _in ); | ||||
| if ( _peak_writer ) | |||||
| delete _peak_writer; | |||||
| _in = NULL; | _in = NULL; | ||||
| } | } | ||||
| @@ -194,5 +202,7 @@ Audio_File_SF::read ( sample_t *buf, int channel, nframes_t start, nframes_t end | |||||
| nframes_t | nframes_t | ||||
| Audio_File_SF::write ( sample_t *buf, nframes_t nframes ) | Audio_File_SF::write ( sample_t *buf, nframes_t nframes ) | ||||
| { | { | ||||
| _peak_writer->write( buf, nframes ); | |||||
| return sf_writef_float( _in, buf, nframes ); | return sf_writef_float( _in, buf, nframes ); | ||||
| } | } | ||||
| @@ -43,6 +43,17 @@ | |||||
| Peaks::peakbuffer Peaks::_peakbuf; | 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 | /** Prepare a buffer of peaks from /s/ to /e/ for reading. Must be | ||||
| * called before any calls to operator[] */ | * called before any calls to operator[] */ | ||||
| int | int | ||||
| @@ -253,15 +264,6 @@ Peaks::read_peaks ( nframes_t s, nframes_t e, int npeaks, int chunksize ) const | |||||
| /* return p; */ | /* 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 | bool | ||||
| Peaks::open ( void ) | Peaks::open ( void ) | ||||
| @@ -271,7 +273,7 @@ Peaks::open ( void ) | |||||
| int fd; | int fd; | ||||
| if ( ! current() ) | if ( ! current() ) | ||||
| /* Build peaks asyncronously */ | |||||
| /* Build peaks asyncronously */ | |||||
| if ( ! fork() ) | if ( ! fork() ) | ||||
| exit( make_peaks( 256 ) ); | 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 | /* 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 */ | /** build peaks file for /filename/ if necessary */ | ||||
| bool | bool | ||||
| Peaks::make_peaks ( int chunksize ) | Peaks::make_peaks ( int chunksize ) | ||||
| @@ -387,3 +389,65 @@ Peaks::make_peaks ( int chunksize ) | |||||
| /* return s; */ | /* 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; | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -67,7 +67,7 @@ class Peaks | |||||
| int read_source_peaks ( Peak *peaks, int npeaks, int chunksize ) const; | 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; | 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 ( ); | // Peaks ( ); | ||||
| @@ -104,3 +104,27 @@ public: | |||||
| Peak & operator[] ( int X ) const; | Peak & operator[] ( int X ) const; | ||||
| }; | }; | ||||
| #include <stdio.h> | |||||
| 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 ); | |||||
| }; | |||||
| @@ -142,7 +142,6 @@ Record_DS::start ( nframes_t frame ) | |||||
| } | } | ||||
| _af = Audio_File_SF::create( "testing.wav", 48000, channels(), "Wav/24" ); | _af = Audio_File_SF::create( "testing.wav", 48000, channels(), "Wav/24" ); | ||||
| _frame = frame; | _frame = frame; | ||||
| run(); | run(); | ||||
| @@ -23,6 +23,7 @@ | |||||
| #include "Audio_File_SF.H" | #include "Audio_File_SF.H" | ||||
| class Audio_File; | class Audio_File; | ||||
| class Peak_Writer; | |||||
| class Record_DS : public Disk_Stream | class Record_DS : public Disk_Stream | ||||
| { | { | ||||