From 720f024fa0ad638463e75c030d9649070c2f1089 Mon Sep 17 00:00:00 2001 From: Jonathan Moore Liles Date: Sat, 16 Feb 2008 21:32:31 -0600 Subject: [PATCH] Read peaks directly from source at high zoom levels. --- Clip.H | 6 ++--- Peaks.C | 71 +++++++++++++++++++++++++++++++++++++++++++++++------- Peaks.H | 10 +++++++- Region.C | 7 +++--- Timeline.H | 1 + main.C | 3 +++ 6 files changed, 82 insertions(+), 16 deletions(-) diff --git a/Clip.H b/Clip.H index 7f38bf6..16fa3d2 100644 --- a/Clip.H +++ b/Clip.H @@ -25,16 +25,16 @@ typedef unsigned long nframes_t; class Clip { - char *_filename; + const char *_filename; Peaks _peaks; nframes_t _length; /* length of clip in samples */ public: - Clip ( const char *filename ) + Clip ( const char *filename ) : _peaks( this ) { - _filename = NULL; + _filename = filename; // FIXME: open file diff --git a/Peaks.C b/Peaks.C index d23eb27..a6dfa36 100644 --- a/Peaks.C +++ b/Peaks.C @@ -31,6 +31,7 @@ #include +#include "Clip.H" void Peaks::downsample ( int s, int e, float *mhi, float *mlo ) const @@ -63,6 +64,54 @@ Peaks::read ( int X, float *hi, float *lo ) const downsample( start, end, hi, lo ); } +void +Peaks::read_peaks ( int s, int e, float *mhi, float *mlo ) const +{ + /* this could be faster, but who cares. Don't zoom in so far! */ + + SNDFILE *in; + SF_INFO si; + + memset( &si, 0, sizeof( si ) ); + + in = sf_open( _clip->name(), SFM_READ, &si ); + +/* if ( si.channels != 1 ) */ +/* abort(); */ +/* if ( si.samplerate != timeline.sample_rate ) */ +/* abort(); */ + + sf_seek( in, s, SEEK_SET ); + + int chunksize = e - s; + + float *fbuf = new float[ chunksize ]; + + size_t len; + + /* read in a buffer */ + len = sf_read_float( in, fbuf, chunksize ); + + Peak p; + p.max = -1.0; + p.min = 1.0; + + for ( int i = 0; i < len; ++i ) + { + if ( fbuf[i] > p.max ) + p.max = fbuf[i]; + if ( fbuf[i] < p.min ) + p.min = fbuf[i]; + } + + sf_close( in ); + + delete fbuf; + + *mhi = p.max; + *mlo = p.min; +} + /* virtual array. Index is a Pixel value, and it returns the * (resampled) peaks for that pixel based on the current timeline @@ -75,16 +124,18 @@ Peaks::operator[] ( int X ) const if ( timeline.fpp < _peaks->chunksize ) { - printf( "we need to a smaller chunksize! examine the source!\n" ); + int start = timeline.x_to_ts( X ); + int end = timeline.x_to_ts( X + 1 ); + + read_peaks( start, end, &p.max, &p.min ); } + else + { + int start = timeline.x_to_ts( X ) / _peaks->chunksize; + int end = timeline.x_to_ts( X + 1 ) / _peaks->chunksize; - int start = timeline.x_to_ts( X ) / _peaks->chunksize; - int end = timeline.x_to_ts( X + 1 ) / _peaks->chunksize; - -/* int start = X * timeline.fpp; */ -/* int end = (X + 1) * timeline.fpp; */ - - downsample( start, end, &p.max, &p.min ); + downsample( start, end, &p.max, &p.min ); + } return p; } @@ -179,6 +230,8 @@ Peaks::make_peaks ( const char *filename, int chunksize ) if ( si.channels != 1 ) abort(); + if ( si.samplerate != timeline.sample_rate ) + abort(); FILE *fp = fopen( peakname( filename ), "w" ); @@ -216,7 +269,7 @@ Peaks::make_peaks ( const char *filename, int chunksize ) while ( len == chunksize ); fclose( fp ); - sf_close( in ); + delete fbuf; } diff --git a/Peaks.H b/Peaks.H index b20b4a0..50f6a9a 100644 --- a/Peaks.H +++ b/Peaks.H @@ -26,6 +26,7 @@ struct Peak { float max; }; +class Clip; class Peaks { @@ -35,19 +36,26 @@ class Peaks Peak data[]; }; + + Clip *_clip; + peaks *_peaks; size_t _len; + void read_peaks ( int s, int e, float *mhi, float *mlo ) const; + public: - Peaks ( void ) + Peaks ( Clip *c ) { _peaks = new peaks; _peaks->chunksize = 0; // _peaks->data = NULL; _len = 0; + + _clip = c; } void downsample ( int s, int e, float *mhi, float *mlo ) const; diff --git a/Region.C b/Region.C index 0b70100..d3a1ff8 100644 --- a/Region.C +++ b/Region.C @@ -237,9 +237,10 @@ Region::draw ( void ) // fl_pop_clip(); - fl_color( FL_RED ); - fl_line( x() - _start, y(), x() - _start, y() + h() ); - fl_line( x() + w() - _end, y(), x() + w() - _end, y() + h() ); + +/* fl_color( FL_RED ); */ +/* fl_line( x() - timeline.ts_to_x( _start ), y(), x() - timeline.ts_to_x( _start ), y() + h() ); */ +/* fl_line( x() + w() - _end, y(), x() + w() - _end, y() + h() ); */ draw_label(); diff --git a/Timeline.H b/Timeline.H index bce934b..1e450da 100644 --- a/Timeline.H +++ b/Timeline.H @@ -28,6 +28,7 @@ struct Timeline { float fpp; /* frames per pixel */ + nframes_t sample_rate; int ts_to_x( nframes_t ts ) diff --git a/main.C b/main.C index 8769c78..b9d1391 100644 --- a/main.C +++ b/main.C @@ -67,6 +67,9 @@ main ( int argc, char **argv ) timeline.scroll = new Fl_Scroll( 0, 24, 800, 600 - 24 ); timeline.fpp = 256; + + timeline.sample_rate = 44100; + Fl_Pack *tracks = new Fl_Pack( 0, 0, 5000, 5000 ); tracks->type( Fl_Pack::VERTICAL );