Tempo ramps - hook up tempo display, a new approach to audio-locked meters
- audio locked meters define an offset which is used for all public TempoMap methods while the internal map remains contiguous. Probably a few unexpected consequences here, but seems to work mostly.
This commit is contained in:
parent
3a2ff0a4a7
commit
ec791c8dd4
@ -1281,7 +1281,7 @@ AudioClock::set_bbt (framepos_t when, bool /*force*/)
|
||||
|
||||
TempoMetric m (_session->tempo_map().metric_at (pos));
|
||||
|
||||
sprintf (buf, "%-5.1f", m.tempo().beats_per_minute());
|
||||
sprintf (buf, "%-5.1f", _session->tempo_map().tempo_at (pos));
|
||||
_left_layout->set_markup (string_compose ("<span size=\"%1\">" TXTSPAN "%3</span> <span foreground=\"green\">%2</span></span>",
|
||||
INFO_FONT_SIZE, buf, _("Tempo")));
|
||||
|
||||
|
@ -3231,9 +3231,9 @@ MeterMarkerDrag::finished (GdkEvent* event, bool movement_occurred)
|
||||
} else {
|
||||
/* we removed it before, so add it back now */
|
||||
if (_marker->meter().position_lock_style() == AudioTime) {
|
||||
map.add_meter (_marker->meter(), _marker->position());
|
||||
map.replace_meter (*_real_section, _marker->meter(), _marker->position());
|
||||
} else {
|
||||
map.add_meter (_marker->meter(), map.beat_at_frame (_marker->position()), when);
|
||||
map.replace_meter (*_real_section, _marker->meter(), when);
|
||||
}
|
||||
|
||||
XMLNode &after = map.get_state();
|
||||
@ -3331,7 +3331,14 @@ TempoMarkerDrag::motion (GdkEvent* event, bool first_move)
|
||||
framepos_t const pf = adjusted_current_frame (event, false);
|
||||
Tempo const tp = _marker->tempo();
|
||||
_marker->set_position (pf);
|
||||
_editor->session()->tempo_map().gui_move_tempo (_real_section, tp, pf);
|
||||
/* just here for a check/laugh
|
||||
if (_real_section->position_lock_style() == MusicTime) {
|
||||
const double baf = _editor->session()->tempo_map().beat_at_frame (pf);
|
||||
_editor->session()->tempo_map().gui_move_tempo_beat (_real_section, tp, baf);
|
||||
} else {
|
||||
*/
|
||||
_editor->session()->tempo_map().gui_move_tempo_frame (_real_section, tp, pf);
|
||||
//}
|
||||
|
||||
show_verbose_cursor_time (pf);
|
||||
}
|
||||
|
@ -401,7 +401,7 @@ class LIBARDOUR_API TempoMap : public PBD::StatefulDestructible
|
||||
XMLNode& get_state (void);
|
||||
int set_state (const XMLNode&, int version);
|
||||
|
||||
void dump (std::ostream&) const;
|
||||
void dump (Metrics& metrics, std::ostream&) const;
|
||||
void clear ();
|
||||
|
||||
TempoMetric metric_at (Timecode::BBT_Time bbt) const;
|
||||
@ -430,13 +430,16 @@ class LIBARDOUR_API TempoMap : public PBD::StatefulDestructible
|
||||
PBD::Signal0<void> MetricPositionChanged;
|
||||
|
||||
private:
|
||||
double bbt_to_beats_locked (Metrics& metrics, Timecode::BBT_Time bbt);
|
||||
double bbt_to_beats_locked (const Metrics& metrics, Timecode::BBT_Time bbt);
|
||||
Timecode::BBT_Time beats_to_bbt_locked (Metrics& metrics, double beats);
|
||||
double beat_at_frame_locked (Metrics& metrics, framecnt_t frame) const;
|
||||
framecnt_t frame_at_beat_locked (Metrics& metrics, double beat) const;
|
||||
framecnt_t frame_at_beat_locked (const Metrics& metrics, double beat) const;
|
||||
double tick_at_frame_locked (const Metrics& metrics, framecnt_t frame) const;
|
||||
double tick_offset_at (const Metrics& metrics, double tick) const;
|
||||
framecnt_t frame_offset_at (const Metrics& metrics, framepos_t frame) const;
|
||||
|
||||
framecnt_t frame_at_tick_locked (const Metrics& metrics, double tick) const;
|
||||
framepos_t frame_time_locked (Metrics& metrics, const Timecode::BBT_Time&);
|
||||
framepos_t frame_time_locked (const Metrics& metrics, const Timecode::BBT_Time&);
|
||||
|
||||
bool check_solved (Metrics& metrics, bool by_frame);
|
||||
bool solve_map (Metrics& metrics, TempoSection* section, const Tempo& bpm, const framepos_t& frame);
|
||||
|
@ -68,7 +68,6 @@ Meter::frames_per_bar (const Tempo& tempo, framecnt_t sr) const
|
||||
return frames_per_grid (tempo, sr) * _divisions_per_bar;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************/
|
||||
|
||||
const string TempoSection::xml_state_node_name = "Tempo";
|
||||
@ -447,7 +446,7 @@ TempoSection::tick_tempo_at_tick (double tick) const
|
||||
double
|
||||
TempoSection::tick_at_time (double time) const
|
||||
{
|
||||
return ((exp (_c_func * time)) - 1) * ticks_per_minute() / _c_func;
|
||||
return ((exp (_c_func * time)) - 1) * (ticks_per_minute() / _c_func);
|
||||
}
|
||||
|
||||
/* time in minutes at tick */
|
||||
@ -746,15 +745,14 @@ void
|
||||
TempoMap::do_insert (MetricSection* section)
|
||||
{
|
||||
bool need_add = true;
|
||||
|
||||
/* we only allow new meters to be inserted on beat 1 of an existing
|
||||
* measure.
|
||||
*/
|
||||
MeterSection* m = 0;
|
||||
if ((m = dynamic_cast<MeterSection*>(section)) != 0) {
|
||||
assert (m->bbt().ticks == 0);
|
||||
//assert (m->bbt().ticks == 0);
|
||||
|
||||
if (m->position_lock_style() == MusicTime && ((m->bbt().beats != 1) || (m->bbt().ticks != 0))) {
|
||||
if ((m->bbt().beats != 1) || (m->bbt().ticks != 0)) {
|
||||
|
||||
pair<double, BBT_Time> corrected = make_pair (m->beat(), m->bbt());
|
||||
corrected.second.beats = 1;
|
||||
@ -777,6 +775,8 @@ TempoMap::do_insert (MetricSection* section)
|
||||
|
||||
TempoSection* const tempo = dynamic_cast<TempoSection*> (*i);
|
||||
TempoSection* const insert_tempo = dynamic_cast<TempoSection*> (section);
|
||||
MeterSection* const meter = dynamic_cast<MeterSection*> (*i);
|
||||
MeterSection* const insert_meter = dynamic_cast<MeterSection*> (section);
|
||||
|
||||
if (tempo && insert_tempo) {
|
||||
|
||||
@ -799,11 +799,10 @@ TempoMap::do_insert (MetricSection* section)
|
||||
break;
|
||||
}
|
||||
|
||||
} else if (!tempo && !insert_tempo) {
|
||||
} else if (meter && insert_meter) {
|
||||
|
||||
/* Meter Sections */
|
||||
MeterSection* const meter = dynamic_cast<MeterSection*> (*i);
|
||||
MeterSection* const insert_meter = dynamic_cast<MeterSection*> (section);
|
||||
|
||||
bool const ipm = insert_meter->position_lock_style() == MusicTime;
|
||||
|
||||
if ((ipm && meter->beat() == insert_meter->beat()) || (!ipm && meter->frame() == insert_meter->frame())) {
|
||||
@ -836,7 +835,6 @@ TempoMap::do_insert (MetricSection* section)
|
||||
if (need_add) {
|
||||
MeterSection* const insert_meter = dynamic_cast<MeterSection*> (section);
|
||||
TempoSection* const insert_tempo = dynamic_cast<TempoSection*> (section);
|
||||
|
||||
Metrics::iterator i;
|
||||
if (insert_meter) {
|
||||
for (i = _metrics.begin(); i != _metrics.end(); ++i) {
|
||||
@ -863,7 +861,7 @@ TempoMap::do_insert (MetricSection* section)
|
||||
}
|
||||
|
||||
_metrics.insert (i, section);
|
||||
//dump (std::cerr);
|
||||
//dump (_metrics, std::cerr);
|
||||
}
|
||||
}
|
||||
|
||||
@ -941,7 +939,7 @@ TempoMap::add_tempo_locked (const Tempo& tempo, double where, bool recompute, AR
|
||||
do_insert (ts);
|
||||
|
||||
if (recompute) {
|
||||
solve_map (_metrics, ts, ts->beats_per_minute(), ts->beat());
|
||||
solve_map (_metrics, ts, Tempo (ts->beats_per_minute(), ts->note_type()), ts->beat());
|
||||
}
|
||||
}
|
||||
|
||||
@ -953,7 +951,7 @@ TempoMap::add_tempo_locked (const Tempo& tempo, framepos_t frame, bool recompute
|
||||
do_insert (ts);
|
||||
|
||||
if (recompute) {
|
||||
solve_map (_metrics, ts, ts->beats_per_minute(), ts->frame());
|
||||
solve_map (_metrics, ts, Tempo (ts->beats_per_minute(), ts->note_type()), ts->frame());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1007,7 +1005,7 @@ TempoMap::add_meter (const Meter& meter, double beat, BBT_Time where)
|
||||
|
||||
#ifndef NDEBUG
|
||||
if (DEBUG_ENABLED(DEBUG::TempoMap)) {
|
||||
dump (std::cerr);
|
||||
dump (_metrics, std::cerr);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -1025,7 +1023,7 @@ TempoMap::add_meter (const Meter& meter, framepos_t frame)
|
||||
|
||||
#ifndef NDEBUG
|
||||
if (DEBUG_ENABLED(DEBUG::TempoMap)) {
|
||||
dump (std::cerr);
|
||||
dump (_metrics, std::cerr);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -1049,11 +1047,11 @@ TempoMap::add_meter_locked (const Meter& meter, double beat, BBT_Time where, boo
|
||||
|
||||
/* new meters *always* start on a beat. */
|
||||
where.ticks = 0;
|
||||
|
||||
do_insert (new MeterSection (beat, where, meter.divisions_per_bar(), meter.note_divisor()));
|
||||
MeterSection* new_meter = new MeterSection (beat, where, meter.divisions_per_bar(), meter.note_divisor());
|
||||
do_insert (new_meter);
|
||||
|
||||
if (recompute) {
|
||||
recompute_map (_metrics);
|
||||
solve_map (_metrics, new_meter, Meter (meter.divisions_per_bar(), meter.note_divisor()), beat);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1062,11 +1060,14 @@ void
|
||||
TempoMap::add_meter_locked (const Meter& meter, framepos_t frame, bool recompute)
|
||||
{
|
||||
|
||||
/* MusicTime meters always start on 1|1|0. */
|
||||
do_insert (new MeterSection (frame, meter.divisions_per_bar(), meter.note_divisor()));
|
||||
MeterSection* new_meter = new MeterSection (frame, meter.divisions_per_bar(), meter.note_divisor());
|
||||
double baf = beat_at_frame_locked (_metrics, frame);
|
||||
pair<double, BBT_Time> beat = make_pair (baf, beats_to_bbt_locked (_metrics, baf));
|
||||
new_meter->set_beat (beat);
|
||||
do_insert (new_meter);
|
||||
|
||||
if (recompute) {
|
||||
recompute_map (_metrics);
|
||||
solve_map (_metrics, new_meter, Meter (new_meter->divisions_per_bar(), new_meter->note_divisor()), frame);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1396,9 +1397,10 @@ TempoMap::recompute_meters (Metrics& metrics)
|
||||
if (meter->position_lock_style() == AudioTime) {
|
||||
/* a frame based meter has to have a 1|1|0 bbt */
|
||||
pair<double, BBT_Time> pr;
|
||||
BBT_Time const where (1, 1, 0);
|
||||
|
||||
pr.first = beat_at_frame_locked (metrics, meter->frame());
|
||||
pr.first = ceil (beat_at_frame_locked (metrics, meter->frame()));
|
||||
BBT_Time const where = beats_to_bbt_locked (metrics, pr.first);
|
||||
|
||||
pr.second = where;
|
||||
meter->set_beat (pr);
|
||||
} else {
|
||||
@ -1496,7 +1498,6 @@ TempoMap::metric_at (BBT_Time bbt) const
|
||||
void
|
||||
TempoMap::bbt_time (framepos_t frame, BBT_Time& bbt)
|
||||
{
|
||||
Glib::Threads::RWLock::ReaderLock lm (lock);
|
||||
|
||||
if (frame < 0) {
|
||||
bbt.bars = 1;
|
||||
@ -1505,24 +1506,30 @@ TempoMap::bbt_time (framepos_t frame, BBT_Time& bbt)
|
||||
warning << string_compose (_("tempo map asked for BBT time at frame %1\n"), frame) << endmsg;
|
||||
return;
|
||||
}
|
||||
bbt = beats_to_bbt_locked (_metrics, beat_at_frame_locked (_metrics, frame));
|
||||
Glib::Threads::RWLock::ReaderLock lm (lock);
|
||||
framepos_t const frame_off = frame_offset_at (_metrics, frame);
|
||||
double const beats = beat_at_frame_locked (_metrics, frame + frame_off);
|
||||
|
||||
bbt = beats_to_bbt_locked (_metrics, beats);
|
||||
}
|
||||
|
||||
double
|
||||
TempoMap::bbt_to_beats (Timecode::BBT_Time bbt)
|
||||
{
|
||||
Glib::Threads::RWLock::ReaderLock lm (lock);
|
||||
return bbt_to_beats_locked (_metrics, bbt);
|
||||
double const ticks = bbt_to_beats_locked (_metrics, bbt) * BBT_Time::ticks_per_beat;
|
||||
double const tick_off = tick_offset_at (_metrics, ticks);
|
||||
|
||||
return (ticks + tick_off) / BBT_Time::ticks_per_beat;
|
||||
}
|
||||
|
||||
double
|
||||
TempoMap::bbt_to_beats_locked (Metrics& metrics, Timecode::BBT_Time bbt)
|
||||
TempoMap::bbt_to_beats_locked (const Metrics& metrics, Timecode::BBT_Time bbt)
|
||||
{
|
||||
/* CALLER HOLDS READ LOCK */
|
||||
|
||||
double accumulated_beats = 0.0;
|
||||
double accumulated_bars = 0.0;
|
||||
double bars_offset = 0.0;
|
||||
MeterSection* prev_ms = 0;
|
||||
|
||||
for (Metrics::const_iterator i = metrics.begin(); i != metrics.end(); ++i) {
|
||||
@ -1536,20 +1543,14 @@ TempoMap::bbt_to_beats_locked (Metrics& metrics, Timecode::BBT_Time bbt)
|
||||
break;
|
||||
}
|
||||
if (prev_ms) {
|
||||
if (m->position_lock_style() == AudioTime) {
|
||||
accumulated_beats = 0.0;
|
||||
accumulated_bars = 0;
|
||||
bars_offset += bars_to_m;
|
||||
} else {
|
||||
accumulated_beats += m->beat() - prev_ms->beat();
|
||||
accumulated_bars += bars_to_m;
|
||||
}
|
||||
accumulated_beats += m->beat() - prev_ms->beat();
|
||||
accumulated_bars += bars_to_m;
|
||||
}
|
||||
prev_ms = m;
|
||||
}
|
||||
}
|
||||
|
||||
double const remaining_bars = ((bbt.bars - bars_offset) - 1) - accumulated_bars;
|
||||
double const remaining_bars = (bbt.bars - 1) - accumulated_bars;
|
||||
double const remaining_bars_in_beats = remaining_bars * prev_ms->divisions_per_bar();
|
||||
double const ret = remaining_bars_in_beats + accumulated_beats + (bbt.beats - 1) + (bbt.ticks / BBT_Time::ticks_per_beat);
|
||||
|
||||
@ -1560,7 +1561,9 @@ Timecode::BBT_Time
|
||||
TempoMap::beats_to_bbt (double beats)
|
||||
{
|
||||
Glib::Threads::RWLock::ReaderLock lm (lock);
|
||||
return beats_to_bbt_locked (_metrics, beats);
|
||||
double const ticks = beats * BBT_Time::ticks_per_beat;
|
||||
double const tick_off = tick_offset_at (_metrics, ticks);
|
||||
return beats_to_bbt_locked (_metrics, (ticks + tick_off) / BBT_Time::ticks_per_beat);
|
||||
}
|
||||
|
||||
Timecode::BBT_Time
|
||||
@ -1577,16 +1580,15 @@ TempoMap::beats_to_bbt_locked (Metrics& metrics, double beats)
|
||||
if ((m = dynamic_cast<MeterSection*> (*i)) != 0) {
|
||||
|
||||
if (prev_ms) {
|
||||
|
||||
if (m->beat() > beats) {
|
||||
/* this is the meter after the one our beat is on*/
|
||||
break;
|
||||
}
|
||||
if(m->position_lock_style() == AudioTime) {
|
||||
accumulated_bars = 0;
|
||||
} else {
|
||||
/* we need a whole number of bars. */
|
||||
accumulated_bars += ((m->beat() - prev_ms->beat()) + 1) / prev_ms->divisions_per_bar();
|
||||
}
|
||||
|
||||
/* we need a whole number of bars. */
|
||||
double const beats_dur = m->beat() - prev_ms->beat();
|
||||
accumulated_bars += (beats_dur + 1) / prev_ms->divisions_per_bar();
|
||||
}
|
||||
|
||||
prev_ms = m;
|
||||
@ -1614,7 +1616,7 @@ TempoMap::beats_to_bbt_locked (Metrics& metrics, double beats)
|
||||
ret.ticks -= BBT_Time::ticks_per_beat;
|
||||
}
|
||||
|
||||
if (ret.beats > prev_ms->divisions_per_bar()) {
|
||||
if (ret.beats >= prev_ms->divisions_per_bar() + 1) {
|
||||
++ret.bars;
|
||||
ret.beats = 1;
|
||||
}
|
||||
@ -1633,9 +1635,11 @@ TempoMap::tick_at_frame_locked (const Metrics& metrics, framecnt_t frame) const
|
||||
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()) {
|
||||
|
||||
if ((prev_ts) && t->frame() > frame) {
|
||||
/*the previous ts is the one containing the frame */
|
||||
return prev_ts->tick_at_frame (frame, _frame_rate);
|
||||
double const ret = prev_ts->tick_at_frame (frame, _frame_rate);
|
||||
return ret;
|
||||
}
|
||||
|
||||
accumulated_ticks = t->tick();
|
||||
@ -1644,12 +1648,56 @@ TempoMap::tick_at_frame_locked (const Metrics& metrics, framecnt_t frame) const
|
||||
}
|
||||
|
||||
/* treated as constant for this ts */
|
||||
double const ticks_in_section = ((frame - prev_ts->frame()) / prev_ts->frames_per_beat (_frame_rate)) * Timecode::BBT_Time::ticks_per_beat;
|
||||
double const ticks_in_section = (((frame - prev_ts->frame()) / prev_ts->frames_per_beat (_frame_rate)) * Timecode::BBT_Time::ticks_per_beat);
|
||||
|
||||
return ticks_in_section + accumulated_ticks;
|
||||
|
||||
}
|
||||
|
||||
double
|
||||
TempoMap::tick_offset_at (const Metrics& metrics, double tick) const
|
||||
{
|
||||
MeterSection* prev_m = 0;
|
||||
double beat_off = 0.0;
|
||||
|
||||
for (Metrics::const_iterator i = metrics.begin(); i != metrics.end(); ++i) {
|
||||
MeterSection* m = 0;
|
||||
if ((m = dynamic_cast<MeterSection*> (*i)) != 0) {
|
||||
if (m->tick() > tick) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (prev_m && m->position_lock_style() == AudioTime) {
|
||||
beat_off += ((m->beat() - prev_m->beat()) / prev_m->note_divisor()) - floor ((m->beat() - prev_m->beat()) / prev_m->note_divisor());
|
||||
}
|
||||
|
||||
prev_m = m;
|
||||
}
|
||||
}
|
||||
|
||||
return beat_off;
|
||||
}
|
||||
|
||||
framecnt_t
|
||||
TempoMap::frame_offset_at (const Metrics& metrics, framepos_t frame) const
|
||||
{
|
||||
framecnt_t frame_off = 0;
|
||||
|
||||
for (Metrics::const_iterator i = metrics.begin(); i != metrics.end(); ++i) {
|
||||
MeterSection* m = 0;
|
||||
if ((m = dynamic_cast<MeterSection*> (*i)) != 0) {
|
||||
if (m->frame() > frame) {
|
||||
break;
|
||||
}
|
||||
if (m->position_lock_style() == AudioTime) {
|
||||
frame_off = frame_at_beat_locked (metrics, m->beat()) - m->frame();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return frame_off;
|
||||
}
|
||||
|
||||
framecnt_t
|
||||
TempoMap::frame_at_tick_locked (const Metrics& metrics, double tick) const
|
||||
{
|
||||
@ -1660,8 +1708,9 @@ TempoMap::frame_at_tick_locked (const Metrics& metrics, double tick) const
|
||||
|
||||
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()) {
|
||||
if (prev_ts && t->tick() > tick) {
|
||||
/* prev_ts is the one affecting us. */
|
||||
return prev_ts->frame_at_tick (tick, _frame_rate);
|
||||
}
|
||||
@ -1674,7 +1723,7 @@ TempoMap::frame_at_tick_locked (const Metrics& metrics, double tick) const
|
||||
double const ticks_in_section = tick - accumulated_ticks;
|
||||
double const dtime = (ticks_in_section / BBT_Time::ticks_per_beat) * prev_ts->frames_per_beat (_frame_rate);
|
||||
|
||||
framecnt_t const ret = ((framecnt_t) floor (dtime)) + prev_ts->frame();
|
||||
framecnt_t const ret = (((framecnt_t) floor (dtime)) + prev_ts->frame());
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -1683,7 +1732,9 @@ double
|
||||
TempoMap::beat_at_frame (framecnt_t frame) const
|
||||
{
|
||||
Glib::Threads::RWLock::ReaderLock lm (lock);
|
||||
return tick_at_frame_locked (_metrics, frame) / BBT_Time::ticks_per_beat;
|
||||
double const tick = tick_at_frame_locked (_metrics, frame);
|
||||
framecnt_t const tick_off = tick_offset_at (_metrics, tick);
|
||||
return (tick + tick_off) / BBT_Time::ticks_per_beat;
|
||||
}
|
||||
|
||||
double
|
||||
@ -1696,11 +1747,13 @@ framecnt_t
|
||||
TempoMap::frame_at_beat (double beat) const
|
||||
{
|
||||
Glib::Threads::RWLock::ReaderLock lm (lock);
|
||||
return frame_at_tick_locked (_metrics, beat * BBT_Time::ticks_per_beat);
|
||||
framecnt_t const frame = frame_at_tick_locked (_metrics, beat * BBT_Time::ticks_per_beat);
|
||||
framecnt_t const frame_off = frame_offset_at (_metrics, frame);
|
||||
return frame - frame_off;
|
||||
}
|
||||
|
||||
framecnt_t
|
||||
TempoMap::frame_at_beat_locked (Metrics& metrics, double beat) const
|
||||
TempoMap::frame_at_beat_locked (const Metrics& metrics, double beat) const
|
||||
{
|
||||
|
||||
return frame_at_tick_locked (metrics, beat * BBT_Time::ticks_per_beat);
|
||||
@ -1719,11 +1772,13 @@ TempoMap::frame_time (const BBT_Time& bbt)
|
||||
}
|
||||
Glib::Threads::RWLock::ReaderLock lm (lock);
|
||||
|
||||
return frame_time_locked (_metrics, bbt);;
|
||||
framecnt_t const frame = frame_at_beat_locked (_metrics, bbt_to_beats_locked (_metrics, bbt));
|
||||
framecnt_t const frame_off = frame_offset_at (_metrics, frame);
|
||||
return frame - frame_off;
|
||||
}
|
||||
|
||||
framepos_t
|
||||
TempoMap::frame_time_locked (Metrics& metrics, const BBT_Time& bbt)
|
||||
TempoMap::frame_time_locked (const Metrics& metrics, const BBT_Time& bbt)
|
||||
{
|
||||
/* HOLD THE READER LOCK */
|
||||
|
||||
@ -1838,27 +1893,7 @@ TempoMap::solve_map (Metrics& imaginary, TempoSection* section, const Tempo& bpm
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
prev_ts = 0;
|
||||
std::cerr << "dumping frame order ------" << std::endl;;
|
||||
for (Metrics::iterator i = imaginary.begin(); i != imaginary.end(); ++i) {
|
||||
TempoSection* t;
|
||||
|
||||
if ((t = dynamic_cast<TempoSection*> (*i)) != 0) {
|
||||
if (prev_ts) {
|
||||
|
||||
std::cerr << "current : " << t->beats_per_minute() << " | " << t->beat() << " | " << t->frame() << std::endl;
|
||||
std::cerr << "previous : " << prev_ts->beats_per_minute() << " | " << prev_ts->beat() << " | " << prev_ts->frame() << std::endl;
|
||||
std::cerr << "calculated : " << prev_ts->tempo_at_beat(t->beat()) << " | " << prev_ts->beat_at_tempo (t->beats_per_minute(), t->frame(), _frame_rate) << " | " << prev_ts->frame_at_tempo(t->beats_per_minute(), t->beat(), _frame_rate) << std::endl;
|
||||
std::cerr << "------" << std::endl;
|
||||
|
||||
}
|
||||
prev_ts = t;
|
||||
}
|
||||
}
|
||||
std::cerr << "end dump ------" << std::endl;
|
||||
*/
|
||||
|
||||
//dump (imaginary, std::cerr);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1940,29 +1975,7 @@ TempoMap::solve_map (Metrics& imaginary, TempoSection* section, const Tempo& bpm
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
prev_ts = 0;
|
||||
std::cerr << "dumping beat order ------" << std::endl;
|
||||
std::cerr << "section : " << section->beats_per_minute() << " | " << section->beat() << " | " << section->frame() << std::endl;
|
||||
std::cerr << "------------------------------------" << std::endl;
|
||||
|
||||
for (Metrics::iterator i = imaginary.begin(); i != imaginary.end(); ++i) {
|
||||
TempoSection* t;
|
||||
if ((t = dynamic_cast<TempoSection*> (*i)) != 0) {
|
||||
if (prev_ts) {
|
||||
|
||||
std::cerr << "current : " << t->beats_per_minute() << " | " << t->beat() << " | " << t->frame() << std::endl;
|
||||
std::cerr << "prev : " << prev_ts->beats_per_minute() << " | " << prev_ts->beat() << " | " << prev_ts->frame() << std::endl;
|
||||
std::cerr << "calculated : " << prev_ts->tempo_at_beat(t->beat()) << " | " << prev_ts->beat_at_tempo (t->beats_per_minute(), t->frame(), _frame_rate) << " | " << prev_ts->frame_at_tempo(t->beats_per_minute(), t->beat(), _frame_rate) << std::endl;
|
||||
std::cerr << " ------" << std::endl;;
|
||||
|
||||
}
|
||||
prev_ts = t;
|
||||
}
|
||||
}
|
||||
std::cerr << "end dump ------";
|
||||
prev_ts = 0;
|
||||
*/
|
||||
//dump (imaginary, std::cerr);
|
||||
|
||||
return false;
|
||||
}
|
||||
@ -1972,7 +1985,7 @@ TempoMap::solve_map (Metrics& imaginary, MeterSection* section, const Meter& mt,
|
||||
{
|
||||
MeterSection* prev_ms = 0;
|
||||
|
||||
pair<double, BBT_Time> b_bbt = make_pair (beat, BBT_Time (1, 1, 0));
|
||||
pair<double, BBT_Time> b_bbt = make_pair (beat, beats_to_bbt_locked (imaginary, beat));
|
||||
section->set_beat (b_bbt);
|
||||
MetricSectionSorter cmp;
|
||||
imaginary.sort (cmp);
|
||||
@ -1981,7 +1994,7 @@ TempoMap::solve_map (Metrics& imaginary, MeterSection* section, const Meter& mt,
|
||||
MeterSection* m;
|
||||
if ((m = dynamic_cast<MeterSection*> (*i)) != 0) {
|
||||
if (prev_ms) {
|
||||
if (m->beat() > beat){
|
||||
if (m == section){
|
||||
section->set_frame (frame_at_beat_locked (imaginary, beat));
|
||||
prev_ms = section;
|
||||
continue;
|
||||
@ -1990,6 +2003,7 @@ TempoMap::solve_map (Metrics& imaginary, MeterSection* section, const Meter& mt,
|
||||
m->set_frame (frame_at_beat_locked (imaginary, m->beat()));
|
||||
} else {
|
||||
pair<double, BBT_Time> b_bbt = make_pair (beat_at_frame_locked (imaginary, m->frame()), BBT_Time (1, 1, 0));
|
||||
b_bbt.second = beats_to_bbt_locked (imaginary, b_bbt.first);
|
||||
m->set_beat (b_bbt);
|
||||
}
|
||||
}
|
||||
@ -1997,9 +2011,6 @@ TempoMap::solve_map (Metrics& imaginary, MeterSection* section, const Meter& mt,
|
||||
}
|
||||
}
|
||||
|
||||
MetricSectionFrameSorter fcmp;
|
||||
//imaginary.sort (fcmp);
|
||||
|
||||
if (section->position_lock_style() == AudioTime) {
|
||||
/* we're setting the beat */
|
||||
section->set_position_lock_style (MusicTime);
|
||||
@ -2008,32 +2019,36 @@ TempoMap::solve_map (Metrics& imaginary, MeterSection* section, const Meter& mt,
|
||||
} else {
|
||||
recompute_meters (imaginary);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
TempoMap::solve_map (Metrics& imaginary, MeterSection* section, const Meter& mt, const framepos_t& frame)
|
||||
{
|
||||
MeterSection* prev_ms = 0;
|
||||
|
||||
section->set_frame (frame);
|
||||
MetricSectionFrameSorter fcmp;
|
||||
imaginary.sort (fcmp);
|
||||
|
||||
for (Metrics::iterator i = imaginary.begin(); i != imaginary.end(); ++i) {
|
||||
MeterSection* m;
|
||||
if ((m = dynamic_cast<MeterSection*> (*i)) != 0) {
|
||||
if (prev_ms) {
|
||||
if (m->frame() > frame){
|
||||
pair<double, BBT_Time> b_bbt = make_pair (beat_at_frame_locked (imaginary, frame), BBT_Time (1, 1, 0));
|
||||
section->set_beat (b_bbt);
|
||||
prev_ms = section;
|
||||
if (m == section){
|
||||
/*
|
||||
here we define the beat for this frame.
|
||||
we're going to set it 'incorrectly' to the next integer and use this 'error'
|
||||
as an offset to the map as far as users of the public methods are concerned.
|
||||
(meters should go on absolute beats to keep us sane)
|
||||
*/
|
||||
double const beat_at_f = ceil (beat_at_frame_locked (imaginary, m->frame()));
|
||||
pair<double, BBT_Time> b_bbt = make_pair (beat_at_f, beats_to_bbt_locked (imaginary, beat_at_f));
|
||||
m->set_beat (b_bbt);
|
||||
prev_ms = m;
|
||||
continue;
|
||||
}
|
||||
if (m->position_lock_style() == MusicTime) {
|
||||
m->set_frame (frame_at_beat_locked (imaginary, m->beat()));
|
||||
} else {
|
||||
pair<double, BBT_Time> b_bbt = make_pair (beat_at_frame_locked (imaginary, m->frame()), BBT_Time (1, 1, 0));
|
||||
double const beat_at_f = ceil (beat_at_frame_locked (imaginary, frame));
|
||||
pair<double, BBT_Time> b_bbt = make_pair (beat_at_f, beats_to_bbt_locked (imaginary, beat_at_f));
|
||||
m->set_beat (b_bbt);
|
||||
}
|
||||
}
|
||||
@ -2041,16 +2056,13 @@ TempoMap::solve_map (Metrics& imaginary, MeterSection* section, const Meter& mt,
|
||||
}
|
||||
}
|
||||
|
||||
MetricSectionSorter cmp;
|
||||
imaginary.sort (cmp);
|
||||
|
||||
if (section->position_lock_style() == MusicTime) {
|
||||
/* we're setting the frame */
|
||||
section->set_position_lock_style (AudioTime);
|
||||
recompute_map (imaginary);
|
||||
recompute_meters (imaginary);
|
||||
section->set_position_lock_style (MusicTime);
|
||||
} else {
|
||||
recompute_map (imaginary);
|
||||
recompute_meters (imaginary);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2199,7 +2211,7 @@ TempoMap::round_to_type (framepos_t frame, RoundMode dir, BBTPointType type)
|
||||
{
|
||||
Glib::Threads::RWLock::ReaderLock lm (lock);
|
||||
|
||||
double const beat_at_framepos = beat_at_frame_locked (_metrics, frame);
|
||||
double const beat_at_framepos = beat_at_frame_locked (_metrics, frame) + tick_offset_at (_metrics, frame);
|
||||
|
||||
BBT_Time bbt (beats_to_bbt_locked (_metrics, beat_at_framepos));
|
||||
|
||||
@ -2237,11 +2249,11 @@ TempoMap::round_to_type (framepos_t frame, RoundMode dir, BBTPointType type)
|
||||
|
||||
case Beat:
|
||||
if (dir < 0) {
|
||||
return frame_at_beat_locked (_metrics, floor (beat_at_framepos));
|
||||
return frame_at_beat_locked (_metrics, floor (beat_at_framepos)) - frame_offset_at (_metrics, frame);
|
||||
} else if (dir > 0) {
|
||||
return frame_at_beat_locked (_metrics, ceil (beat_at_framepos));
|
||||
return frame_at_beat_locked (_metrics, ceil (beat_at_framepos)) - frame_offset_at (_metrics, frame);
|
||||
} else {
|
||||
return frame_at_beat_locked (_metrics, floor (beat_at_framepos + 0.5));
|
||||
return frame_at_beat_locked (_metrics, floor (beat_at_framepos + 0.5)) - frame_offset_at (_metrics, frame);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -2255,17 +2267,19 @@ TempoMap::get_grid (vector<TempoMap::BBTPoint>& points,
|
||||
{
|
||||
Glib::Threads::RWLock::ReaderLock lm (lock);
|
||||
uint32_t const upper_beat = (uint32_t) floor (beat_at_frame_locked (_metrics, upper));
|
||||
uint32_t cnt = (uint32_t) ceil (beat_at_frame_locked (_metrics, lower));
|
||||
double cnt = ceil (beat_at_frame_locked (_metrics, lower));
|
||||
|
||||
while (cnt <= upper_beat) {
|
||||
framecnt_t const pos = frame_at_beat_locked (_metrics, cnt);
|
||||
framecnt_t pos = frame_at_beat_locked (_metrics, cnt);
|
||||
framecnt_t const frame_offset = frame_offset_at (_metrics, pos);
|
||||
pos -= frame_offset;
|
||||
MeterSection const meter = meter_section_at (pos);
|
||||
|
||||
Tempo const tempo = tempo_at (pos);
|
||||
BBT_Time const bbt = beats_to_bbt_locked (_metrics, (double) cnt);
|
||||
|
||||
points.push_back (BBTPoint (meter, tempo, pos, bbt.bars, bbt.beats));
|
||||
++cnt;
|
||||
cnt += 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2334,7 +2348,6 @@ TempoMap::tempo_at (framepos_t frame) const
|
||||
{
|
||||
Glib::Threads::RWLock::ReaderLock lm (lock);
|
||||
|
||||
TempoMetric m (metric_at (frame));
|
||||
TempoSection* prev_ts = 0;
|
||||
|
||||
Metrics::const_iterator i;
|
||||
@ -2345,14 +2358,17 @@ TempoMap::tempo_at (framepos_t frame) const
|
||||
if ((prev_ts) && t->frame() > frame) {
|
||||
/* this is the one past frame */
|
||||
double const ret = prev_ts->tempo_at_frame (frame, _frame_rate);
|
||||
Tempo const ret_tempo (ret, m.tempo().note_type ());
|
||||
Tempo const ret_tempo (ret, prev_ts->note_type());
|
||||
return ret_tempo;
|
||||
}
|
||||
prev_ts = t;
|
||||
}
|
||||
}
|
||||
|
||||
return m.tempo();
|
||||
double const ret = prev_ts->beats_per_minute();
|
||||
Tempo const ret_tempo (ret, prev_ts->note_type ());
|
||||
|
||||
return ret_tempo;
|
||||
}
|
||||
|
||||
const MeterSection&
|
||||
@ -2547,21 +2563,29 @@ TempoMap::set_state (const XMLNode& node, int /*version*/)
|
||||
}
|
||||
|
||||
void
|
||||
TempoMap::dump (std::ostream& o) const
|
||||
TempoMap::dump (Metrics& metrics, std::ostream& o) const
|
||||
{
|
||||
Glib::Threads::RWLock::ReaderLock lm (lock, Glib::Threads::TRY_LOCK);
|
||||
const MeterSection* m;
|
||||
const TempoSection* t;
|
||||
const TempoSection* prev_ts = 0;
|
||||
|
||||
for (Metrics::const_iterator i = _metrics.begin(); i != _metrics.end(); ++i) {
|
||||
for (Metrics::const_iterator i = metrics.begin(); i != metrics.end(); ++i) {
|
||||
|
||||
if ((t = dynamic_cast<const TempoSection*>(*i)) != 0) {
|
||||
o << "Tempo @ " << *i << " (Bar-offset: " << t->bar_offset() << ") " << t->beats_per_minute() << " BPM (pulse = 1/" << t->note_type() << ") at " << t->beat() << " frame= " << t->frame() << " (movable? "
|
||||
<< t->movable() << ')' << endl;
|
||||
if (prev_ts) {
|
||||
o << "current : " << t->beats_per_minute() << " | " << t->beat() << " | " << t->frame() << std::endl;
|
||||
o << "previous : " << prev_ts->beats_per_minute() << " | " << prev_ts->beat() << " | " << prev_ts->frame() << std::endl;
|
||||
o << "calculated : " << prev_ts->tempo_at_beat (t->beat()) << " | " << prev_ts->beat_at_tempo (t->beats_per_minute(), t->frame(), _frame_rate) << " | " << prev_ts->frame_at_tempo (t->beats_per_minute(), t->beat(), _frame_rate) << std::endl;
|
||||
o << "------" << std::endl;
|
||||
}
|
||||
} else if ((m = dynamic_cast<const MeterSection*>(*i)) != 0) {
|
||||
o << "Meter @ " << *i << ' ' << m->divisions_per_bar() << '/' << m->note_divisor() << " at " << m->bbt() << " frame= " << m->frame()
|
||||
<< " (movable? " << m->movable() << ')' << endl;
|
||||
}
|
||||
prev_ts = t;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user