Tempo ramps - rename tempo_at() -> tempo_at_frame().. 3 decimals for the audioclock tempo display.

This commit is contained in:
nick_m 2016-05-27 01:25:47 +10:00
parent 250c88c038
commit 8f3bc6f809
12 changed files with 152 additions and 151 deletions

View file

@ -1287,7 +1287,7 @@ AudioClock::set_bbt (framepos_t when, bool /*force*/)
TempoMetric m (_session->tempo_map().metric_at (pos));
sprintf (buf, "%-5.1f", _session->tempo_map().tempo_at (pos).beats_per_minute());
sprintf (buf, "%-5.3f", _session->tempo_map().tempo_at_frame (pos).beats_per_minute());
_left_layout->set_markup (string_compose ("<span size=\"%1\">" TXTSPAN "%3</span> <span foreground=\"green\">%2</span></span>",
INFO_FONT_SIZE, buf, _("Tempo")));

View file

@ -261,7 +261,7 @@ AutomationController::set_freq_beats(double beats)
const ARDOUR::ParameterDescriptor& desc = _controllable->desc();
const ARDOUR::Session& session = _controllable->session();
const framepos_t pos = session.transport_frame();
const ARDOUR::Tempo& tempo = session.tempo_map().tempo_at(pos);
const ARDOUR::Tempo& tempo = session.tempo_map().tempo_at_frame (pos);
const double bpm = tempo.beats_per_minute();
const double bps = bpm / 60.0;
const double freq = bps / beats;

View file

@ -547,7 +547,7 @@ AutomationLine::ContiguousControlPoints::compute_x_bounds (PublicEditor& e)
const framepos_t pos = e.pixel_to_sample(before_x);
const Meter& meter = map.meter_at (pos);
const framecnt_t len = ceil (meter.frames_per_bar (map.tempo_at (pos), e.session()->frame_rate())
const framecnt_t len = ceil (meter.frames_per_bar (map.tempo_at_frame (pos), e.session()->frame_rate())
/ (Timecode::BBT_Time::ticks_per_beat * meter.divisions_per_bar()) );
const double one_tick_in_pixels = e.sample_to_pixel_unrounded (len);
@ -563,7 +563,7 @@ AutomationLine::ContiguousControlPoints::compute_x_bounds (PublicEditor& e)
const framepos_t pos = e.pixel_to_sample(after_x);
const Meter& meter = map.meter_at (pos);
const framecnt_t len = ceil (meter.frames_per_bar (map.tempo_at (pos), e.session()->frame_rate())
const framecnt_t len = ceil (meter.frames_per_bar (map.tempo_at_frame (pos), e.session()->frame_rate())
/ (Timecode::BBT_Time::ticks_per_beat * meter.divisions_per_bar()));
const double one_tick_in_pixels = e.sample_to_pixel_unrounded (len);

View file

@ -3418,7 +3418,7 @@ BBTRulerDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
ostringstream sstr;
_tempo = const_cast<TempoSection*> (&map.tempo_section_at (raw_grab_frame()));
sstr << "^" << fixed << setprecision(3) << map.tempo_at (adjusted_current_frame (event)).beats_per_minute() << "\n";
sstr << "^" << fixed << setprecision(3) << map.tempo_at_frame (adjusted_current_frame (event)).beats_per_minute() << "\n";
sstr << "<" << fixed << setprecision(3) << _tempo->beats_per_minute();
show_verbose_cursor_text (sstr.str());
finished (event, false);
@ -3461,7 +3461,7 @@ BBTRulerDrag::motion (GdkEvent* event, bool first_move)
_editor->session()->tempo_map().gui_dilate_tempo (_tempo, map.frame_at_pulse (_pulse), pf, _pulse);
}
ostringstream sstr;
sstr << "^" << fixed << setprecision(3) << map.tempo_at (pf).beats_per_minute() << "\n";
sstr << "^" << fixed << setprecision(3) << map.tempo_at_frame (pf).beats_per_minute() << "\n";
sstr << "<" << fixed << setprecision(3) << _tempo->beats_per_minute();
show_verbose_cursor_text (sstr.str());
}

View file

@ -316,7 +316,7 @@ Editor::mouse_add_new_tempo_event (framepos_t frame)
if (pulse > 0.0) {
XMLNode &before = map.get_state();
/* add music-locked ramped (?) tempo using the bpm/note type at frame*/
map.add_tempo (map.tempo_at (frame), pulse, 0, TempoSection::Ramp, MusicTime);
map.add_tempo (map.tempo_at_frame (frame), pulse, 0, TempoSection::Ramp, MusicTime);
XMLNode &after = map.get_state();
_session->add_command(new MementoCommand<TempoMap>(map, &before, &after));

View file

@ -116,7 +116,7 @@ StepEditor::prepare_step_edit_region ()
} else {
const Meter& m = _mtv.session()->tempo_map().meter_at (step_edit_insert_position);
const Tempo& t = _mtv.session()->tempo_map().tempo_at (step_edit_insert_position);
const Tempo& t = _mtv.session()->tempo_map().tempo_at_frame (step_edit_insert_position);
double baf = _mtv.session()->tempo_map().beat_at_frame (step_edit_insert_position);
double next_bar_in_beats = baf + m.divisions_per_bar();

View file

@ -46,7 +46,7 @@ TempoDialog::TempoDialog (TempoMap& map, framepos_t frame, const string&)
, tap_tempo_button (_("Tap tempo"))
{
Timecode::BBT_Time when;
Tempo tempo (map.tempo_at (frame));
Tempo tempo (map.tempo_at_frame (frame));
map.bbt_time (frame, when);
init (when, tempo.beats_per_minute(), tempo.note_type(), TempoSection::Constant, true, MusicTime);

View file

@ -327,44 +327,9 @@ class LIBARDOUR_API TempoMap : public PBD::StatefulDestructible
void get_grid (std::vector<BBTPoint>&,
framepos_t start, framepos_t end);
/* TEMPO- AND METER-SENSITIVE FUNCTIONS
bbt_time(), beat_at_frame(), frame_at_beat(), tick_at_frame(),
frame_at_tick(),frame_time() and bbt_duration_at()
are all sensitive to tempo and meter, and will give answers
that align with the grid formed by tempo and meter sections.
They SHOULD NOT be used to determine the position of events
whose location is canonically defined in beats.
*/
void bbt_time (framepos_t when, Timecode::BBT_Time&);
double beat_at_frame (const framecnt_t& frame) const;
framecnt_t frame_at_beat (const double& beat) const;
framepos_t frame_time (const Timecode::BBT_Time&);
framecnt_t bbt_duration_at (framepos_t, const Timecode::BBT_Time&, int dir);
/* TEMPO-SENSITIVE FUNCTIONS
These next 4 functions will all take tempo in account and should be
used to determine position (and in the last case, distance in beats)
when tempo matters but meter does not.
They SHOULD be used to determine the position of events
whose location is canonically defined in beats.
*/
framepos_t framepos_plus_bbt (framepos_t pos, Timecode::BBT_Time b) const;
framepos_t framepos_plus_beats (framepos_t, Evoral::Beats) const;
framepos_t framepos_minus_beats (framepos_t, Evoral::Beats) const;
Evoral::Beats framewalk_to_beats (framepos_t pos, framecnt_t distance) const;
static const Tempo& default_tempo() { return _default_tempo; }
static const Meter& default_meter() { return _default_meter; }
const Tempo tempo_at (const framepos_t& frame) const;
double frames_per_beat_at (const framepos_t&, const framecnt_t& sr) const;
const Meter& meter_at (framepos_t) const;
@ -397,16 +362,6 @@ class LIBARDOUR_API TempoMap : public PBD::StatefulDestructible
void replace_meter (const MeterSection&, const Meter&, const Timecode::BBT_Time& where, const framepos_t& frame
, PositionLockStyle pls);
std::pair<double, framepos_t> predict_tempo_position (TempoSection* section, const Timecode::BBT_Time& bbt);
void gui_move_tempo (TempoSection*, const framepos_t& frame);
void gui_move_meter (MeterSection*, const framepos_t& frame);
bool gui_change_tempo (TempoSection*, const Tempo& bpm);
void gui_dilate_tempo (TempoSection* tempo, const framepos_t& frame, const framepos_t& end_frame, const double& pulse);
bool can_solve_bbt (TempoSection* section, const Timecode::BBT_Time& bbt);
framepos_t round_to_bar (framepos_t frame, RoundMode dir);
framepos_t round_to_beat (framepos_t frame, RoundMode dir);
framepos_t round_to_beat_subdivision (framepos_t fr, int sub_num, RoundMode dir);
@ -441,11 +396,19 @@ class LIBARDOUR_API TempoMap : public PBD::StatefulDestructible
framecnt_t frame_rate () const { return _frame_rate; }
double beat_at_bbt (const Timecode::BBT_Time& bbt);
Timecode::BBT_Time bbt_at_beat (const double& beats);
/* TEMPO- AND METER-SENSITIVE FUNCTIONS
double pulse_at_bbt (const Timecode::BBT_Time& bbt);
Timecode::BBT_Time bbt_at_pulse (const double& pulse);
bbt_time(), beat_at_frame(), frame_at_beat(), frame_time()
and bbt_duration_at()
are all sensitive to tempo and meter, and will give answers
that align with the grid formed by tempo and meter sections.
They SHOULD NOT be used to determine the position of events
whose location is canonically defined in beats.
*/
double beat_at_frame (const framecnt_t& frame) const;
framecnt_t frame_at_beat (const double& beat) const;
double pulse_at_beat (const double& beat) const;
double beat_at_pulse (const double& pulse) const;
@ -453,6 +416,42 @@ class LIBARDOUR_API TempoMap : public PBD::StatefulDestructible
double pulse_at_frame (const framecnt_t& frame) const;
framecnt_t frame_at_pulse (const double& pulse) const;
const Tempo tempo_at_frame (const framepos_t& frame) const;
double beat_at_bbt (const Timecode::BBT_Time& bbt);
Timecode::BBT_Time bbt_at_beat (const double& beats);
double pulse_at_bbt (const Timecode::BBT_Time& bbt);
Timecode::BBT_Time bbt_at_pulse (const double& pulse);
std::pair<double, framepos_t> predict_tempo_position (TempoSection* section, const Timecode::BBT_Time& bbt);
void bbt_time (framepos_t when, Timecode::BBT_Time&);
framepos_t frame_time (const Timecode::BBT_Time&);
framecnt_t bbt_duration_at (framepos_t, const Timecode::BBT_Time&, int dir);
/* TEMPO-SENSITIVE FUNCTIONS
These next 4 functions will all take tempo in account and should be
used to determine position (and in the last case, distance in beats)
when tempo matters but meter does not.
They SHOULD be used to determine the position of events
whose location is canonically defined in beats.
*/
framepos_t framepos_plus_bbt (framepos_t pos, Timecode::BBT_Time b) const;
framepos_t framepos_plus_beats (framepos_t, Evoral::Beats) const;
framepos_t framepos_minus_beats (framepos_t, Evoral::Beats) const;
Evoral::Beats framewalk_to_beats (framepos_t pos, framecnt_t distance) const;
void gui_move_tempo (TempoSection*, const framepos_t& frame);
void gui_move_meter (MeterSection*, const framepos_t& frame);
bool gui_change_tempo (TempoSection*, const Tempo& bpm);
void gui_dilate_tempo (TempoSection* tempo, const framepos_t& frame, const framepos_t& end_frame, const double& pulse);
bool can_solve_bbt (TempoSection* section, const Timecode::BBT_Time& bbt);
PBD::Signal0<void> MetricPositionChanged;
private:
@ -471,12 +470,13 @@ private:
double pulse_at_bbt_locked (const Metrics& metrics, const Timecode::BBT_Time& bbt) const;
Timecode::BBT_Time bbt_at_pulse_locked (const Metrics& metrics, const double& pulse) const;
const Tempo tempo_at_frame_locked (const Metrics& metrics, const framepos_t& frame) const;
framepos_t frame_time_locked (const Metrics& metrics, const Timecode::BBT_Time&) const;
const TempoSection& tempo_section_at_locked (const Metrics& metrics, framepos_t frame) const;
const TempoSection& tempo_section_at_beat_locked (const Metrics& metrics, const double& beat) const;
const TempoSection& tempo_section_at_pulse_locked (const Metrics& metrics, const double& pulse) const;
const Tempo tempo_at_locked (const Metrics& metrics, const framepos_t& frame) const;
const MeterSection& meter_section_at_locked (const Metrics& metrics, framepos_t frame) const;
const MeterSection& meter_section_at_beat_locked (const Metrics& metrics, const double& beat) const;

View file

@ -82,7 +82,7 @@ MIDIClock_Slave::rebind (MidiPort& port)
void
MIDIClock_Slave::calculate_one_ppqn_in_frames_at(framepos_t time)
{
const Tempo& current_tempo = session->tempo_map().tempo_at(time);
const Tempo& current_tempo = session->tempo_map().tempo_at_frame (time);
double const frames_per_beat = session->tempo_map().frames_per_beat_at (time, session->frame_rate());
double quarter_notes_per_beat = 4.0 / current_tempo.note_type();

View file

@ -357,7 +357,7 @@ intptr_t Session::vst_callback (
SHOW_CALLBACK ("audioMasterTempoAt");
// returns tempo (in bpm * 10000) at sample frame location passed in <value>
if (session) {
const Tempo& t (session->tempo_map().tempo_at (value));
const Tempo& t (session->tempo_map().tempo_at_frame (value));
return t.beats_per_minute() * 1000;
} else {
return 0;

View file

@ -1014,7 +1014,7 @@ TempoMap::add_meter_locked (const Meter& meter, double beat, const Timecode::BBT
if (pls == AudioTime) {
/* add meter-locked tempo */
add_tempo_locked (tempo_at_locked (_metrics, frame), pulse, frame, TempoSection::Ramp, AudioTime, true, true);
add_tempo_locked (tempo_at_frame_locked (_metrics, frame), pulse, frame, TempoSection::Ramp, AudioTime, true, true);
}
MeterSection* new_meter = new MeterSection (pulse, frame, beat, where, meter.divisions_per_bar(), meter.note_divisor(), pls);
@ -1385,6 +1385,70 @@ TempoMap::metric_at (BBT_Time bbt) const
return m;
}
double
TempoMap::beat_at_frame (const framecnt_t& frame) const
{
Glib::Threads::RWLock::ReaderLock lm (lock);
return beat_at_frame_locked (_metrics, frame);
}
/* meter / tempo section based */
double
TempoMap::beat_at_frame_locked (const Metrics& metrics, const framecnt_t& frame) const
{
const TempoSection& ts = tempo_section_at_locked (metrics, frame);
MeterSection* prev_m = 0;
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;
break;
}
prev_m = m;
}
}
if (frame < prev_m->frame()) {
return 0.0;
}
const double beat = prev_m->beat() + (ts.pulse_at_frame (frame, _frame_rate) - prev_m->pulse()) * prev_m->note_divisor();
if (next_m && next_m->beat() < beat) {
return next_m->beat();
}
return beat;
}
framecnt_t
TempoMap::frame_at_beat (const double& beat) const
{
Glib::Threads::RWLock::ReaderLock lm (lock);
return frame_at_beat_locked (_metrics, beat);
}
/* meter section based */
framecnt_t
TempoMap::frame_at_beat_locked (const Metrics& metrics, const double& beat) const
{
const TempoSection& prev_t = tempo_section_at_beat_locked (metrics, beat);
MeterSection* prev_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->beat() > beat) {
break;
}
prev_m = m;
}
}
return prev_t.frame_at_pulse (((beat - prev_m->beat()) / prev_m->note_divisor()) + prev_m->pulse(), _frame_rate);
}
double
TempoMap::pulse_at_beat (const double& beat) const
{
@ -1512,70 +1576,43 @@ TempoMap::frame_at_pulse_locked (const Metrics& metrics, const double& pulse) co
return ret;
}
double
TempoMap::beat_at_frame (const framecnt_t& frame) const
const Tempo
TempoMap::tempo_at_frame (const framepos_t& frame) const
{
Glib::Threads::RWLock::ReaderLock lm (lock);
return beat_at_frame_locked (_metrics, frame);
return tempo_at_frame_locked (_metrics, frame);
}
/* meter / tempo section based */
double
TempoMap::beat_at_frame_locked (const Metrics& metrics, const framecnt_t& frame) const
const Tempo
TempoMap::tempo_at_frame_locked (const Metrics& metrics, const framepos_t& frame) const
{
const TempoSection& ts = tempo_section_at_locked (metrics, frame);
MeterSection* prev_m = 0;
MeterSection* next_m = 0;
TempoSection* prev_t = 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;
break;
Metrics::const_iterator i;
for (i = _metrics.begin(); i != _metrics.end(); ++i) {
TempoSection* t;
if ((t = dynamic_cast<TempoSection*> (*i)) != 0) {
if (!t->active()) {
continue;
}
prev_m = m;
}
}
if (frame < prev_m->frame()) {
return 0.0;
}
const double beat = prev_m->beat() + (ts.pulse_at_frame (frame, _frame_rate) - prev_m->pulse()) * prev_m->note_divisor();
if (next_m && next_m->beat() < beat) {
return next_m->beat();
}
return beat;
}
framecnt_t
TempoMap::frame_at_beat (const double& beat) const
{
Glib::Threads::RWLock::ReaderLock lm (lock);
return frame_at_beat_locked (_metrics, beat);
}
/* meter section based */
framecnt_t
TempoMap::frame_at_beat_locked (const Metrics& metrics, const double& beat) const
{
const TempoSection& prev_t = tempo_section_at_beat_locked (metrics, beat);
MeterSection* prev_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->beat() > beat) {
break;
if ((prev_t) && t->frame() > frame) {
/* t is the section past frame */
const double ret_bpm = prev_t->tempo_at_frame (frame, _frame_rate) * prev_t->note_type();
const Tempo ret_tempo (ret_bpm, prev_t->note_type());
return ret_tempo;
}
prev_m = m;
prev_t = t;
}
}
return prev_t.frame_at_pulse (((beat - prev_m->beat()) / prev_m->note_divisor()) + prev_m->pulse(), _frame_rate);
const double ret = prev_t->beats_per_minute();
const Tempo ret_tempo (ret, prev_t->note_type ());
return ret_tempo;
}
double
TempoMap::beat_at_bbt (const Timecode::BBT_Time& bbt)
{
@ -2814,7 +2851,7 @@ TempoMap::get_grid (vector<TempoMap::BBTPoint>& points,
const TempoSection tempo = tempo_section_at_locked (_metrics, pos);
const MeterSection meter = meter_section_at_locked (_metrics, pos);
const BBT_Time bbt = bbt_at_beat_locked (_metrics, cnt);
points.push_back (BBTPoint (meter, tempo_at_locked (_metrics, pos), pos, bbt.bars, bbt.beats, tempo.c_func()));
points.push_back (BBTPoint (meter, tempo_at_frame_locked (_metrics, pos), pos, bbt.bars, bbt.beats, tempo.c_func()));
++cnt;
}
}
@ -2925,42 +2962,6 @@ TempoMap::frames_per_beat_at (const framepos_t& frame, const framecnt_t& sr) con
return ts_at->frames_per_beat (_frame_rate);
}
const Tempo
TempoMap::tempo_at_locked (const Metrics& metrics, const framepos_t& frame) const
{
TempoSection* prev_t = 0;
Metrics::const_iterator i;
for (i = _metrics.begin(); i != _metrics.end(); ++i) {
TempoSection* t;
if ((t = dynamic_cast<TempoSection*> (*i)) != 0) {
if (!t->active()) {
continue;
}
if ((prev_t) && t->frame() > frame) {
/* t is the section past frame */
const double ret_bpm = prev_t->tempo_at_frame (frame, _frame_rate) * prev_t->note_type();
const Tempo ret_tempo (ret_bpm, prev_t->note_type());
return ret_tempo;
}
prev_t = t;
}
}
const double ret = prev_t->beats_per_minute();
const Tempo ret_tempo (ret, prev_t->note_type ());
return ret_tempo;
}
const Tempo
TempoMap::tempo_at (const framepos_t& frame) const
{
Glib::Threads::RWLock::ReaderLock lm (lock);
return tempo_at_locked (_metrics, frame);
}
const MeterSection&
TempoMap::meter_section_at_locked (const Metrics& metrics, framepos_t frame) const
{

View file

@ -307,7 +307,7 @@ MidiClockTicker::tick (const framepos_t& /* transport_frame */, pframes_t nframe
double
MidiClockTicker::one_ppqn_in_frames (framepos_t transport_position)
{
const Tempo& current_tempo = _session->tempo_map().tempo_at (transport_position);
const Tempo& current_tempo = _session->tempo_map().tempo_at_frame (transport_position);
double frames_per_beat = _session->tempo_map().frames_per_beat_at (transport_position, _session->nominal_frame_rate());
double quarter_notes_per_beat = 4.0 / current_tempo.note_type();