double bpb = meter_dialog.get_bpb ();
bpb = max (1.0, bpb); // XXX is this a reasonable limit?
- double note_type = meter_dialog.get_note_type ();
+ double const note_type = meter_dialog.get_note_type ();
Timecode::BBT_Time when;
meter_dialog.get_bbt_time(when);
framepos_t const frame = _session->tempo_map().frame_at_beat (_session->tempo_map().bbt_to_beats (when));
if (meter_dialog.get_lock_style() == MusicTime) {
_session->tempo_map().replace_meter (*section, Meter (bpb, note_type), when);
} else {
- _session->tempo_map().replace_meter (*section, Meter (bpb, note_type), section->frame());
+ _session->tempo_map().replace_meter (*section, Meter (bpb, note_type), frame);
}
XMLNode &after = _session->tempo_map().get_state();
_session->add_command(new MementoCommand<TempoMap>(_session->tempo_map(), &before, &after));
double bpm = tempo_dialog.get_bpm ();
double nt = tempo_dialog.get_note_type ();
- double beat;
Timecode::BBT_Time when;
tempo_dialog.get_bbt_time(when);
+ double const beat = _session->tempo_map().bbt_to_beats (when);
+
bpm = max (0.01, bpm);
- beat = _session->tempo_map().bbt_to_beats (when);
begin_reversible_command (_("replace tempo mark"));
XMLNode &before = _session->tempo_map().get_state();
MetricSection (double beat)
: _beat (beat), _frame (0), _movable (true), _position_lock_style (PositionLockStyle::MusicTime) {}
MetricSection (framepos_t frame)
- : _beat (0), _frame (frame), _movable (true), _position_lock_style (PositionLockStyle::AudioTime) {}
+ : _beat (0.0), _frame (frame), _movable (true), _position_lock_style (PositionLockStyle::AudioTime) {}
virtual ~MetricSection() {}
MeterSection (double beat, const Timecode::BBT_Time& bbt, double bpb, double note_type)
: MetricSection (beat), Meter (bpb, note_type), _bbt (bbt) {}
MeterSection (framepos_t frame, double bpb, double note_type)
- : MetricSection (frame), Meter (bpb, note_type) {}
+ : MetricSection (frame), Meter (bpb, note_type), _bbt (1, 1, 0) {}
MeterSection (const XMLNode&);
static const std::string xml_state_node_name;
private:
double bbt_to_beats_locked (Timecode::BBT_Time bbt);
Timecode::BBT_Time beats_to_bbt_locked (double beats);
-
+ double beat_at_frame_locked (framecnt_t frame) const;
+ framecnt_t frame_at_beat_locked (double beat) const;
friend class ::BBTTest;
friend class ::FrameposPlusBeatsTest;
friend class ::TempoTest;
TempoMap::TempoMap (framecnt_t fr)
{
_frame_rate = fr;
- BBT_Time start;
-
- start.bars = 1;
- start.beats = 1;
- start.ticks = 0;
+ BBT_Time start (1, 1, 0);
TempoSection *t = new TempoSection (0.0, _default_tempo.beats_per_minute(), _default_tempo.note_type(), TempoSection::Constant);
MeterSection *m = new MeterSection (0.0, start, _default_meter.divisions_per_bar(), _default_meter.note_divisor());
TempoSection* t;
framepos_t ret = 0;
MetricSectionSorter cmp;
-
+ {
Glib::Threads::RWLock::WriterLock lm (lock);
for (Metrics::iterator i = metrics.begin(); i != metrics.end(); ++i) {
ret = prev_ts->frame_at_beat (beat, _frame_rate);
}
-
+ }
return ret;
}
for (i = metrics.begin(); i != metrics.end(); ++i) {
TempoSection* t;
if ((t = dynamic_cast<TempoSection*> (*i)) != 0) {
-
- if (t->frame() >= frame) {
- break;
+ if (t->frame() == frame) {
+ continue;
}
-
- prev_ts = t;
- }
- }
-
- for (i = metrics.begin(); i != metrics.end(); ++i) {
- TempoSection* t;
- if ((t = dynamic_cast<TempoSection*> (*i)) != 0) {
-
- if (t->frame() > frame) {
+ if (frame < t->frame()) {
next_ts = t;
break;
}
+
+ prev_ts = t;
}
}
/* with frame-based editing, it is possible to get in a
situation where if the tempo was placed at the mouse pointer frame,
the following music-based tempo would jump to an earlier frame,
- changing the beat beat of the moved tempo.
- in this case, we have to do some beat-based comparison TODO
+ changing the odering.
+ in this case, we need some kind of tempo map speculator.
*/
} else if (prev_ts->beat() > beats) {
ts.set_beat (prev_ts->beat());
TempoMap::add_meter_locked (const Meter& meter, framepos_t frame, bool recompute)
{
- /* MusicTime meters *always* start on 1|1|0. */
- MeterSection* ms = new MeterSection (frame, meter.divisions_per_bar(), meter.note_divisor());
- BBT_Time bbt;
- pair<double, BBT_Time> pr;
- bbt.bars = 1;
- bbt.beats = 1;
- bbt.ticks = 0;
- /* just a dummy - the actual beat should be applied in recompute_map() as thins is AudioTime */
- pr.first = 0.0;
- pr.second = bbt;
- ms->set_beat (pr);
- do_insert (ms);
+ /* MusicTime meters always start on 1|1|0. */
+ do_insert (new MeterSection (frame, meter.divisions_per_bar(), meter.note_divisor()));
if (recompute) {
recompute_map (true);
where.beats = 1;
where.ticks = 0;
- pr.first = beat_at_frame (meter->frame());
+ pr.first = beat_at_frame_locked (meter->frame());
pr.second = where;
meter->set_beat (pr);
} else {
warning << string_compose (_("tempo map asked for BBT time at frame %1\n"), frame) << endmsg;
return;
}
- bbt = beats_to_bbt_locked (beat_at_frame (frame));
+ bbt = beats_to_bbt_locked (beat_at_frame_locked (frame));
}
double
double accumulated_bars = 0.0;
MeterSection* prev_ms = 0;
- Metrics::const_iterator i;
-
- for (i = metrics.begin(); i != metrics.end(); ++i) {
+ for (Metrics::const_iterator i = metrics.begin(); i != metrics.end(); ++i) {
MeterSection* m;
if ((m = dynamic_cast<MeterSection*> (*i)) != 0) {
double bars_to_m = 0.0;
MeterSection* prev_ms = 0;
uint32_t accumulated_bars = 0;
- Metrics::const_iterator i;
-
- for (i = metrics.begin(); i != metrics.end(); ++i) {
+ for (Metrics::const_iterator i = metrics.begin(); i != metrics.end(); ++i) {
MeterSection* m = 0;
if ((m = dynamic_cast<MeterSection*> (*i)) != 0) {
{
/* HOLD (at least) THE READER LOCK */
- Metrics::const_iterator i;
TempoSection* prev_ts = 0;
double accumulated_ticks = 0.0;
- for (i = metrics.begin(); i != metrics.end(); ++i) {
+ for (Metrics::const_iterator i = metrics.begin(); i != metrics.end(); ++i) {
TempoSection* t;
-
if ((t = dynamic_cast<TempoSection*> (*i)) != 0) {
-
if ((prev_ts) && frame < t->frame()) {
/*the previous ts is the one containing the frame */
return prev_ts->tick_at_frame (frame, _frame_rate);
}
- if (prev_ts && t->frame() > prev_ts->frame()) {
- accumulated_ticks = t->tick();
- }
-
+ accumulated_ticks = t->tick();
prev_ts = t;
}
}
{
/* HOLD THE READER LOCK */
- double accumulated_ticks = 0.0;
const TempoSection* prev_ts = 0;
+ double accumulated_ticks = 0.0;
- Metrics::const_iterator i;
-
- for (i = metrics.begin(); i != metrics.end(); ++i) {
+ for (Metrics::const_iterator i = metrics.begin(); i != metrics.end(); ++i) {
TempoSection* t;
if ((t = dynamic_cast<TempoSection*> (*i)) != 0) {
if (prev_ts && tick < t->tick()) {
TempoMap::beat_at_frame (framecnt_t frame) const
{
Glib::Threads::RWLock::ReaderLock lm (lock);
+ return tick_at_frame (frame) / BBT_Time::ticks_per_beat;
+}
+double
+TempoMap::beat_at_frame_locked (framecnt_t frame) const
+{
return tick_at_frame (frame) / BBT_Time::ticks_per_beat;
}
TempoMap::frame_at_beat (double beat) const
{
Glib::Threads::RWLock::ReaderLock lm (lock);
+ return frame_at_tick (beat * BBT_Time::ticks_per_beat);
+}
+
+framecnt_t
+TempoMap::frame_at_beat_locked (double beat) const
+{
return frame_at_tick (beat * BBT_Time::ticks_per_beat);
}
framecnt_t
TempoMap::bbt_duration_at (framepos_t pos, const BBT_Time& bbt, int dir)
{
-
Glib::Threads::RWLock::ReaderLock lm (lock);
Metrics::const_iterator i;
return time_at_bbt - pos;
}
-
double const ticks = bbt.ticks + (bbt.beats * BBT_Time::ticks_per_beat);
+
return (framecnt_t) floor ((ticks / BBT_Time::ticks_per_beat) * first->frames_per_beat(_frame_rate));
}
{
Glib::Threads::RWLock::ReaderLock lm (lock);
- double const beat_at_framepos = beat_at_frame (frame);
+ double const beat_at_framepos = beat_at_frame_locked (frame);
BBT_Time bbt (beats_to_bbt_locked (beat_at_framepos));
framepos_t lower, framepos_t upper)
{
Glib::Threads::RWLock::ReaderLock lm (lock);
- uint32_t const upper_beat = (uint32_t) floor (beat_at_frame (upper));
- uint32_t cnt = (uint32_t) ceil (beat_at_frame (lower));
+ uint32_t const upper_beat = (uint32_t) floor (beat_at_frame_locked (upper));
+ uint32_t cnt = (uint32_t) ceil (beat_at_frame_locked (lower));
while (cnt <= upper_beat) {
framecnt_t const pos = frame_at_beat (cnt);
}
return m.tempo();
-
}
const MeterSection&
TempoMap::meter_section_at (framepos_t frame) const
{
Glib::Threads::RWLock::ReaderLock lm (lock);
+
Metrics::const_iterator i;
MeterSection* prev = 0;
// cerr << bbt << endl;
if ((t = dynamic_cast<TempoSection*>(*i)) != 0) {
- t->set_beat (beat_at_frame (m->frame()));
+ t->set_beat (beat_at_frame_locked (m->frame()));
tempo = t;
// cerr << "NEW TEMPO, frame = " << (*i)->frame() << " beat = " << (*i)->beat() <<endl;
} else if ((m = dynamic_cast<MeterSection*>(*i)) != 0) {
bbt.beats = 1;
}
}
- pair<double, BBT_Time> start = make_pair (beat_at_frame (m->frame()), bbt);
+ pair<double, BBT_Time> start = make_pair (beat_at_frame_locked (m->frame()), bbt);
m->set_beat (start);
meter = m;
// cerr << "NEW METER, frame = " << (*i)->frame() << " beat = " << (*i)->beat() <<endl;