Attempt to draw measure lines with a more efficient incremental algorithm.
This commit is contained in:
parent
0af8d7e124
commit
34400df589
|
@ -712,7 +712,7 @@ Region::draw ( void )
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: only draw as many as are necessary! */
|
/* FIXME: only draw as many as are necessary! */
|
||||||
timeline->draw_measure_lines( rx, Y, rw, H, _box_color );
|
timeline->draw_measure_lines( X, Y, W, H, _box_color );
|
||||||
|
|
||||||
/* fl_color( FL_BLACK ); */
|
/* fl_color( FL_BLACK ); */
|
||||||
/* fl_line( rx, Y, rx, Y + H ); */
|
/* fl_line( rx, Y, rx, Y + H ); */
|
||||||
|
|
|
@ -49,6 +49,7 @@ protected:
|
||||||
|
|
||||||
char *_name;
|
char *_name;
|
||||||
|
|
||||||
|
friend class Timeline; // for draw_measure
|
||||||
std::list <Sequence_Widget *> _widgets;
|
std::list <Sequence_Widget *> _widgets;
|
||||||
Sequence_Widget *event_widget ( void );
|
Sequence_Widget *event_widget ( void );
|
||||||
|
|
||||||
|
|
|
@ -34,18 +34,29 @@ public:
|
||||||
// box( FL_DOWN_BOX );
|
// box( FL_DOWN_BOX );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** return a pointer to the closest tempo point *before* /when/ */
|
||||||
|
Tempo_Point *
|
||||||
|
at ( nframes_t when )
|
||||||
|
{
|
||||||
|
for ( std::list <Sequence_Widget *>::const_reverse_iterator i = _widgets.rbegin();
|
||||||
|
i != _widgets.rend(); i++ )
|
||||||
|
if ( (*i)->offset() < when )
|
||||||
|
return ((Tempo_Point*)(*i));
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
float
|
float
|
||||||
beats_per_minute ( nframes_t when )
|
beats_per_minute ( nframes_t when )
|
||||||
{
|
{
|
||||||
// sort();
|
// sort();
|
||||||
|
|
||||||
for ( std::list <Sequence_Widget *>::const_reverse_iterator i = _widgets.rbegin();
|
Tempo_Point *p = at( when );
|
||||||
i != _widgets.rend(); i++ )
|
|
||||||
{
|
|
||||||
if ( (*i)->offset() < when )
|
|
||||||
return ((Tempo_Point*)(*i))->tempo();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if ( p )
|
||||||
|
return p->tempo();
|
||||||
|
else
|
||||||
return 120.0;
|
return 120.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,6 +64,7 @@ public:
|
||||||
beats_per_minute ( nframes_t when, float bpm )
|
beats_per_minute ( nframes_t when, float bpm )
|
||||||
{
|
{
|
||||||
add( new Tempo_Point( when, bpm ) );
|
add( new Tempo_Point( when, bpm ) );
|
||||||
|
sort();
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -104,18 +104,29 @@ public:
|
||||||
void time ( int bpb, int note ) { _time.beats_per_bar = bpb; _time.beat_type = note; }
|
void time ( int bpb, int note ) { _time.beats_per_bar = bpb; _time.beat_type = note; }
|
||||||
time_sig time ( void ) const { return _time; }
|
time_sig time ( void ) const { return _time; }
|
||||||
|
|
||||||
int
|
/* Time_Point * */
|
||||||
handle ( int m )
|
/* at ( nframes_t when ) */
|
||||||
{
|
/* { */
|
||||||
int r = Sequence_Widget::handle( m );
|
/* for ( std::list <Sequence_Widget *>::const_reverse_iterator i = _widgets.rbegin(); */
|
||||||
|
/* i != _widgets.rend(); i++ ) */
|
||||||
|
/* if ( (*i)->offset() < when ) */
|
||||||
|
/* return ((Time_Point*)(*i)); */
|
||||||
|
|
||||||
if ( m == FL_RELEASE )
|
/* return NULL; */
|
||||||
{
|
/* } */
|
||||||
_track->sort();
|
|
||||||
timeline->redraw();
|
/* int */
|
||||||
}
|
/* handle ( int m ) */
|
||||||
return r;
|
/* { */
|
||||||
}
|
/* int r = Sequence_Widget::handle( m ); */
|
||||||
|
|
||||||
|
/* if ( m == FL_RELEASE ) */
|
||||||
|
/* { */
|
||||||
|
/* _track->sort(); */
|
||||||
|
/* timeline->redraw(); */
|
||||||
|
/* } */
|
||||||
|
/* return r; */
|
||||||
|
/* } */
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -151,6 +151,12 @@ Timeline::Timeline ( int X, int Y, int W, int H, const char* L ) : Fl_Overlay_Wi
|
||||||
o->align( FL_ALIGN_LEFT );
|
o->align( FL_ALIGN_LEFT );
|
||||||
|
|
||||||
tempo_track = o;
|
tempo_track = o;
|
||||||
|
|
||||||
|
o->beats_per_minute( 0, 120 );
|
||||||
|
|
||||||
|
o->beats_per_minute( 48000 * 50, 250 );
|
||||||
|
|
||||||
|
o->beats_per_minute( 48000 * 120, 60 );
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -162,6 +168,8 @@ Timeline::Timeline ( int X, int Y, int W, int H, const char* L ) : Fl_Overlay_Wi
|
||||||
o->align( FL_ALIGN_LEFT );
|
o->align( FL_ALIGN_LEFT );
|
||||||
|
|
||||||
time_track = o;
|
time_track = o;
|
||||||
|
|
||||||
|
o->time( 0, 4, 4 );
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -306,6 +314,12 @@ Timeline::nearest_line ( int ix )
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nframes_t
|
||||||
|
Timeline::x_to_offset ( int x ) const
|
||||||
|
{
|
||||||
|
return x_to_ts( max( 0, x - Track::width() ) ) + xoffset;
|
||||||
|
}
|
||||||
|
|
||||||
/** draw appropriate measure lines inside the given bounding box */
|
/** draw appropriate measure lines inside the given bounding box */
|
||||||
/* FIXME: this function *really* needs to be optimized. Currently it
|
/* FIXME: this function *really* needs to be optimized. Currently it
|
||||||
searched both the time and tempo lists once for every horiontal
|
searched both the time and tempo lists once for every horiontal
|
||||||
|
@ -316,23 +330,83 @@ Timeline::draw_measure ( int X, int Y, int W, int H, Fl_Color color, bool BBT )
|
||||||
if ( ! draw_with_measure_lines )
|
if ( ! draw_with_measure_lines )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
fl_push_clip( X, Y, W, H );
|
// fl_push_clip( X, Y, W, H );
|
||||||
|
|
||||||
// fl_line_style( FL_DASH, 2 );
|
// fl_line_style( FL_DASH, 2 );
|
||||||
fl_line_style( FL_DASH, 0 );
|
fl_line_style( FL_DASH, 0 );
|
||||||
|
|
||||||
const Fl_Color beat = fl_color_average( FL_BLACK, color, 0.65f );
|
const Fl_Color beat = fl_color_average( FL_BLACK, color, 0.65f );
|
||||||
const Fl_Color bar = fl_color_average( FL_RED, color, 0.65f );
|
const Fl_Color bar = fl_color_average( FL_RED, beat, 0.65f );
|
||||||
|
|
||||||
const nframes_t samples_per_minute = sample_rate() * 60;
|
const nframes_t samples_per_minute = sample_rate() * 60;
|
||||||
|
|
||||||
/* we need to back up a bit in order to catch all the numbers */
|
/* we need to back up a bit in order to catch all the numbers */
|
||||||
if ( BBT )
|
|
||||||
|
/* if ( BBT ) */
|
||||||
|
/* { */
|
||||||
|
/* X -= 40; */
|
||||||
|
/* W += 40; */
|
||||||
|
/* } */
|
||||||
|
|
||||||
|
nframes_t when = x_to_offset( X );
|
||||||
|
|
||||||
|
list <Sequence_Widget*>::const_iterator tpi;
|
||||||
|
list <Sequence_Widget*>::const_iterator mpi;
|
||||||
|
|
||||||
|
/* find the first points before our range */
|
||||||
|
|
||||||
|
for ( list <Sequence_Widget *>::const_reverse_iterator i = tempo_track->_widgets.rbegin();
|
||||||
|
i != tempo_track->_widgets.rend(); i++ )
|
||||||
|
if ( (*i)->offset() <= when )
|
||||||
{
|
{
|
||||||
X -= 40;
|
tpi = i.base();
|
||||||
W += 40;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for ( list <Sequence_Widget *>::const_reverse_iterator i = time_track->_widgets.rbegin();
|
||||||
|
i != time_track->_widgets.rend(); i++ )
|
||||||
|
if ( (*i)->offset() <= when )
|
||||||
|
{
|
||||||
|
mpi = i.base();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
--tpi;
|
||||||
|
|
||||||
|
/* start on the next beat */
|
||||||
|
const Tempo_Point *tp = (Tempo_Point*)(*tpi);
|
||||||
|
nframes_t beat_inc = samples_per_minute / tp->tempo();
|
||||||
|
|
||||||
|
nframes_t f = when - ( ( when - tp->offset() ) % beat_inc );
|
||||||
|
|
||||||
|
for ( ; tpi != tempo_track->_widgets.end(); ++tpi )
|
||||||
|
{
|
||||||
|
list <Sequence_Widget*>::const_iterator ntpi = tpi;
|
||||||
|
++ntpi;
|
||||||
|
|
||||||
|
tp = (Tempo_Point*)(*tpi);
|
||||||
|
const Tempo_Point *ntp = (Tempo_Point*)(*ntpi);
|
||||||
|
|
||||||
|
const nframes_t ntpo = ntp ? ntp->offset() : when + x_to_ts( W + 1 );
|
||||||
|
|
||||||
|
beat_inc = samples_per_minute / tp->tempo();
|
||||||
|
|
||||||
|
const int incx = ts_to_x( beat_inc );
|
||||||
|
|
||||||
|
if ( incx < 8 )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for ( ; f < ntpo; f += beat_inc )
|
||||||
|
{
|
||||||
|
const int x = ts_to_x( f - xoffset ) + Track::width();
|
||||||
|
|
||||||
|
fl_color( beat );
|
||||||
|
|
||||||
|
fl_line( x, Y, x, Y + H );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
for ( int x = X; x < X + W; ++x )
|
for ( int x = X; x < X + W; ++x )
|
||||||
{
|
{
|
||||||
// measure = ts_to_x( (double)(sample_rate() * 60) / beats_per_minute( x_to_ts( x - Track::width() ) + xoffset ) );
|
// measure = ts_to_x( (double)(sample_rate() * 60) / beats_per_minute( x_to_ts( x - Track::width() ) + xoffset ) );
|
||||||
|
@ -404,9 +478,11 @@ Timeline::draw_measure ( int X, int Y, int W, int H, Fl_Color color, bool BBT )
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
fl_line_style( FL_SOLID, 0 );
|
fl_line_style( FL_SOLID, 0 );
|
||||||
|
|
||||||
fl_pop_clip();
|
// fl_pop_clip();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -135,6 +135,7 @@ public:
|
||||||
nframes_t sample_rate ( void ) const { return engine->sample_rate(); }
|
nframes_t sample_rate ( void ) const { return engine->sample_rate(); }
|
||||||
int ts_to_x( nframes_t ts ) const { return ts >> _fpp; }
|
int ts_to_x( nframes_t ts ) const { return ts >> _fpp; }
|
||||||
nframes_t x_to_ts ( int x ) const { return x << _fpp; }
|
nframes_t x_to_ts ( int x ) const { return x << _fpp; }
|
||||||
|
nframes_t x_to_offset ( int x ) const;
|
||||||
|
|
||||||
float beats_per_minute ( nframes_t when ) const;
|
float beats_per_minute ( nframes_t when ) const;
|
||||||
int beats_per_bar ( nframes_t when ) const;
|
int beats_per_bar ( nframes_t when ) const;
|
||||||
|
|
Loading…
Reference in New Issue