/** A section of timeline with a certain Tempo or Meter. */
class LIBARDOUR_API MetricSection {
public:
- MetricSection (double pulse, framepos_t frame, PositionLockStyle pls)
- : _pulse (pulse), _frame (frame), _movable (true), _position_lock_style (pls) {}
+ MetricSection (double pulse, framepos_t frame, PositionLockStyle pls, bool is_tempo)
+ : _pulse (pulse), _frame (frame), _movable (true), _position_lock_style (pls), _is_tempo (is_tempo) {}
virtual ~MetricSection() {}
PositionLockStyle position_lock_style () const { return _position_lock_style; }
void set_position_lock_style (PositionLockStyle ps) { _position_lock_style = ps; }
+ const bool is_tempo () const { return _is_tempo; }
private:
double _pulse;
framepos_t _frame;
bool _movable;
PositionLockStyle _position_lock_style;
+ const bool _is_tempo;
};
/** A section of timeline with a certain Meter. */
class LIBARDOUR_API MeterSection : public MetricSection, public Meter {
public:
MeterSection (double pulse, framepos_t frame, double beat, const Timecode::BBT_Time& bbt, double bpb, double note_type, PositionLockStyle pls)
- : MetricSection (pulse, frame, pls), Meter (bpb, note_type), _bbt (bbt), _beat (beat) {}
+ : MetricSection (pulse, frame, pls, false), Meter (bpb, note_type), _bbt (bbt), _beat (beat) {}
MeterSection (const XMLNode&);
};
TempoSection (const double& pulse, const framepos_t& frame, double qpm, double note_type, Type tempo_type, PositionLockStyle pls)
- : MetricSection (pulse, frame, pls), Tempo (qpm, note_type), _type (tempo_type), _c_func (0.0), _active (true), _locked_to_meter (false) {}
+ : MetricSection (pulse, frame, pls, true), Tempo (qpm, note_type), _type (tempo_type), _c_func (0.0), _active (true), _locked_to_meter (false) {}
TempoSection (const XMLNode&);
double tempo_at_pulse (const double& pulse) const;
double pulse_at_tempo (const double& ppm, const framepos_t& frame, const framecnt_t& frame_rate) const;
- double pulse_at_frame (const framepos_t& frame, const framecnt_t& frame_rate) const;
- frameoffset_t frame_at_pulse (const double& pulse, const framecnt_t& frame_rate) const;
+ double pulse_at_frame (const framepos_t& frame, const framepos_t& frame_rate) const;
+ framepos_t frame_at_pulse (const double& pulse, const framecnt_t& frame_rate) const;
double compute_c_func_pulse (const double& end_bpm, const double& end_pulse, const framecnt_t& frame_rate);
double compute_c_func_frame (const double& end_bpm, const framepos_t& end_frame, const framecnt_t& frame_rate) const;
*/
double beat_at_frame (const framecnt_t& frame) const;
- framecnt_t frame_at_beat (const double& beat) const;
+ framepos_t frame_at_beat (const double& beat) const;
Tempo tempo_at_frame (const framepos_t& frame) const;
framepos_t frame_at_tempo (const Tempo& tempo) const;
double beat_at_pulse (const double& pulse) const;
double pulse_at_frame (const framecnt_t& frame) const;
- framecnt_t frame_at_pulse (const double& pulse) const;
+ framepos_t frame_at_pulse (const double& pulse) const;
/* bbt - it's nearly always better to use beats.*/
Timecode::BBT_Time bbt_at_frame (framepos_t when);
private:
double beat_at_frame_locked (const Metrics& metrics, const framecnt_t& frame) const;
- framecnt_t frame_at_beat_locked (const Metrics& metrics, const double& beat) const;
+ framepos_t frame_at_beat_locked (const Metrics& metrics, const double& beat) const;
double pulse_at_beat_locked (const Metrics& metrics, const double& beat) const;
double beat_at_pulse_locked (const Metrics& metrics, const double& pulse) const;
- double pulse_at_frame_locked (const Metrics& metrics, const framecnt_t& frame) const;
- framecnt_t frame_at_pulse_locked (const Metrics& metrics, const double& pulse) const;
+ double pulse_at_frame_locked (const Metrics& metrics, const framepos_t& frame) const;
+ framepos_t frame_at_pulse_locked (const Metrics& metrics, const double& pulse) const;
Tempo tempo_at_frame_locked (const Metrics& metrics, const framepos_t& frame) const;
framepos_t frame_at_tempo_locked (const Metrics& metrics, const Tempo& tempo) const;
const string TempoSection::xml_state_node_name = "Tempo";
TempoSection::TempoSection (const XMLNode& node)
- : MetricSection (0.0, 0, MusicTime)
+ : MetricSection (0.0, 0, MusicTime, true)
, Tempo (TempoMap::default_tempo())
, _c_func (0.0)
, _active (true)
const string MeterSection::xml_state_node_name = "Meter";
MeterSection::MeterSection (const XMLNode& node)
- : MetricSection (0.0, 0, MusicTime), Meter (TempoMap::default_meter())
+ : MetricSection (0.0, 0, MusicTime, false), Meter (TempoMap::default_meter())
{
XMLProperty const * prop;
LocaleGuard lg;
for (Metrics::const_iterator i = metrics.begin(); i != metrics.end(); ++i) {
TempoSection* t;
- if ((t = dynamic_cast<TempoSection*> (*i)) != 0) {
+ if ((*i)->is_tempo()) {
+ t = static_cast<TempoSection*> (*i);
if (!t->active()) {
continue;
}
MeterSection* prev_m = 0;
for (Metrics::const_iterator mi = metrics.begin(); mi != metrics.end(); ++mi) {
- if ((meter = dynamic_cast<MeterSection*> (*mi)) != 0) {
+ if (!(*mi)->is_tempo()) {
+ meter = static_cast<MeterSection*> (*mi);
if (meter->position_lock_style() == AudioTime) {
double pulse = 0.0;
pair<double, BBT_Time> b_bbt;
TempoSection* meter_locked_tempo = 0;
for (Metrics::const_iterator ii = metrics.begin(); ii != metrics.end(); ++ii) {
TempoSection* t;
- if ((t = dynamic_cast<TempoSection*> (*ii)) != 0) {
+ if ((*ii)->is_tempo()) {
+ t = static_cast<TempoSection*> (*ii);
if ((t->locked_to_meter() || !t->movable()) && t->frame() == meter->frame()) {
meter_locked_tempo = t;
break;
for (Metrics::const_iterator i = _metrics.begin(); i != _metrics.end(); ++i) {
MeterSection* mw;
- if ((mw = dynamic_cast<MeterSection*> (*i)) != 0) {
+ if (!(*i)->is_tempo()) {
+ mw = static_cast<MeterSection*> (*i);
BBT_Time section_start (mw->bbt());
if (section_start.bars > bbt.bars || (section_start.bars == bbt.bars && section_start.beats > bbt.beats)) {
MeterSection* next_m = 0;
for (Metrics::const_iterator i = metrics.begin(); i != metrics.end(); ++i) {
- MeterSection* m;
- if ((m = dynamic_cast<MeterSection*> (*i)) != 0) {
- if (prev_m && m->frame() > frame) {
- next_m = m;
+ if (!(*i)->is_tempo()) {
+ if (prev_m && (*i)->frame() > frame) {
+ next_m = static_cast<MeterSection*> (*i);
break;
}
- prev_m = m;
+ prev_m = static_cast<MeterSection*> (*i);
}
}
if (frame < prev_m->frame()) {
return beat;
}
-framecnt_t
+framepos_t
TempoMap::frame_at_beat (const double& beat) const
{
Glib::Threads::RWLock::ReaderLock lm (lock);
}
/* meter & tempo section based */
-framecnt_t
+framepos_t
TempoMap::frame_at_beat_locked (const Metrics& metrics, const double& beat) const
{
MeterSection* prev_m = 0;
TempoSection* prev_t = 0;
+ MeterSection* m;
+
for (Metrics::const_iterator i = metrics.begin(); i != metrics.end(); ++i) {
- MeterSection* m;
- if ((m = dynamic_cast<MeterSection*> (*i)) != 0) {
+ if (!(*i)->is_tempo()) {
+ m = static_cast<MeterSection*> (*i);
if (prev_m && m->beat() > beat) {
break;
}
}
}
+ TempoSection* t;
+
for (Metrics::const_iterator i = metrics.begin(); i != metrics.end(); ++i) {
- TempoSection* t;
- if ((t = dynamic_cast<TempoSection*> (*i)) != 0) {
+ if ((*i)->is_tempo()) {
+ t = static_cast<TempoSection*> (*i);
if (prev_t && ((t->pulse() - prev_m->pulse()) * prev_m->note_divisor()) + prev_m->beat() > beat) {
break;
}
{
TempoSection* prev_t = 0;
+ TempoSection* t;
+
for (Metrics::const_iterator i = _metrics.begin(); i != _metrics.end(); ++i) {
- TempoSection* t;
- if ((t = dynamic_cast<TempoSection*> (*i)) != 0) {
+ if ((*i)->is_tempo()) {
+ t = static_cast<TempoSection*> (*i);
if (!t->active()) {
continue;
}
for (i = _metrics.begin(); i != _metrics.end(); ++i) {
TempoSection* t;
- if ((t = dynamic_cast<TempoSection*> (*i)) != 0) {
+ if ((*i)->is_tempo()) {
+ t = static_cast<TempoSection*> (*i);
if (!t->active()) {
continue;
const double prev_t_ppm = prev_t->beats_per_minute() / prev_t->note_type();
if ((t_ppm > tempo_ppm && prev_t_ppm < tempo_ppm) || (t_ppm < tempo_ppm && prev_t_ppm > tempo_ppm)) {
- const framepos_t ret_frame = prev_t->frame_at_tempo (tempo_ppm, prev_t->pulse(), _frame_rate);
- return ret_frame;
+ return prev_t->frame_at_tempo (tempo_ppm, prev_t->pulse(), _frame_rate);
}
}
prev_t = t;
for (Metrics::const_iterator i = metrics.begin(); i != metrics.end(); ++i) {
MeterSection* m;
- if ((m = dynamic_cast<MeterSection*> (*i)) != 0) {
+ if (!(*i)->is_tempo()) {
+ m = static_cast<MeterSection*> (*i);
if (prev_m && m->pulse() > pulse) {
if (((pulse - prev_m->pulse()) * prev_m->note_divisor()) + prev_m->beat() > m->beat()) {
break;
}
double
-TempoMap::pulse_at_frame (const framecnt_t& frame) const
+TempoMap::pulse_at_frame (const framepos_t& frame) const
{
Glib::Threads::RWLock::ReaderLock lm (lock);
return pulse_at_frame_locked (_metrics, frame);
/* tempo section based */
double
-TempoMap::pulse_at_frame_locked (const Metrics& metrics, const framecnt_t& frame) const
+TempoMap::pulse_at_frame_locked (const Metrics& metrics, const framepos_t& frame) const
{
/* HOLD (at least) THE READER LOCK */
TempoSection* prev_t = 0;
for (Metrics::const_iterator i = metrics.begin(); i != metrics.end(); ++i) {
TempoSection* t;
- if ((t = dynamic_cast<TempoSection*> (*i)) != 0) {
+ if ((*i)->is_tempo()) {
+ t = static_cast<TempoSection*> (*i);
if (!t->active()) {
continue;
}
return pulses_in_section + prev_t->pulse();
}
-framecnt_t
+framepos_t
TempoMap::frame_at_pulse (const double& pulse) const
{
Glib::Threads::RWLock::ReaderLock lm (lock);
}
/* tempo section based */
-framecnt_t
+framepos_t
TempoMap::frame_at_pulse_locked (const Metrics& metrics, const double& pulse) const
{
/* HOLD THE READER LOCK */
for (Metrics::const_iterator i = metrics.begin(); i != metrics.end(); ++i) {
TempoSection* t;
- if ((t = dynamic_cast<TempoSection*> (*i)) != 0) {
+ if ((*i)->is_tempo()) {
+ t = static_cast<TempoSection*> (*i);
if (!t->active()) {
continue;
}
}
}
/* must be treated as constant, irrespective of _type */
- double const pulses_in_section = pulse - prev_t->pulse();
- double const dtime = pulses_in_section * prev_t->frames_per_pulse (_frame_rate);
+ double const dtime = (pulse - prev_t->pulse()) * prev_t->frames_per_pulse (_frame_rate);
- framecnt_t const ret = (framecnt_t) floor (dtime) + prev_t->frame();
-
- return ret;
+ return (framecnt_t) floor (dtime) + prev_t->frame();
}
double
/* because audio-locked meters have 'fake' integral beats,
there is no pulse offset here.
*/
+ MeterSection* m;
+
for (Metrics::const_iterator i = metrics.begin(); i != metrics.end(); ++i) {
- MeterSection* m;
- if ((m = dynamic_cast<MeterSection*> (*i)) != 0) {
+ if (!(*i)->is_tempo()) {
+ m = static_cast<MeterSection*> (*i);
if (prev_m) {
const double bars_to_m = (m->beat() - prev_m->beat()) / prev_m->divisions_per_bar();
if ((bars_to_m + (prev_m->bbt().bars - 1)) > (bbt.bars - 1)) {
MeterSection* prev_m = 0;
const double beats = max (0.0, b);
- for (Metrics::const_iterator i = metrics.begin(); i != metrics.end(); ++i) {
- MeterSection* m = 0;
+ MeterSection* m = 0;
- if ((m = dynamic_cast<MeterSection*> (*i)) != 0) {
+ for (Metrics::const_iterator i = metrics.begin(); i != metrics.end(); ++i) {
+ if (!(*i)->is_tempo()) {
+ m = static_cast<MeterSection*> (*i);
if (prev_m) {
if (m->beat() > beats) {
/* this is the meter after the one our beat is on*/
/* because audio-locked meters have 'fake' integral beats,
there is no pulse offset here.
*/
+ MeterSection* m;
+
for (Metrics::const_iterator i = metrics.begin(); i != metrics.end(); ++i) {
- MeterSection* m;
- if ((m = dynamic_cast<MeterSection*> (*i)) != 0) {
+ if (!(*i)->is_tempo()) {
+ m = static_cast<MeterSection*> (*i);
if (prev_m) {
if (m->bbt().bars > bbt.bars) {
break;
{
MeterSection* prev_m = 0;
+ MeterSection* m = 0;
+
for (Metrics::const_iterator i = metrics.begin(); i != metrics.end(); ++i) {
- MeterSection* m = 0;
- if ((m = dynamic_cast<MeterSection*> (*i)) != 0) {
+ if (!(*i)->is_tempo()) {
+ m = static_cast<MeterSection*> (*i);
if (prev_m) {
double const pulses_to_m = m->pulse() - prev_m->pulse();
MeterSection* prev_m = 0;
MeterSection* next_m = 0;
+ MeterSection* m;
+
for (Metrics::const_iterator i = metrics.begin(); i != metrics.end(); ++i) {
- MeterSection* m;
- if ((m = dynamic_cast<MeterSection*> (*i)) != 0) {
+ if (!(*i)->is_tempo()) {
+ m = static_cast<MeterSection*> (*i);
if (prev_m && m->frame() > frame) {
next_m = m;
break;
for (Metrics::const_iterator i = metrics.begin(); i != metrics.end(); ++i) {
TempoSection* t;
MeterSection* m;
- if ((t = dynamic_cast<TempoSection*> (*i)) != 0) {
+ if ((*i)->is_tempo()) {
+ t = static_cast<TempoSection*> (*i);
if (!t->active()) {
continue;
}
prev_t = t;
}
- if ((m = dynamic_cast<MeterSection*> (*i)) != 0) {
+ if (!(*i)->is_tempo()) {
+ m = static_cast<MeterSection*> (*i);
if (prev_m && m->position_lock_style() == AudioTime) {
- TempoSection* t = const_cast<TempoSection*>(&tempo_section_at_frame_locked (metrics, m->frame() - 1));
+ const TempoSection* t = &tempo_section_at_frame_locked (metrics, m->frame() - 1);
const double nascent_m_pulse = ((m->beat() - prev_m->beat()) / prev_m->note_divisor()) + prev_m->pulse();
const framepos_t nascent_m_frame = t->frame_at_pulse (nascent_m_pulse, _frame_rate);
{
for (Metrics::const_iterator i = metrics.begin(); i != metrics.end(); ++i) {
TempoSection* t;
- if ((t = dynamic_cast<TempoSection*> (*i)) != 0) {
+ if ((*i)->is_tempo()) {
+ t = static_cast<TempoSection*> (*i);
if (!t->movable()) {
t->set_active (true);
continue;
/* can't move a tempo before the first meter */
for (Metrics::iterator i = imaginary.begin(); i != imaginary.end(); ++i) {
MeterSection* m;
- if ((m = dynamic_cast<MeterSection*> (*i)) != 0) {
+ if (!(*i)->is_tempo()) {
+ m = static_cast<MeterSection*> (*i);
if (!m->movable()) {
first_m_frame = m->frame();
break;
for (Metrics::iterator i = imaginary.begin(); i != imaginary.end(); ++i) {
TempoSection* t;
- if ((t = dynamic_cast<TempoSection*> (*i)) != 0) {
+ if ((*i)->is_tempo()) {
+ t = static_cast<TempoSection*> (*i);
if (!t->active()) {
continue;
for (Metrics::iterator i = imaginary.begin(); i != imaginary.end(); ++i) {
TempoSection* t;
- if ((t = dynamic_cast<TempoSection*> (*i)) != 0) {
+ if ((*i)->is_tempo()) {
+ t = static_cast<TempoSection*> (*i);
if (!t->active()) {
continue;
}
for (Metrics::const_iterator ii = imaginary.begin(); ii != imaginary.end(); ++ii) {
TempoSection* t;
- if ((t = dynamic_cast<TempoSection*> (*ii)) != 0) {
+ if ((*ii)->is_tempo()) {
+ t = static_cast<TempoSection*> (*ii);
if ((t->locked_to_meter() || !t->movable()) && t->frame() == section->frame()) {
meter_locked_tempo = t;
break;
for (Metrics::iterator i = imaginary.begin(); i != imaginary.end(); ++i) {
MeterSection* m;
- if ((m = dynamic_cast<MeterSection*> (*i)) != 0) {
+ if (!(*i)->is_tempo()) {
+ m = static_cast<MeterSection*> (*i);
if (m == section){
if (prev_m && section->movable()) {
const double beats = (pulse_at_frame_locked (imaginary, frame) - prev_m->pulse()) * prev_m->note_divisor();
/* disallow setting section to an existing meter's bbt */
for (Metrics::iterator i = imaginary.begin(); i != imaginary.end(); ++i) {
MeterSection* m;
- if ((m = dynamic_cast<MeterSection*> (*i)) != 0) {
+ if (!(*i)->is_tempo()) {
+ m = static_cast<MeterSection*> (*i);
if (m != section && m->bbt().bars == when.bars) {
return false;
}
for (Metrics::iterator i = imaginary.begin(); i != imaginary.end(); ++i) {
MeterSection* m;
- if ((m = dynamic_cast<MeterSection*> (*i)) != 0) {
+ if (!(*i)->is_tempo()) {
+ m = static_cast<MeterSection*> (*i);
pair<double, BBT_Time> b_bbt;
double new_pulse = 0.0;
for (Metrics::const_iterator ii = imaginary.begin(); ii != imaginary.end(); ++ii) {
TempoSection* t;
- if ((t = dynamic_cast<TempoSection*> (*ii)) != 0) {
+ if ((*i)->is_tempo()) {
+ t = static_cast<TempoSection*> (*ii);
if ((t->locked_to_meter() || !t->movable()) && t->frame() == m->frame()) {
meter_locked_tempo = t;
break;
for (Metrics::const_iterator i = metrics.begin(); i != metrics.end(); ++i) {
TempoSection* t;
MeterSection* m;
- if ((t = dynamic_cast<TempoSection*> (*i)) != 0) {
+ if ((*i)->is_tempo()) {
+ t = static_cast<TempoSection*> (*i);
if (t == section) {
ret = new TempoSection (*t);
copy.push_back (ret);
TempoSection* cp = new TempoSection (*t);
copy.push_back (cp);
}
- if ((m = dynamic_cast<MeterSection *> (*i)) != 0) {
+ if (!(*i)->is_tempo()) {
+ m = static_cast<MeterSection *> (*i);
MeterSection* cp = new MeterSection (*m);
copy.push_back (cp);
}
for (Metrics::const_iterator i = metrics.begin(); i != metrics.end(); ++i) {
TempoSection* t;
MeterSection* m;
- if ((t = dynamic_cast<TempoSection*> (*i)) != 0) {
+ if ((*i)->is_tempo()) {
+ t = static_cast<TempoSection*> (*i);
TempoSection* cp = new TempoSection (*t);
copy.push_back (cp);
}
- if ((m = dynamic_cast<MeterSection *> (*i)) != 0) {
+ if (!(*i)->is_tempo()) {
+ m = static_cast<MeterSection *> (*i);
if (m == section) {
ret = new MeterSection (*m);
copy.push_back (ret);
TempoSection* next_t = 0;
for (Metrics::iterator i = future_map.begin(); i != future_map.end(); ++i) {
TempoSection* t = 0;
- if ((t = dynamic_cast<TempoSection*> (*i)) != 0) {
+ if ((*i)->is_tempo()) {
+ t = static_cast<TempoSection*> (*i);
if (t->frame() > ts->frame()) {
next_t = t;
break;
const TempoSection&
TempoMap::tempo_section_at_frame_locked (const Metrics& metrics, framepos_t frame) const
{
- Metrics::const_iterator i;
TempoSection* prev = 0;
- for (i = metrics.begin(); i != metrics.end(); ++i) {
- TempoSection* t;
+ TempoSection* t;
- if ((t = dynamic_cast<TempoSection*> (*i)) != 0) {
+ for (Metrics::const_iterator i = metrics.begin(); i != metrics.end(); ++i) {
+
+ if ((*i)->is_tempo()) {
+ t = static_cast<TempoSection*> (*i);
if (!t->active()) {
continue;
}
TempoSection* prev_t = 0;
const MeterSection* prev_m = &meter_section_at_beat_locked (metrics, beat);
+ TempoSection* t;
+
for (Metrics::const_iterator i = metrics.begin(); i != metrics.end(); ++i) {
- TempoSection* t;
- if ((t = dynamic_cast<TempoSection*> (*i)) != 0) {
+ if ((*i)->is_tempo()) {
+ t = static_cast<TempoSection*> (*i);
if (prev_t && ((t->pulse() - prev_m->pulse()) * prev_m->note_divisor()) + prev_m->beat() > beat) {
break;
}
{
Glib::Threads::RWLock::ReaderLock lm (lock);
- const TempoSection* ts_at = &tempo_section_at_frame_locked (_metrics, frame);
+ const TempoSection* ts_at = 0;
const TempoSection* ts_after = 0;
Metrics::const_iterator i;
+ TempoSection* t;
for (i = _metrics.begin(); i != _metrics.end(); ++i) {
- TempoSection* t;
- if ((t = dynamic_cast<TempoSection*> (*i)) != 0) {
+ if ((*i)->is_tempo()) {
+ t = static_cast<TempoSection*> (*i);
if (!t->active()) {
continue;
}
- if ((*i)->frame() > frame) {
+ if (ts_at && (*i)->frame() > frame) {
ts_after = t;
break;
}
+ ts_at = t;
}
}
Metrics::const_iterator i;
MeterSection* prev = 0;
+ MeterSection* m;
+
for (i = metrics.begin(); i != metrics.end(); ++i) {
- MeterSection* m;
- if ((m = dynamic_cast<MeterSection*> (*i)) != 0) {
+ if (!(*i)->is_tempo()) {
+ m = static_cast<MeterSection*> (*i);
if (prev && (*i)->frame() > frame) {
break;
for (Metrics::const_iterator i = metrics.begin(); i != metrics.end(); ++i) {
MeterSection* m;
- if ((m = dynamic_cast<MeterSection*> (*i)) != 0) {
+ if (!(*i)->is_tempo()) {
+ m = static_cast<MeterSection*> (*i);
if (prev_m && m->beat() > beat) {
break;
}
int cnt = 0;
for (Metrics::const_iterator i = _metrics.begin(); i != _metrics.end(); ++i) {
- if (dynamic_cast<const TempoSection*>(*i) != 0) {
+ if ((*i)->is_tempo()) {
cnt++;
}
}
int cnt = 0;
for (Metrics::const_iterator i = _metrics.begin(); i != _metrics.end(); ++i) {
- if (dynamic_cast<const MeterSection*>(*i) != 0) {
+ if (!(*i)->is_tempo()) {
cnt++;
}
}