Browse Source

Fix runaway processing in peakfile generation.

tags/non-daw-v1.2.0
Jonathan Moore Liles 13 years ago
parent
commit
e5875fa072
6 changed files with 246 additions and 152 deletions
  1. +1
    -1
      timeline/makefile.inc
  2. +48
    -28
      timeline/src/Audio_Region.C
  3. +2
    -0
      timeline/src/Audio_Region.H
  4. +177
    -115
      timeline/src/Engine/Peaks.C
  5. +17
    -8
      timeline/src/Engine/Peaks.H
  6. +1
    -0
      timeline/src/Transport.C

+ 1
- 1
timeline/makefile.inc View File

@@ -14,7 +14,7 @@ OBJS:=$(SRCS:.C=.o)


LIBS += $(FLTK_LDFLAGS) $(JACK_LIBS) $(SNDFILE_LIBS) $(LIBLO_LIBS) $(SIGCPP_LIBS) $(XPM_LIBS) LIBS += $(FLTK_LDFLAGS) $(JACK_LIBS) $(SNDFILE_LIBS) $(LIBLO_LIBS) $(SIGCPP_LIBS) $(XPM_LIBS)


CFLAGS += $(SNDFILE_CFLAGS) $(FLTK_CFLAGS) $(JACK_CFLAGS) $(SIGCPP_CFLAGS) $(XPM_CFLAGS)
CFLAGS += $(SNDFILE_CFLAGS) $(FLTK_CFLAGS) $(JACK_CFLAGS) $(SIGCPP_CFLAGS) $(XPM_CFLAGS) -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64


ifeq ($(USE_UNOPTIMIZED_DRAWING),yes) ifeq ($(USE_UNOPTIMIZED_DRAWING),yes)
CFLAGS+=-DUSE_UNOPTIMIZED_DRAWING CFLAGS+=-DUSE_UNOPTIMIZED_DRAWING


+ 48
- 28
timeline/src/Audio_Region.C View File

@@ -470,6 +470,15 @@ Audio_Region::draw_box( void )
fl_pop_clip(); fl_pop_clip();
} }


void
Audio_Region::peaks_ready_callback ( void *v )
{
Fl::lock();
((Audio_Region*)v)->redraw();
Fl::unlock();
Fl::awake();
}

/** Draw (part of) region. X, Y, W and H are the rectangle we're clipped to. */ /** Draw (part of) region. X, Y, W and H are the rectangle we're clipped to. */
void void
Audio_Region::draw ( void ) Audio_Region::draw ( void )
@@ -540,12 +549,12 @@ Audio_Region::draw ( void )


// DMESSAGE( "Drawing audio region."); // DMESSAGE( "Drawing audio region.");


int channels;
int peaks;
Peak *pbuf = NULL;
do { do {


int channels;
int peaks;
Peak *pbuf;

nframes_t start = _r->offset; nframes_t start = _r->offset;


int loop_peaks_needed = _loop ? timeline->ts_to_x( _loop ) : timeline->ts_to_x( _clip->length() ); int loop_peaks_needed = _loop ? timeline->ts_to_x( _loop ) : timeline->ts_to_x( _clip->length() );
@@ -577,22 +586,7 @@ Audio_Region::draw ( void )


assert( loop_peaks_needed >= 0 ); assert( loop_peaks_needed >= 0 );


if ( _loop && offset < _loop )
{
const int x = timeline->ts_to_x( _loop - offset );

/* FIXME: is there no way to draw these symbols direclty? */
fl_color( FL_WHITE );
fl_push_matrix();
fl_translate( X + x + 2, y() + h() - 14 );
fl_scale( - 16, 8 );
draw_full_arrow_symbol( FL_BLACK );
fl_pop_matrix();
}
} }


if ( xo + loop_peaks_needed > total_peaks_needed ) if ( xo + loop_peaks_needed > total_peaks_needed )
@@ -607,15 +601,26 @@ Audio_Region::draw ( void )


if ( start != ostart || end != oend ) if ( start != ostart || end != oend )
{ {
if ( _clip->read_peaks( timeline->fpp(),
start,
end,
&peaks, &pbuf, &channels ) )
if ( _clip->peaks()->peakfile_ready() )
{ {
Waveform::scale( pbuf, peaks * channels, _scale );
if ( _clip->read_peaks( timeline->fpp(),
start,
end,
&peaks, &pbuf, &channels ) )
{
Waveform::scale( pbuf, peaks * channels, _scale );


ostart = start;
oend = end;
ostart = start;
oend = end;
}
}
else
{
if ( ! transport->rolling )
{
/* create a thread to make the peaks */
_clip->peaks()->make_peaks_asynchronously( Audio_Region::peaks_ready_callback, this );
}
} }
} }
else else
@@ -640,7 +645,7 @@ Audio_Region::draw ( void )
loop_peaks_needed, loop_peaks_needed,
ch, ch,
pbuf + i, peaks, channels, pbuf + i, peaks, channels,
c );
c );
} }
} }


@@ -656,6 +661,21 @@ Audio_Region::draw ( void )


timeline->draw_measure_lines( X, Y, W, H ); timeline->draw_measure_lines( X, Y, W, H );


if ( _loop && offset < _loop )
{
const int x = timeline->ts_to_x( _loop - offset );

/* FIXME: is there no way to draw these symbols direclty? */

fl_push_matrix();
fl_translate( X + x + 2, y() + h() - 7 );
fl_scale( - 8, 8 );
draw_full_arrow_symbol( FL_WHITE );
fl_pop_matrix();
}
/* fl_color( FL_BLACK ); */ /* fl_color( FL_BLACK ); */
/* fl_line( rx, Y, rx, Y + H ); */ /* fl_line( rx, Y, rx, Y + H ); */
/* fl_line( rx + rw - 1, Y, rx + rw - 1, Y + H ); */ /* fl_line( rx + rw - 1, Y, rx + rw - 1, Y + H ); */


+ 2
- 0
timeline/src/Audio_Region.H View File

@@ -33,6 +33,8 @@ class Audio_Region : public Sequence_Region
/* not permitted */ /* not permitted */
Audio_Region & operator = ( const Audio_Region &rhs ); Audio_Region & operator = ( const Audio_Region &rhs );


static void peaks_ready_callback ( void *v );

public: public:


static bool inherit_track_color; static bool inherit_track_color;


+ 177
- 115
timeline/src/Engine/Peaks.C View File

@@ -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 );




+ 17
- 8
timeline/src/Engine/Peaks.H View File

@@ -31,6 +31,7 @@




class Audio_File; class Audio_File;
class Peakfile;


class Peaks class Peaks
{ {
@@ -62,6 +63,8 @@ class Peaks
size = len = 0; size = len = 0;
} }
}; };
Peakfile *_peakfile;


class Streamer class Streamer
{ {
@@ -87,7 +90,7 @@ class Peaks
class Builder class Builder
{ {
FILE *fp; FILE *fp;
size_t last_block_pos;
off_t last_block_pos;
const Peaks *_peaks; const Peaks *_peaks;


void write_block_header ( nframes_t chunksize ); void write_block_header ( nframes_t chunksize );
@@ -100,16 +103,17 @@ class Peaks
Builder ( const Peaks *peaks ); Builder ( const Peaks *peaks );
}; };


/* FIXME: Is this ever accessed by multiple threads? */
static peakbuffer _peakbuf; static peakbuffer _peakbuf;


Audio_File *_clip; Audio_File *_clip;


mutable float _fpp; mutable float _fpp;


int read_peaks ( nframes_t s, int npeaks, nframes_t chunksize ) const;
int read_source_peaks ( Peak *peaks, nframes_t s, int npeaks, nframes_t chunksize ) const;
int read_source_peaks ( Peak *peaks, int npeaks, nframes_t chunksize ) const;
int read_peakfile_peaks ( Peak *peaks, nframes_t s, int npeaks, nframes_t chunksize ) const;
nframes_t read_peaks ( nframes_t s, nframes_t npeaks, nframes_t chunksize ) const;
nframes_t read_source_peaks ( Peak *peaks, nframes_t s, nframes_t npeaks, nframes_t chunksize ) const;
nframes_t read_source_peaks ( Peak *peaks, nframes_t npeaks, nframes_t chunksize ) const;
nframes_t read_peakfile_peaks ( Peak *peaks, nframes_t s, nframes_t npeaks, nframes_t chunksize ) const;


Streamer * volatile _peak_writer; /* exists when streaming peaks to disk */ Streamer * volatile _peak_writer; /* exists when streaming peaks to disk */


@@ -117,6 +121,8 @@ class Peaks
Peaks ( const Peaks &rhs ); Peaks ( const Peaks &rhs );
const Peaks &operator= ( const Peaks &rhs ); const Peaks &operator= ( const Peaks &rhs );


bool current ( void ) const;

public: public:


static bool mipmapped_peakfiles; static bool mipmapped_peakfiles;
@@ -133,14 +139,17 @@ public:


int fill_buffer ( float fpp, nframes_t s, nframes_t e ) const; int fill_buffer ( float fpp, nframes_t s, nframes_t e ) const;


bool peakfile_ready ( void ) const;

void read ( int X, float *hi, float *lo ) const; void read ( int X, float *hi, float *lo ) const;
bool ready ( nframes_t s, int npeaks, nframes_t chunksize ) const;
bool ready ( nframes_t s, nframes_t npeaks, nframes_t chunksize ) const;


bool current ( void ) const;
bool make_peaks ( void ) const; bool make_peaks ( void ) const;
bool make_peaks_mipmap ( void ) const;
bool make_peaks_mipmap ( void ) const;
void make_peaks_asynchronously ( void(*callback)(void*), void *userdata ) const;


void prepare_for_writing ( void ); void prepare_for_writing ( void );
void finish_writing ( void ); void finish_writing ( void );
void write ( sample_t *buf, nframes_t nframes ); void write ( sample_t *buf, nframes_t nframes );

}; };

+ 1
- 0
timeline/src/Transport.C View File

@@ -20,6 +20,7 @@
/* Controls the audio transport */ /* Controls the audio transport */


#include "Transport.H" #include "Transport.H"
#include "Timeline.H"


#include "Engine/Engine.H" #include "Engine/Engine.H"




Loading…
Cancel
Save