Browse Source

Make normalization code work at all zoom levels.

tags/non-daw-v1.1.0
Jonathan Moore Liles 17 years ago
parent
commit
3b02169d31
9 changed files with 158 additions and 44 deletions
  1. +71
    -7
      Clip.C
  2. +5
    -1
      Clip.H
  3. +47
    -15
      Peaks.C
  4. +4
    -1
      Peaks.H
  5. +4
    -2
      Region.C
  6. +20
    -6
      Track.H
  7. +2
    -10
      Waveform.C
  8. +3
    -0
      Waveform.H
  9. +2
    -2
      main.C

+ 71
- 7
Clip.C View File

@@ -25,30 +25,94 @@
#include <stdlib.h>
#include <string.h>

Clip::Clip ( const char *filename ) : _peaks( this )

Clip::Clip ( void ) : _peaks( this )
{
_filename = filename;
_filename = NULL;
_length = 0;
}


/* Clip::Clip ( const char *filename ) : _peaks( this ) */
/* { */
/* _filename = filename; */

/* SNDFILE *in; */
/* SF_INFO si; */

/* memset( &si, 0, sizeof( si ) ); */

/* if ( ! ( in = sf_open( filename, SFM_READ, &si ) ) ) */
/* { */
/* printf( "couldn't open file\n" ); */
/* return; */
/* } */

/* if ( si.channels != 1 ) */
/* { */
/* printf( "error: incompatible format\n" ); */
/* return; */
/* } */

/* if ( si.samplerate != timeline.sample_rate ) */
/* { */
/* printf( "error: samplerate mismatch!\n" ); */
/* return; */
/* } */

/* _length = si.frames; */

/* sf_close( in ); */

/* _peaks.open(); */
/* } */


Clip *
Clip::from_file ( const char *filename )
{
SNDFILE *in;
SF_INFO si;

Clip *c = NULL;

memset( &si, 0, sizeof( si ) );

in = sf_open( filename, SFM_READ, &si );
if ( ! ( in = sf_open( filename, SFM_READ, &si ) ) )
{
printf( "couldn't open file\n" );
return NULL;
}

if ( si.channels != 1 )
printf( "error: incompatible format" );
{
printf( "error: incompatible format\n" );
goto invalid;
}

if ( si.samplerate != timeline.sample_rate )
{
printf( "error: samplerate mismatch!\n" );
goto invalid;
}

c = new Clip;

_length = si.frames;
c->_filename = filename;
c->_length = si.frames;

sf_close( in );

_peaks.open();
}
c->_peaks.open();

return c;


invalid:

sf_close( in );
return NULL;
}

bool
Clip::open ( void )


+ 5
- 1
Clip.H View File

@@ -38,7 +38,11 @@ class Clip

public:

Clip ( const char *filename );
Clip ( );

// Clip ( const char *filename );

static Clip *from_file ( const char *filename );

Peaks const * peaks ( void ) { return &_peaks; }
const char *name ( void ) { return _filename; }


+ 47
- 15
Peaks.C View File

@@ -35,6 +35,8 @@

#include "assert.h"

#include <math.h>

Peaks::peakbuffer Peaks::peakbuf;


@@ -58,7 +60,7 @@ Peaks::fill_buffer ( int s, int e ) const


void
Peaks::downsample ( int s, int e, float *mhi, float *mlo ) const
Peaks::downsample ( Peak *peaks, int s, int e, float *mhi, float *mlo ) const
{
*mhi = 0;
*mlo = 0;
@@ -68,8 +70,8 @@ Peaks::downsample ( int s, int e, float *mhi, float *mlo ) const

for ( int j = s; j < e; j++ )
{
const float lo = _peaks->data[ j ].min;
const float hi = _peaks->data[ j ].max;
const float lo = peaks[ j ].min;
const float hi = peaks[ j ].max;

if ( hi > *mhi )
*mhi = hi;
@@ -135,12 +137,9 @@ Peaks::read_peaks ( int s, int e, int npeaks, int chunksize ) const
_clip->close();
}


/* virtual array. Index is a Pixel value, and it returns the
* (resampled) peaks for that pixel based on the current timeline
* zoom. */
/** Return the peak for the range of samples */
Peak &
Peaks::operator[] ( int X ) const
Peaks::peak ( nframes_t start, nframes_t end ) const
{
/* Is there a better way to return this? */
static Peak p;
@@ -149,24 +148,36 @@ Peaks::operator[] ( int X ) const
{
assert( timeline.fpp == peakbuf.buf->chunksize );

int start = timeline.x_to_ts( X ) / peakbuf.buf->chunksize;
int i = start - (peakbuf.offset / peakbuf.buf->chunksize);
start = (start - peakbuf.offset) / peakbuf.buf->chunksize;
end = (end - peakbuf.offset) / peakbuf.buf->chunksize;

if ( end > peakbuf.len )
end = peakbuf.len;

assert( peakbuf.len > i );
// assert( peakbuf.len > start );

p = peakbuf.buf->data[ i ];
downsample( peakbuf.buf->data, 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;
start /= _peaks->chunksize;
end /= _peaks->chunksize;

downsample( start, end, &p.max, &p.min );
downsample( _peaks->data, start, end, &p.max, &p.min );
}

return p;
}

/* virtual array. Index is a Pixel value, and it returns the
* (resampled) peaks for that pixel based on the current timeline
* zoom. */
Peak &
Peaks::operator[] ( int X ) const
{
return peak( timeline.x_to_ts( X ), timeline.x_to_ts( X + 1 ) );
}

static
const char *
peakname ( const char *filename )
@@ -271,3 +282,24 @@ Peaks::make_peaks ( int chunksize )

return true;
}


/** return normalization factor for range of samples from /start/ to
/end/ (uses known peak data if possible */

float
Peaks::normalization_factor( nframes_t start, nframes_t end ) const
{
float s;

fill_buffer( start, end );

Peak p = peak( start, end );

s = fabs( 1.0f / p.max );

if ( s * p.min < -1.0 )
s = 1 / fabs( p.max );

return s;
}

+ 4
- 1
Peaks.H View File

@@ -65,6 +65,8 @@ class Peaks
void read_peaks ( int s, int e, int npeaks, int chunksize ) const;
int clip_read_peaks ( Peak *peaks, int npeaks, int chunksize ) const;

Peak & peak ( nframes_t start, nframes_t end ) const;

public:

Peaks ( Clip *c )
@@ -78,9 +80,10 @@ public:

void fill_buffer ( int s, int e ) const;

void downsample ( int s, int e, float *mhi, float *mlo ) const;
void downsample ( Peak *peaks, int s, int e, float *mhi, float *mlo ) const;
void read ( int X, float *hi, float *lo ) const;
bool open ( void );
float normalization_factor( nframes_t start, nframes_t end ) const;

bool current ( void ) const;
bool make_peaks ( int chunksize );


+ 4
- 2
Region.C View File

@@ -250,8 +250,10 @@ Region::draw ( void )


/* 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() ); */
/* int sx = x() - timeline.ts_to_x( _start ); */
/* fl_line( sx, y(), sx, y() + h() ); */
/* int ex = x() + timeline.ts_to_x( _end - _start ); */
/* fl_line( ex, y(), ex, y() + h() ); */

draw_label();



+ 20
- 6
Track.H View File

@@ -92,16 +92,30 @@ public:
return 1;
case FL_PASTE:
{
const char *file, *text = Fl::event_text();
const char *text = Fl::event_text();

if ( ! strncmp( text, "file://", 7 ) )
file = text + 7;
else
// error?
file = text;
char *file;

if ( ! sscanf( text, "file://%a[^\r\n]\n", &file ) )
{
printf( "invalid drop \"%s\"\n", text );
return 0;
}

printf( "pasted file \"%s\"\n", file );

Clip *c = Clip::from_file( file );

// free( file );

if ( ! c )
{
free( file );
return 0;
}

this->add( new Region( c ) );

return 1;
}
default:


+ 2
- 10
Waveform.C View File

@@ -141,20 +141,12 @@ Waveform::draw ( int X, int Y, int W, int H )
fl_pop_clip();
}


void
Waveform::normalize ( void )
{
float mhi, mlo;

_clip->peaks()->downsample( _start, _end, &mhi, &mlo );

_scale = 1.0f / (float)mhi;

if ( _scale * mlo < -1.0 )
_scale = 1 / fabs( mlo );
printf( "normalize: start=%lu end=%lu\n", _start, _end );

_scale = fabs( _scale );
_scale = _clip->peaks()->normalization_factor( _start, _end );

redraw();
}

+ 3
- 0
Waveform.H View File

@@ -69,6 +69,9 @@ public:

void start ( nframes_t s ) { _start = s; }
void end ( nframes_t e ) { _end = e; }
void scale ( float s ) { _scale = s; }
float scale ( void ) { return _scale; }

// void peaks ( float *p ) { _peaks = p; }
void normalize ( void );



+ 2
- 2
main.C View File

@@ -103,7 +103,7 @@ main ( int argc, char **argv )

// Region *wave = new Region( 0, 0, 5000, 100, "foo" );

Region *wave = new Region( new Clip( "streambass8.wav" ) );
Region *wave = new Region( Clip::from_file( "streambass8.wav" ) );

// wave->resize( 0, 0, 500, 100 );

@@ -141,7 +141,7 @@ main ( int argc, char **argv )
timeline.scroll->end();

Fl_Slider *zoom_slider = new Fl_Slider( 0, 0, 800, 24 );
zoom_slider->type( 1 );
zoom_slider->type( FL_HOR_SLIDER );
zoom_slider->callback( cb_zoom, 0 );
zoom_slider->range( 2, 4096 );
zoom_slider->step( 1 );


Loading…
Cancel
Save