|
@@ -35,8 +35,6 @@ |
|
|
#include <stdio.h> |
|
|
#include <stdio.h> |
|
|
#include <string.h> |
|
|
#include <string.h> |
|
|
|
|
|
|
|
|
#include "../Transport.H" // for .recording |
|
|
|
|
|
|
|
|
|
|
|
#include "Audio_File.H" |
|
|
#include "Audio_File.H" |
|
|
#include "Peaks.H" |
|
|
#include "Peaks.H" |
|
|
|
|
|
|
|
@@ -53,8 +51,19 @@ |
|
|
using std::min; |
|
|
using std::min; |
|
|
using std::max; |
|
|
using std::max; |
|
|
|
|
|
|
|
|
|
|
|
#include <math.h> |
|
|
|
|
|
|
|
|
#include <stdint.h> |
|
|
#include <stdint.h> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct peak_thread_data |
|
|
|
|
|
{ |
|
|
|
|
|
void(*callback)(void*); |
|
|
|
|
|
void *userdata; |
|
|
|
|
|
Peaks *peaks; |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* whether to cache peaks at multiple resolutions on disk to |
|
|
/* whether to cache peaks at multiple resolutions on disk to |
|
@@ -82,31 +91,6 @@ peakname ( const char *filename ) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Peaks::Peaks ( Audio_File *c ) |
|
|
|
|
|
{ |
|
|
|
|
|
_pending = false; |
|
|
|
|
|
_clip = c; |
|
|
|
|
|
_peak_writer = NULL; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Peaks::~Peaks ( ) |
|
|
|
|
|
{ |
|
|
|
|
|
if ( _peak_writer ) |
|
|
|
|
|
delete _peak_writer; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Prepare a buffer of peaks from /s/ to /e/ for reading. Must be |
|
|
|
|
|
* called before any calls to operator[] */ |
|
|
|
|
|
int |
|
|
|
|
|
Peaks::fill_buffer ( float fpp, nframes_t s, nframes_t e ) const |
|
|
|
|
|
{ |
|
|
|
|
|
_fpp = fpp; |
|
|
|
|
|
|
|
|
|
|
|
return read_peaks( s, (e - s) / fpp, fpp ); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct peakfile_block_header |
|
|
struct peakfile_block_header |
|
|
{ |
|
|
{ |
|
@@ -121,15 +105,15 @@ class Peakfile |
|
|
nframes_t _chunksize; |
|
|
nframes_t _chunksize; |
|
|
int _channels; /* number of channels this peakfile represents */ |
|
|
int _channels; /* number of channels this peakfile represents */ |
|
|
nframes_t _length; /* length, in frames, of the clip this peakfile represents */ |
|
|
nframes_t _length; /* length, in frames, of the clip this peakfile represents */ |
|
|
size_t _offset; |
|
|
|
|
|
int _blocks; |
|
|
|
|
|
|
|
|
off_t _offset; |
|
|
|
|
|
// int _blocks; |
|
|
|
|
|
|
|
|
struct block_descriptor |
|
|
struct block_descriptor |
|
|
{ |
|
|
{ |
|
|
nframes_t chunksize; |
|
|
nframes_t chunksize; |
|
|
size_t pos; |
|
|
|
|
|
|
|
|
off_t pos; |
|
|
|
|
|
|
|
|
block_descriptor ( nframes_t chunksize, size_t pos ) : chunksize( chunksize ), pos( pos ) |
|
|
|
|
|
|
|
|
block_descriptor ( nframes_t chunksize, off_t pos ) : chunksize( chunksize ), pos( pos ) |
|
|
{ |
|
|
{ |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@@ -139,16 +123,18 @@ class Peakfile |
|
|
} |
|
|
} |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
std::list <block_descriptor> blocks; |
|
|
|
|
|
|
|
|
public: |
|
|
public: |
|
|
|
|
|
|
|
|
Peakfile ( ) |
|
|
Peakfile ( ) |
|
|
{ |
|
|
{ |
|
|
_blocks = 0; |
|
|
|
|
|
|
|
|
// _blocks = 0; |
|
|
_fp = NULL; |
|
|
_fp = NULL; |
|
|
_offset = 0; |
|
|
_offset = 0; |
|
|
_chunksize = 0; |
|
|
_chunksize = 0; |
|
|
_channels = 0; |
|
|
_channels = 0; |
|
|
|
|
|
_length = 0; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
~Peakfile ( ) |
|
|
~Peakfile ( ) |
|
@@ -157,52 +143,59 @@ public: |
|
|
close(); |
|
|
close(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
int blocks ( void ) const { return _blocks; } |
|
|
|
|
|
|
|
|
/* int blocks ( void ) const { return blocks.size(); } */ |
|
|
/** find the best block for /chunksize/ */ |
|
|
/** find the best block for /chunksize/ */ |
|
|
void |
|
|
void |
|
|
scan ( nframes_t chunksize ) |
|
|
scan ( nframes_t chunksize ) |
|
|
{ |
|
|
{ |
|
|
rewind( _fp ); |
|
|
|
|
|
clearerr( _fp ); |
|
|
|
|
|
|
|
|
|
|
|
std::list <block_descriptor> blocks; |
|
|
|
|
|
|
|
|
|
|
|
/* scan all blocks */ |
|
|
|
|
|
for ( ;; ) |
|
|
|
|
|
|
|
|
if ( ! blocks.size() ) |
|
|
{ |
|
|
{ |
|
|
peakfile_block_header bh; |
|
|
|
|
|
|
|
|
|
|
|
fread( &bh, sizeof( bh ), 1, _fp ); |
|
|
|
|
|
|
|
|
|
|
|
if ( feof( _fp ) ) |
|
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
// printf( "chunksize=%lu, skip=%lu\n", (unsigned long)bh.chunksize, (unsigned long) bh.skip ); |
|
|
|
|
|
|
|
|
|
|
|
ASSERT( bh.chunksize, "Chucksize of zero. Invalid peak file structure!" ); |
|
|
|
|
|
|
|
|
|
|
|
blocks.push_back( block_descriptor( bh.chunksize, ftell( _fp ) ) ); |
|
|
|
|
|
|
|
|
|
|
|
if ( ! bh.skip ) |
|
|
|
|
|
/* last block */ |
|
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
if ( fseek( _fp, bh.skip, SEEK_CUR ) ) |
|
|
|
|
|
|
|
|
rewind( _fp ); |
|
|
|
|
|
clearerr( _fp ); |
|
|
|
|
|
|
|
|
|
|
|
/* scan all blocks */ |
|
|
|
|
|
for ( ;; ) |
|
|
{ |
|
|
{ |
|
|
WARNING( "seek failed: %s (%lu)", strerror( errno ), bh.skip ); |
|
|
|
|
|
break; |
|
|
|
|
|
|
|
|
peakfile_block_header bh; |
|
|
|
|
|
|
|
|
|
|
|
fread( &bh, sizeof( bh ), 1, _fp ); |
|
|
|
|
|
|
|
|
|
|
|
if ( feof( _fp ) ) |
|
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
DMESSAGE( "Peakfile: chunksize=%lu, skip=%lu\n", (uint64_t)bh.chunksize, (uint64_t) bh.skip ); |
|
|
|
|
|
|
|
|
|
|
|
ASSERT( bh.chunksize, "Chucksize of zero. Invalid peak file structure!" ); |
|
|
|
|
|
|
|
|
|
|
|
blocks.push_back( block_descriptor( bh.chunksize, ftello( _fp ) ) ); |
|
|
|
|
|
|
|
|
|
|
|
if ( ! bh.skip ) |
|
|
|
|
|
/* last block */ |
|
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
if ( fseeko( _fp, bh.skip, SEEK_CUR ) ) |
|
|
|
|
|
{ |
|
|
|
|
|
WARNING( "seek failed: %s (%lu)", strerror( errno ), bh.skip ); |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if ( ! blocks.size() ) |
|
|
if ( ! blocks.size() ) |
|
|
FATAL( "Peak file contains no blocks!" ); |
|
|
FATAL( "Peak file contains no blocks!" ); |
|
|
|
|
|
|
|
|
|
|
|
if ( chunksize == _chunksize ) |
|
|
|
|
|
{ |
|
|
|
|
|
return; |
|
|
|
|
|
/* already on the right block... */ |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
// DMESSAGE( "peakfile has %d blocks.", blocks.size() ); |
|
|
// DMESSAGE( "peakfile has %d blocks.", blocks.size() ); |
|
|
|
|
|
|
|
|
blocks.sort(); |
|
|
blocks.sort(); |
|
|
|
|
|
|
|
|
/* fall back on the smallest chunksize */ |
|
|
/* fall back on the smallest chunksize */ |
|
|
fseek( _fp, blocks.front().pos, SEEK_SET ); |
|
|
|
|
|
|
|
|
fseeko( _fp, blocks.front().pos, SEEK_SET ); |
|
|
_chunksize = blocks.front().chunksize; |
|
|
_chunksize = blocks.front().chunksize; |
|
|
|
|
|
|
|
|
/* search for the best-fit chunksize */ |
|
|
/* search for the best-fit chunksize */ |
|
@@ -211,19 +204,19 @@ public: |
|
|
if ( chunksize >= i->chunksize ) |
|
|
if ( chunksize >= i->chunksize ) |
|
|
{ |
|
|
{ |
|
|
_chunksize = i->chunksize; |
|
|
_chunksize = i->chunksize; |
|
|
fseek( _fp, i->pos, SEEK_SET ); |
|
|
|
|
|
|
|
|
fseeko( _fp, i->pos, SEEK_SET ); |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// DMESSAGE( "using peakfile block for chunksize %lu", _chunksize ); |
|
|
// DMESSAGE( "using peakfile block for chunksize %lu", _chunksize ); |
|
|
_blocks = blocks.size(); |
|
|
|
|
|
_offset = ftell( _fp ); |
|
|
|
|
|
|
|
|
// _blocks = blocks.size(); |
|
|
|
|
|
_offset = ftello( _fp ); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/** convert frame number of peak number */ |
|
|
/** convert frame number of peak number */ |
|
|
nframes_t frame_to_peak ( nframes_t frame ) |
|
|
nframes_t frame_to_peak ( nframes_t frame ) |
|
|
{ |
|
|
{ |
|
|
return frame * _channels / _chunksize; |
|
|
|
|
|
|
|
|
return ( frame / _chunksize ) * (nframes_t)_channels; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/** return the number of peaks in already open peakfile /fp/ */ |
|
|
/** return the number of peaks in already open peakfile /fp/ */ |
|
@@ -241,7 +234,7 @@ public: |
|
|
bool |
|
|
bool |
|
|
ready ( nframes_t start, nframes_t npeaks ) |
|
|
ready ( nframes_t start, nframes_t npeaks ) |
|
|
{ |
|
|
{ |
|
|
if ( _blocks > 1 ) |
|
|
|
|
|
|
|
|
if ( blocks.size() > 1 ) |
|
|
return true; |
|
|
return true; |
|
|
else |
|
|
else |
|
|
return this->npeaks() > frame_to_peak( start ) + npeaks; |
|
|
return this->npeaks() > frame_to_peak( start ) + npeaks; |
|
@@ -251,7 +244,7 @@ public: |
|
|
bool |
|
|
bool |
|
|
open ( const char *name, int channels, nframes_t chunksize ) |
|
|
open ( const char *name, int channels, nframes_t chunksize ) |
|
|
{ |
|
|
{ |
|
|
_chunksize = 0; |
|
|
|
|
|
|
|
|
// _chunksize = 0; |
|
|
_channels = channels; |
|
|
_channels = channels; |
|
|
|
|
|
|
|
|
char *pn = peakname( name ); |
|
|
char *pn = peakname( name ); |
|
@@ -305,7 +298,7 @@ public: |
|
|
* large enough to fit the entire request. Returns the number of |
|
|
* large enough to fit the entire request. Returns the number of |
|
|
* peaks actually read, which may be fewer than were requested. */ |
|
|
* peaks actually read, which may be fewer than were requested. */ |
|
|
nframes_t |
|
|
nframes_t |
|
|
read_peaks ( Peak *peaks, nframes_t s, int npeaks, nframes_t chunksize ) |
|
|
|
|
|
|
|
|
read_peaks ( Peak *peaks, nframes_t s, nframes_t npeaks, nframes_t chunksize ) |
|
|
{ |
|
|
{ |
|
|
if ( ! _fp ) |
|
|
if ( ! _fp ) |
|
|
{ |
|
|
{ |
|
@@ -316,12 +309,19 @@ public: |
|
|
const unsigned int ratio = chunksize / _chunksize; |
|
|
const unsigned int ratio = chunksize / _chunksize; |
|
|
|
|
|
|
|
|
/* locate to start position */ |
|
|
/* locate to start position */ |
|
|
if ( fseek( _fp, _offset + ( frame_to_peak( s ) * sizeof( Peak ) ), SEEK_SET ) ) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* if ( s > _clip->length() ) */ |
|
|
|
|
|
/* return 0; */ |
|
|
|
|
|
|
|
|
|
|
|
if ( fseeko( _fp, _offset + ( frame_to_peak( s ) * sizeof( Peak ) ), SEEK_SET ) ) |
|
|
{ |
|
|
{ |
|
|
DMESSAGE( "failed to seek... peaks not ready?" ); |
|
|
DMESSAGE( "failed to seek... peaks not ready?" ); |
|
|
return 0; |
|
|
return 0; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if ( feof( _fp ) ) |
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
|
if ( ratio == 1 ) |
|
|
if ( ratio == 1 ) |
|
|
return fread( peaks, sizeof( Peak ) * _channels, npeaks, _fp ); |
|
|
return fread( peaks, sizeof( Peak ) * _channels, npeaks, _fp ); |
|
|
|
|
|
|
|
@@ -329,7 +329,7 @@ public: |
|
|
|
|
|
|
|
|
nframes_t len = 0; |
|
|
nframes_t len = 0; |
|
|
|
|
|
|
|
|
int i; |
|
|
|
|
|
|
|
|
nframes_t i; |
|
|
|
|
|
|
|
|
for ( i = 0; i < npeaks; ++i ) |
|
|
for ( i = 0; i < npeaks; ++i ) |
|
|
{ |
|
|
{ |
|
@@ -358,8 +358,10 @@ public: |
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if ( len < ratio ) |
|
|
|
|
|
|
|
|
if ( feof( _fp) || len < ratio ) |
|
|
|
|
|
{ |
|
|
break; |
|
|
break; |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
delete[] pbuf; |
|
|
delete[] pbuf; |
|
@@ -368,8 +370,43 @@ public: |
|
|
} |
|
|
} |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Peaks::Peaks ( Audio_File *c ) |
|
|
|
|
|
{ |
|
|
|
|
|
_pending = false; |
|
|
|
|
|
_clip = c; |
|
|
|
|
|
_peak_writer = NULL; |
|
|
|
|
|
_peakfile = new Peakfile(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Peaks::~Peaks ( ) |
|
|
|
|
|
{ |
|
|
|
|
|
if ( _peak_writer ) |
|
|
|
|
|
{ |
|
|
|
|
|
delete _peak_writer; |
|
|
|
|
|
_peak_writer = NULL; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
delete _peakfile; |
|
|
|
|
|
_peakfile = NULL; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Prepare a buffer of peaks from /s/ to /e/ for reading. Must be |
|
|
|
|
|
* called before any calls to operator[] */ |
|
|
|
|
|
int |
|
|
|
|
|
Peaks::fill_buffer ( float fpp, nframes_t s, nframes_t e ) const |
|
|
|
|
|
{ |
|
|
|
|
|
_fpp = fpp; |
|
|
|
|
|
|
|
|
|
|
|
return read_peaks( s, (e - s) / fpp, fpp ); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool |
|
|
bool |
|
|
Peaks::ready ( nframes_t s, int npeaks, nframes_t chunksize ) const |
|
|
|
|
|
|
|
|
Peaks::ready ( nframes_t s, nframes_t npeaks, nframes_t chunksize ) const |
|
|
{ |
|
|
{ |
|
|
/* if ( _pending ) */ |
|
|
/* if ( _pending ) */ |
|
|
/* return false; */ |
|
|
/* return false; */ |
|
@@ -382,45 +419,65 @@ Peaks::ready ( nframes_t s, int npeaks, nframes_t chunksize ) const |
|
|
return _peakfile.ready( s, npeaks ); |
|
|
return _peakfile.ready( s, npeaks ); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
int |
|
|
|
|
|
Peaks::read_peakfile_peaks ( Peak *peaks, nframes_t s, int npeaks, nframes_t chunksize ) const |
|
|
|
|
|
|
|
|
/** If this returns false, then the peakfile needs to be built */ |
|
|
|
|
|
bool |
|
|
|
|
|
Peaks::peakfile_ready ( void ) const |
|
|
{ |
|
|
{ |
|
|
/* never try to build peaks while recording */ |
|
|
|
|
|
if ( ! transport->recording ) |
|
|
|
|
|
{ |
|
|
|
|
|
if ( ! current() && ! _pending ) |
|
|
|
|
|
{ |
|
|
|
|
|
/* Build peaks asyncronously */ |
|
|
|
|
|
_pending = true; |
|
|
|
|
|
_make_peaks_thread.clone( &Peaks::make_peaks, const_cast<Peaks*>(this) ); |
|
|
|
|
|
_make_peaks_thread.detach(); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
return current() && ! _pending; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
|
Peaks::make_peaks_asynchronously ( void(*callback)(void*), void *userdata ) const |
|
|
|
|
|
{ |
|
|
|
|
|
/* already working on it... */ |
|
|
|
|
|
if( _pending ) |
|
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
|
|
// make_peaks(); |
|
|
|
|
|
|
|
|
|
|
|
_pending = true; |
|
|
|
|
|
|
|
|
|
|
|
peak_thread_data *pd = new peak_thread_data(); |
|
|
|
|
|
|
|
|
|
|
|
pd->callback = callback; |
|
|
|
|
|
pd->userdata = userdata; |
|
|
|
|
|
pd->peaks = const_cast<Peaks*>(this); |
|
|
|
|
|
|
|
|
|
|
|
_make_peaks_thread.clone( &Peaks::make_peaks, pd ); |
|
|
|
|
|
_make_peaks_thread.detach(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
nframes_t |
|
|
|
|
|
Peaks::read_peakfile_peaks ( Peak *peaks, nframes_t s, nframes_t npeaks, nframes_t chunksize ) const |
|
|
|
|
|
{ |
|
|
/* if ( _pending ) */ |
|
|
/* if ( _pending ) */ |
|
|
/* return 0; */ |
|
|
/* return 0; */ |
|
|
|
|
|
|
|
|
Peakfile _peakfile; |
|
|
|
|
|
|
|
|
// Peakfile _peakfile; |
|
|
|
|
|
|
|
|
if ( ! _peakfile.open( _clip->filename(), _clip->channels(), chunksize ) ) |
|
|
|
|
|
|
|
|
if ( ! _peakfile->open( _clip->filename(), _clip->channels(), chunksize ) ) |
|
|
{ |
|
|
{ |
|
|
DMESSAGE( "Failed to open peakfile!" ); |
|
|
DMESSAGE( "Failed to open peakfile!" ); |
|
|
return 0; |
|
|
return 0; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
return _peakfile.read_peaks( peaks, s, npeaks, chunksize ); |
|
|
|
|
|
|
|
|
nframes_t l = _peakfile->read_peaks( peaks, s, npeaks, chunksize ); |
|
|
|
|
|
|
|
|
|
|
|
_peakfile->close(); |
|
|
|
|
|
|
|
|
|
|
|
return l; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
int |
|
|
|
|
|
Peaks::read_source_peaks ( Peak *peaks, int npeaks, nframes_t chunksize ) const |
|
|
|
|
|
|
|
|
nframes_t |
|
|
|
|
|
Peaks::read_source_peaks ( Peak *peaks, nframes_t npeaks, nframes_t chunksize ) const |
|
|
{ |
|
|
{ |
|
|
int channels = _clip->channels(); |
|
|
int channels = _clip->channels(); |
|
|
|
|
|
|
|
|
sample_t *fbuf = new sample_t[ chunksize * channels ]; |
|
|
sample_t *fbuf = new sample_t[ chunksize * channels ]; |
|
|
|
|
|
|
|
|
size_t len; |
|
|
|
|
|
|
|
|
off_t len; |
|
|
|
|
|
|
|
|
int i; |
|
|
|
|
|
|
|
|
nframes_t i; |
|
|
for ( i = 0; i < npeaks; ++i ) |
|
|
for ( i = 0; i < npeaks; ++i ) |
|
|
{ |
|
|
{ |
|
|
/* read in a buffer */ |
|
|
/* read in a buffer */ |
|
@@ -455,19 +512,19 @@ Peaks::read_source_peaks ( Peak *peaks, int npeaks, nframes_t chunksize ) const |
|
|
return i; |
|
|
return i; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
int |
|
|
|
|
|
Peaks::read_source_peaks ( Peak *peaks, nframes_t s, int npeaks, nframes_t chunksize ) const |
|
|
|
|
|
|
|
|
nframes_t |
|
|
|
|
|
Peaks::read_source_peaks ( Peak *peaks, nframes_t s, nframes_t npeaks, nframes_t chunksize ) const |
|
|
{ |
|
|
{ |
|
|
_clip->seek( s ); |
|
|
_clip->seek( s ); |
|
|
|
|
|
|
|
|
int i = read_source_peaks( peaks, npeaks, chunksize ); |
|
|
|
|
|
|
|
|
|
|
|
return i; |
|
|
|
|
|
|
|
|
return read_source_peaks( peaks, npeaks, chunksize ); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
int |
|
|
|
|
|
Peaks::read_peaks ( nframes_t s, int npeaks, nframes_t chunksize ) const |
|
|
|
|
|
|
|
|
nframes_t |
|
|
|
|
|
Peaks::read_peaks ( nframes_t s, nframes_t npeaks, nframes_t chunksize ) const |
|
|
{ |
|
|
{ |
|
|
|
|
|
THREAD_ASSERT( UI ); /* because _peakbuf cache is static */ |
|
|
|
|
|
|
|
|
// printf( "reading peaks %d @ %d\n", npeaks, chunksize ); |
|
|
// printf( "reading peaks %d @ %d\n", npeaks, chunksize ); |
|
|
|
|
|
|
|
|
if ( _peakbuf.size < (nframes_t)( npeaks * _clip->channels() ) ) |
|
|
if ( _peakbuf.size < (nframes_t)( npeaks * _clip->channels() ) ) |
|
@@ -510,7 +567,14 @@ Peaks::current ( void ) const |
|
|
void * |
|
|
void * |
|
|
Peaks::make_peaks ( void *v ) |
|
|
Peaks::make_peaks ( void *v ) |
|
|
{ |
|
|
{ |
|
|
((Peaks*)v)->make_peaks(); |
|
|
|
|
|
|
|
|
peak_thread_data *pd = (peak_thread_data*)v; |
|
|
|
|
|
|
|
|
|
|
|
pd->peaks->make_peaks(); |
|
|
|
|
|
|
|
|
|
|
|
if ( pd->callback ) |
|
|
|
|
|
pd->callback( pd->userdata ); |
|
|
|
|
|
|
|
|
|
|
|
delete pd; |
|
|
|
|
|
|
|
|
return NULL; |
|
|
return NULL; |
|
|
} |
|
|
} |
|
@@ -524,10 +588,6 @@ Peaks::make_peaks ( void ) const |
|
|
|
|
|
|
|
|
_pending = false; |
|
|
_pending = false; |
|
|
|
|
|
|
|
|
Fl::lock(); |
|
|
|
|
|
timeline->redraw(); |
|
|
|
|
|
Fl::unlock(); |
|
|
|
|
|
|
|
|
|
|
|
return b; |
|
|
return b; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@@ -706,16 +766,16 @@ Peaks::Builder::write_block_header ( nframes_t chunksize ) |
|
|
if ( last_block_pos ) |
|
|
if ( last_block_pos ) |
|
|
{ |
|
|
{ |
|
|
/* update previous block */ |
|
|
/* update previous block */ |
|
|
size_t pos = ftell( fp ); |
|
|
|
|
|
|
|
|
off_t pos = ftello( fp ); |
|
|
|
|
|
|
|
|
fseek( fp, last_block_pos - sizeof( peakfile_block_header ), SEEK_SET ); |
|
|
|
|
|
|
|
|
fseeko( fp, last_block_pos - sizeof( peakfile_block_header ), SEEK_SET ); |
|
|
|
|
|
|
|
|
peakfile_block_header bh; |
|
|
peakfile_block_header bh; |
|
|
|
|
|
|
|
|
fread( &bh, sizeof( bh ), 1, fp ); |
|
|
fread( &bh, sizeof( bh ), 1, fp ); |
|
|
|
|
|
|
|
|
fseek( fp, last_block_pos - sizeof( peakfile_block_header ), SEEK_SET ); |
|
|
|
|
|
// fseek( fp, 0 - sizeof( bh ), SEEK_CUR ); |
|
|
|
|
|
|
|
|
fseeko( fp, last_block_pos - sizeof( peakfile_block_header ), SEEK_SET ); |
|
|
|
|
|
// fseeko( fp, 0 - sizeof( bh ), SEEK_CUR ); |
|
|
|
|
|
|
|
|
// DMESSAGE( "old block header: chunksize=%lu, skip=%lu", (unsigned long) bh.chunksize, (unsigned long) bh.skip ); |
|
|
// DMESSAGE( "old block header: chunksize=%lu, skip=%lu", (unsigned long) bh.chunksize, (unsigned long) bh.skip ); |
|
|
|
|
|
|
|
@@ -727,7 +787,7 @@ Peaks::Builder::write_block_header ( nframes_t chunksize ) |
|
|
|
|
|
|
|
|
fwrite( &bh, sizeof( bh ), 1, fp ); |
|
|
fwrite( &bh, sizeof( bh ), 1, fp ); |
|
|
|
|
|
|
|
|
fseek( fp, pos, SEEK_SET ); |
|
|
|
|
|
|
|
|
fseeko( fp, pos, SEEK_SET ); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
peakfile_block_header bh; |
|
|
peakfile_block_header bh; |
|
@@ -737,7 +797,7 @@ Peaks::Builder::write_block_header ( nframes_t chunksize ) |
|
|
|
|
|
|
|
|
fwrite( &bh, sizeof( bh ), 1, fp ); |
|
|
fwrite( &bh, sizeof( bh ), 1, fp ); |
|
|
|
|
|
|
|
|
last_block_pos = ftell( fp ); |
|
|
|
|
|
|
|
|
last_block_pos = ftello( fp ); |
|
|
|
|
|
|
|
|
fflush( fp ); |
|
|
fflush( fp ); |
|
|
} |
|
|
} |
|
@@ -796,10 +856,10 @@ Peaks::Builder::make_peaks_mipmap ( void ) |
|
|
|
|
|
|
|
|
free( pn ); |
|
|
free( pn ); |
|
|
|
|
|
|
|
|
if ( fseek( fp, 0, SEEK_END ) ) |
|
|
|
|
|
|
|
|
if ( fseeko( fp, 0, SEEK_END ) ) |
|
|
FATAL( "error performing seek: %s", strerror( errno ) ); |
|
|
FATAL( "error performing seek: %s", strerror( errno ) ); |
|
|
|
|
|
|
|
|
if ( ftell( fp ) == sizeof( peakfile_block_header ) ) |
|
|
|
|
|
|
|
|
if ( ftello( fp ) == sizeof( peakfile_block_header ) ) |
|
|
{ |
|
|
{ |
|
|
DWARNING( "truncated peakfile. Programming error?" ); |
|
|
DWARNING( "truncated peakfile. Programming error?" ); |
|
|
return false; |
|
|
return false; |
|
@@ -834,7 +894,7 @@ Peaks::Builder::make_peaks_mipmap ( void ) |
|
|
|
|
|
|
|
|
write_block_header( cs ); |
|
|
write_block_header( cs ); |
|
|
|
|
|
|
|
|
size_t len; |
|
|
|
|
|
|
|
|
off_t len; |
|
|
nframes_t s = 0; |
|
|
nframes_t s = 0; |
|
|
do { |
|
|
do { |
|
|
len = pf.read_peaks( buf, s, 1, cs ); |
|
|
len = pf.read_peaks( buf, s, 1, cs ); |
|
@@ -843,7 +903,9 @@ Peaks::Builder::make_peaks_mipmap ( void ) |
|
|
|
|
|
|
|
|
fwrite( buf, sizeof( buf ), len, fp ); |
|
|
fwrite( buf, sizeof( buf ), len, fp ); |
|
|
} |
|
|
} |
|
|
while ( len ); |
|
|
|
|
|
|
|
|
while ( len > 0 && s < _clip->length() ); |
|
|
|
|
|
|
|
|
|
|
|
DMESSAGE( "Last sample was %lu", s ); |
|
|
|
|
|
|
|
|
/* fflush( fp ); */ |
|
|
/* fflush( fp ); */ |
|
|
/* fsync( fileno( fp ) ); */ |
|
|
/* fsync( fileno( fp ) ); */ |
|
@@ -887,7 +949,7 @@ Peaks::Builder::make_peaks ( void ) |
|
|
write_block_header( Peaks::cache_minimum ); |
|
|
write_block_header( Peaks::cache_minimum ); |
|
|
|
|
|
|
|
|
/* build first level from source */ |
|
|
/* build first level from source */ |
|
|
size_t len; |
|
|
|
|
|
|
|
|
off_t len; |
|
|
do { |
|
|
do { |
|
|
len = _peaks->read_source_peaks( buf, 1, Peaks::cache_minimum ); |
|
|
len = _peaks->read_source_peaks( buf, 1, Peaks::cache_minimum ); |
|
|
|
|
|
|
|
|