Initial stab at tempo ramps.

Replaces the list of points in TempoMap with TempoSection functions, which
compute tempo-at or tick-at time relative to tempo section start.
TempoMap consults them additively to determine things like bbt_time(),
frame_time() get_grid() etc.
This has a marked effect on scrolling speed along with the code simplification
in the places it has been attempted.

Several things are broken here.
Currently every ramp except the last one is an exponential ramp. this may
be simple to fix :).
Mouse-over midi grid doesn't match mouse click grid. should also be simple.

Many things seem to work, but their accuracy should be in question until
each area has been addressed.
This commit is contained in:
nick_m 2015-12-20 04:41:45 +11:00
parent 94187e66a2
commit 7fc3b0c34c
16 changed files with 904 additions and 1097 deletions

View file

@ -2185,14 +2185,10 @@ Editor::set_snap_to (SnapType st)
case SnapToBeatDiv4:
case SnapToBeatDiv3:
case SnapToBeatDiv2: {
ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_begin;
ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_end;
compute_current_bbt_points (leftmost_frame, leftmost_frame + current_page_samples(),
current_bbt_points_begin, current_bbt_points_end);
compute_bbt_ruler_scale (leftmost_frame, leftmost_frame + current_page_samples(),
current_bbt_points_begin, current_bbt_points_end);
update_tempo_based_rulers (current_bbt_points_begin, current_bbt_points_end);
std::vector<TempoMap::BBTPoint> grid;
compute_current_bbt_points (grid, leftmost_frame, leftmost_frame + current_page_samples());
compute_bbt_ruler_scale (grid, leftmost_frame, leftmost_frame + current_page_samples());
update_tempo_based_rulers (grid);
break;
}
@ -3952,11 +3948,9 @@ Editor::set_show_measures (bool yn)
tempo_lines->show();
}
ARDOUR::TempoMap::BBTPointList::const_iterator begin;
ARDOUR::TempoMap::BBTPointList::const_iterator end;
compute_current_bbt_points (leftmost_frame, leftmost_frame + current_page_samples(), begin, end);
draw_measures (begin, end);
std::vector<TempoMap::BBTPoint> grid;
compute_current_bbt_points (grid, leftmost_frame, leftmost_frame + current_page_samples());
draw_measures (grid);
}
instant_save ();
@ -4582,14 +4576,10 @@ Editor::visual_changer (const VisualChange& vc)
compute_fixed_ruler_scale ();
ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_begin;
ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_end;
compute_current_bbt_points (vc.time_origin, pending_visual_change.time_origin + current_page_samples(),
current_bbt_points_begin, current_bbt_points_end);
compute_bbt_ruler_scale (vc.time_origin, pending_visual_change.time_origin + current_page_samples(),
current_bbt_points_begin, current_bbt_points_end);
update_tempo_based_rulers (current_bbt_points_begin, current_bbt_points_end);
std::vector<TempoMap::BBTPoint> grid;
compute_current_bbt_points (grid, vc.time_origin, pending_visual_change.time_origin + current_page_samples());
compute_bbt_ruler_scale (grid, vc.time_origin, pending_visual_change.time_origin + current_page_samples());
update_tempo_based_rulers (grid);
update_video_timeline();
}

View file

@ -885,8 +885,7 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
void update_just_timecode ();
void compute_fixed_ruler_scale (); //calculates the RulerScale of the fixed rulers
void update_fixed_rulers ();
void update_tempo_based_rulers (ARDOUR::TempoMap::BBTPointList::const_iterator& begin,
ARDOUR::TempoMap::BBTPointList::const_iterator& end);
void update_tempo_based_rulers (std::vector<ARDOUR::TempoMap::BBTPoint>& grid);
void popup_ruler_menu (framepos_t where = 0, ItemType type = RegionItem);
void update_ruler_visibility ();
void set_ruler_visible (RulerType, bool);
@ -949,9 +948,7 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
gint bbt_nmarks;
uint32_t bbt_bar_helper_on;
uint32_t bbt_accent_modulo;
void compute_bbt_ruler_scale (framepos_t lower, framepos_t upper,
ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_begin,
ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_end);
void compute_bbt_ruler_scale (std::vector<ARDOUR::TempoMap::BBTPoint>& grid, framepos_t lower, framepos_t upper);
ArdourCanvas::Ruler* timecode_ruler;
ArdourCanvas::Ruler* bbt_ruler;
@ -1636,8 +1633,7 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
ArdourCanvas::Container* time_line_group;
void hide_measures ();
void draw_measures (ARDOUR::TempoMap::BBTPointList::const_iterator& begin,
ARDOUR::TempoMap::BBTPointList::const_iterator& end);
void draw_measures (std::vector<ARDOUR::TempoMap::BBTPoint>&);
void new_tempo_section ();
@ -1698,9 +1694,7 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
void remove_metric_marks ();
void draw_metric_marks (const ARDOUR::Metrics& metrics);
void compute_current_bbt_points (framepos_t left, framepos_t right,
ARDOUR::TempoMap::BBTPointList::const_iterator& begin,
ARDOUR::TempoMap::BBTPointList::const_iterator& end);
void compute_current_bbt_points (std::vector<ARDOUR::TempoMap::BBTPoint>& grid, framepos_t left, framepos_t right);
void tempo_map_changed (const PBD::PropertyChange&);
void redisplay_tempo (bool immediate_redraw);

View file

@ -3344,14 +3344,14 @@ TempoMarkerDrag::finished (GdkEvent* event, bool movement_occurred)
if (_copy == true) {
_editor->begin_reversible_command (_("copy tempo mark"));
XMLNode &before = map.get_state();
map.add_tempo (_marker->tempo(), when);
map.add_tempo (_marker->tempo(), when, _marker->tempo().type());
XMLNode &after = map.get_state();
_editor->session()->add_command (new MementoCommand<TempoMap>(map, &before, &after));
_editor->commit_reversible_command ();
} else {
/* we removed it before, so add it back now */
map.add_tempo (_marker->tempo(), when);
map.add_tempo (_marker->tempo(), when, _marker->tempo().type());
XMLNode &after = map.get_state();
_editor->session()->add_command (new MementoCommand<TempoMap>(map, before_state, &after));
_editor->commit_reversible_command ();
@ -3369,7 +3369,7 @@ TempoMarkerDrag::aborted (bool moved)
if (moved) {
TempoMap& map (_editor->session()->tempo_map());
/* we removed it before, so add it back now */
map.add_tempo (_marker->tempo(), _marker->tempo().start());
map.add_tempo (_marker->tempo(), _marker->tempo().start(), _marker->tempo().type());
// delete the dummy marker we used for visual representation while moving.
// a new visual marker will show up automatically.
delete _marker;

View file

@ -6552,7 +6552,7 @@ Editor::define_one_bar (framepos_t start, framepos_t end)
} else {
Timecode::BBT_Time bbt;
_session->tempo_map().bbt_time (start, bbt);
_session->tempo_map().add_tempo (Tempo (beats_per_minute, t.note_type()), bbt);
_session->tempo_map().add_tempo (Tempo (beats_per_minute, t.note_type()), bbt, TempoSection::TempoSectionType::Ramp);
}
XMLNode& after (_session->tempo_map().get_state());

View file

@ -710,15 +710,13 @@ Editor::update_fixed_rulers ()
}
void
Editor::update_tempo_based_rulers (ARDOUR::TempoMap::BBTPointList::const_iterator& begin,
ARDOUR::TempoMap::BBTPointList::const_iterator& end)
Editor::update_tempo_based_rulers (std::vector<TempoMap::BBTPoint>& grid)
{
if (_session == 0) {
return;
}
compute_bbt_ruler_scale (leftmost_frame, leftmost_frame+current_page_samples(),
begin, end);
compute_bbt_ruler_scale (grid, leftmost_frame, leftmost_frame+current_page_samples());
_bbt_metric->units_per_pixel = samples_per_pixel;
@ -1011,19 +1009,19 @@ Editor::metric_get_timecode (std::vector<ArdourCanvas::Ruler::Mark>& marks, gdou
}
void
Editor::compute_bbt_ruler_scale (framepos_t lower, framepos_t upper,
ARDOUR::TempoMap::BBTPointList::const_iterator begin,
ARDOUR::TempoMap::BBTPointList::const_iterator end)
Editor::compute_bbt_ruler_scale (std::vector<ARDOUR::TempoMap::BBTPoint>& grid, framepos_t lower, framepos_t upper)
{
if (_session == 0) {
return;
}
TempoMap::BBTPointList::const_iterator i;
std::vector<TempoMap::BBTPoint>::const_iterator i;
Timecode::BBT_Time lower_beat, upper_beat; // the beats at each end of the ruler
framecnt_t beat_before_lower_pos = _session->tempo_map().frame_at_beat (floor(_session->tempo_map().beat_at_frame (lower)));
framecnt_t beat_after_upper_pos = _session->tempo_map().frame_at_beat (floor (_session->tempo_map().beat_at_frame (upper)) + 1.0);
_session->bbt_time (lower, lower_beat);
_session->bbt_time (upper, upper_beat);
_session->bbt_time (beat_before_lower_pos, lower_beat);
_session->bbt_time (beat_after_upper_pos, upper_beat);
uint32_t beats = 0;
bbt_accent_modulo = 1;
@ -1103,19 +1101,21 @@ Editor::compute_bbt_ruler_scale (framepos_t lower, framepos_t upper,
bbt_beat_subdivision = 4;
break;
}
if (distance (begin, end) == 0) {
if (distance (grid.begin(), grid.end()) == 0) {
return;
}
i = end;
i = grid.end();
i--;
if ((*i).beat >= (*begin).beat) {
bbt_bars = (*i).bar - (*begin).bar;
/* XX ?? */
if ((*i).beat >= (*grid.begin()).beat) {
bbt_bars = (*i).bar - (*grid.begin()).bar;
} else {
bbt_bars = (*i).bar - (*begin).bar - 1;
bbt_bars = (*i).bar - (*grid.begin()).bar;
}
beats = distance (begin, end) - bbt_bars;
beats = distance (grid.begin(), grid.end()) - bbt_bars;
/* Only show the bar helper if there aren't many bars on the screen */
if ((bbt_bars < 2) || (beats < 5)) {
@ -1140,7 +1140,7 @@ Editor::compute_bbt_ruler_scale (framepos_t lower, framepos_t upper,
bbt_ruler_scale = bbt_show_ticks_detail;
}
if ((bbt_ruler_scale == bbt_show_ticks_detail) && (lower_beat.beats == upper_beat.beats) && (upper_beat.ticks - lower_beat.ticks <= Timecode::BBT_Time::ticks_per_beat / 4)) {
if ((bbt_ruler_scale == bbt_show_ticks_detail) && beats < 3) {
bbt_ruler_scale = bbt_show_ticks_super_detail;
}
}
@ -1161,38 +1161,34 @@ Editor::metric_get_bbt (std::vector<ArdourCanvas::Ruler::Mark>& marks, gdouble l
return;
}
TempoMap::BBTPointList::const_iterator i;
std::vector<TempoMap::BBTPoint>::const_iterator i;
char buf[64];
gint n = 0;
framepos_t pos;
Timecode::BBT_Time next_beat;
framepos_t next_beat_pos;
uint32_t beats = 0;
uint32_t tick = 0;
uint32_t skip;
uint32_t t;
framepos_t frame_skip;
double frame_skip_error;
double bbt_position_of_helper;
double accumulated_error;
bool i_am_accented = false;
bool helper_active = false;
ArdourCanvas::Ruler::Mark mark;
ARDOUR::TempoMap::BBTPointList::const_iterator begin;
ARDOUR::TempoMap::BBTPointList::const_iterator end;
std::vector<TempoMap::BBTPoint> grid;
compute_current_bbt_points (lower, upper, begin, end);
compute_current_bbt_points (grid, lower, upper);
if (distance (begin, end) == 0) {
if (distance (grid.begin(), grid.end()) == 0) {
return;
}
switch (bbt_ruler_scale) {
case bbt_show_beats:
beats = distance (begin, end);
beats = distance (grid.begin(), grid.end());
bbt_nmarks = beats + 2;
mark.label = "";
@ -1200,7 +1196,7 @@ Editor::metric_get_bbt (std::vector<ArdourCanvas::Ruler::Mark>& marks, gdouble l
mark.style = ArdourCanvas::Ruler::Mark::Micro;
marks.push_back (mark);
for (n = 1, i = begin; n < bbt_nmarks && i != end; ++i) {
for (n = 1, i = grid.begin(); n < bbt_nmarks && i != grid.end(); ++i) {
if ((*i).frame < lower && (bbt_bar_helper_on)) {
snprintf (buf, sizeof(buf), "<%" PRIu32 "|%" PRIu32, (*i).bar, (*i).beat);
@ -1228,7 +1224,7 @@ Editor::metric_get_bbt (std::vector<ArdourCanvas::Ruler::Mark>& marks, gdouble l
case bbt_show_ticks:
beats = distance (begin, end);
beats = distance (grid.begin(), grid.end());
bbt_nmarks = (beats + 2) * bbt_beat_subdivision;
bbt_position_of_helper = lower + (30 * Editor::get_current_zoom ());
@ -1240,7 +1236,7 @@ Editor::metric_get_bbt (std::vector<ArdourCanvas::Ruler::Mark>& marks, gdouble l
mark.style = ArdourCanvas::Ruler::Mark::Micro;
marks.push_back (mark);
for (n = 1, i = begin; n < bbt_nmarks && i != end; ++i) {
for (n = 1, i = grid.begin(); n < bbt_nmarks && i != grid.end(); ++i) {
if ((*i).frame < lower && (bbt_bar_helper_on)) {
snprintf (buf, sizeof(buf), "<%" PRIu32 "|%" PRIu32, (*i).bar, (*i).beat);
@ -1265,45 +1261,20 @@ Editor::metric_get_bbt (std::vector<ArdourCanvas::Ruler::Mark>& marks, gdouble l
}
/* Add the tick marks */
skip = Timecode::BBT_Time::ticks_per_beat / bbt_beat_subdivision;
tick = skip; // the first non-beat tick
t = 0;
while (tick < Timecode::BBT_Time::ticks_per_beat && (n < bbt_nmarks)) {
/* Find the next beat */
next_beat.beats = (*i).beat;
next_beat.bars = (*i).bar;
next_beat.ticks = 0;
next_beat.beats = (*i).beat;
next_beat.bars = (*i).bar;
next_beat.ticks = tick;
pos = _session->tempo_map().frame_time (next_beat);
if ((*i).meter->divisions_per_bar() > (next_beat.beats + 1)) {
next_beat.beats += 1;
} else {
next_beat.bars += 1;
next_beat.beats = 1;
}
next_beat_pos = _session->tempo_map().frame_time(next_beat);
frame_skip = (framepos_t) floor (frame_skip_error = (_session->frame_rate() * 60) / (bbt_beat_subdivision * (*i).tempo->beats_per_minute()));
frame_skip_error -= frame_skip;
skip = (uint32_t) (Timecode::BBT_Time::ticks_per_beat / bbt_beat_subdivision);
pos = (*i).frame + frame_skip;
accumulated_error = frame_skip_error;
tick = skip;
for (t = 0; (tick < Timecode::BBT_Time::ticks_per_beat) && (n < bbt_nmarks) && (pos < next_beat_pos) ; pos += frame_skip, tick += skip, ++t) {
if (t % bbt_accent_modulo == (bbt_accent_modulo - 1)) {
if (t % bbt_accent_modulo == (bbt_accent_modulo - 1)) {
i_am_accented = true;
}
mark.label = "";
/* Error compensation for float to framepos_t*/
accumulated_error += frame_skip_error;
if (accumulated_error > 1) {
pos += 1;
accumulated_error -= 1.0f;
}
mark.position = pos;
if ((bbt_beat_subdivision > 4) && i_am_accented) {
@ -1313,7 +1284,10 @@ Editor::metric_get_bbt (std::vector<ArdourCanvas::Ruler::Mark>& marks, gdouble l
}
i_am_accented = false;
marks.push_back (mark);
n++;
tick += skip;
++t;
++n;
}
}
@ -1321,17 +1295,17 @@ Editor::metric_get_bbt (std::vector<ArdourCanvas::Ruler::Mark>& marks, gdouble l
case bbt_show_ticks_detail:
beats = distance (begin, end);
beats = distance (grid.begin(), grid.end());
bbt_nmarks = (beats + 2) * bbt_beat_subdivision;
bbt_position_of_helper = lower + (30 * Editor::get_current_zoom ());
bbt_position_of_helper = lower + (3 * Editor::get_current_zoom ());
mark.label = "";
mark.position = lower;
mark.style = ArdourCanvas::Ruler::Mark::Micro;
marks.push_back (mark);
for (n = 1, i = begin; n < bbt_nmarks && i != end; ++i) {
for (n = 1, i = grid.begin(); n < bbt_nmarks && i != grid.end(); ++i) {
if ((*i).frame < lower && (bbt_bar_helper_on)) {
snprintf (buf, sizeof(buf), "<%" PRIu32 "|%" PRIu32, (*i).bar, (*i).beat);
@ -1356,36 +1330,20 @@ Editor::metric_get_bbt (std::vector<ArdourCanvas::Ruler::Mark>& marks, gdouble l
}
/* Add the tick marks */
skip = Timecode::BBT_Time::ticks_per_beat / bbt_beat_subdivision;
tick = skip; // the first non-beat tick
/* Find the next beat */
t = 0;
while (tick < Timecode::BBT_Time::ticks_per_beat && (n < bbt_nmarks)) {
next_beat.beats = (*i).beat;
next_beat.bars = (*i).bar;
next_beat.beats = (*i).beat;
next_beat.bars = (*i).bar;
next_beat.ticks = tick;
pos = _session->tempo_map().frame_time (next_beat);
if ((*i).meter->divisions_per_bar() > (next_beat.beats + 1)) {
next_beat.beats += 1;
} else {
next_beat.bars += 1;
next_beat.beats = 1;
}
next_beat_pos = _session->tempo_map().frame_time(next_beat);
frame_skip = (framepos_t) floor (frame_skip_error = (_session->frame_rate() * 60) / (bbt_beat_subdivision * (*i).tempo->beats_per_minute()));
frame_skip_error -= frame_skip;
skip = (uint32_t) (Timecode::BBT_Time::ticks_per_beat / bbt_beat_subdivision);
pos = (*i).frame + frame_skip;
accumulated_error = frame_skip_error;
tick = skip;
for (t = 0; (tick < Timecode::BBT_Time::ticks_per_beat) && (n < bbt_nmarks) && (pos < next_beat_pos) ; pos += frame_skip, tick += skip, ++t) {
if (t % bbt_accent_modulo == (bbt_accent_modulo - 1)) {
i_am_accented = true;
if (t % bbt_accent_modulo == (bbt_accent_modulo - 1)) {
i_am_accented = true;
}
if (i_am_accented && (pos > bbt_position_of_helper)){
snprintf (buf, sizeof(buf), "%" PRIu32, tick);
} else {
@ -1393,14 +1351,6 @@ Editor::metric_get_bbt (std::vector<ArdourCanvas::Ruler::Mark>& marks, gdouble l
}
mark.label = buf;
/* Error compensation for float to framepos_t*/
accumulated_error += frame_skip_error;
if (accumulated_error > 1) {
pos += 1;
accumulated_error -= 1.0f;
}
mark.position = pos;
if ((bbt_beat_subdivision > 4) && i_am_accented) {
@ -1409,7 +1359,11 @@ Editor::metric_get_bbt (std::vector<ArdourCanvas::Ruler::Mark>& marks, gdouble l
mark.style = ArdourCanvas::Ruler::Mark::Micro;
}
i_am_accented = false;
n++;
marks.push_back (mark);
tick += skip;
++t;
++n;
}
}
@ -1417,17 +1371,17 @@ Editor::metric_get_bbt (std::vector<ArdourCanvas::Ruler::Mark>& marks, gdouble l
case bbt_show_ticks_super_detail:
beats = distance (begin, end);
beats = distance (grid.begin(), grid.end());
bbt_nmarks = (beats + 2) * bbt_beat_subdivision;
bbt_position_of_helper = lower + (30 * Editor::get_current_zoom ());
bbt_position_of_helper = lower + (3 * Editor::get_current_zoom ());
mark.label = "";
mark.position = lower;
mark.style = ArdourCanvas::Ruler::Mark::Micro;
marks.push_back (mark);
for (n = 1, i = begin; n < bbt_nmarks && i != end; ++i) {
for (n = 1, i = grid.begin(); n < bbt_nmarks && i != grid.end(); ++i) {
if ((*i).frame < lower && (bbt_bar_helper_on)) {
snprintf (buf, sizeof(buf), "<%" PRIu32 "|%" PRIu32, (*i).bar, (*i).beat);
@ -1452,61 +1406,40 @@ Editor::metric_get_bbt (std::vector<ArdourCanvas::Ruler::Mark>& marks, gdouble l
}
/* Add the tick marks */
/* Find the next beat */
skip = Timecode::BBT_Time::ticks_per_beat / bbt_beat_subdivision;
next_beat.beats = (*i).beat;
next_beat.bars = (*i).bar;
tick = skip; // the first non-beat tick
t = 0;
while (tick < Timecode::BBT_Time::ticks_per_beat && (n < bbt_nmarks)) {
if ((*i).meter->divisions_per_bar() > (next_beat.beats + 1)) {
next_beat.beats += 1;
} else {
next_beat.bars += 1;
next_beat.beats = 1;
}
next_beat.ticks = tick;
pos = _session->tempo_map().frame_time (next_beat);
if (t % bbt_accent_modulo == (bbt_accent_modulo - 1)) {
i_am_accented = true;
}
next_beat_pos = _session->tempo_map().frame_time(next_beat);
if (pos > bbt_position_of_helper) {
snprintf (buf, sizeof(buf), "%" PRIu32, tick);
} else {
buf[0] = '\0';
}
frame_skip = (framepos_t) floor (frame_skip_error = (_session->frame_rate() * 60) / (bbt_beat_subdivision * (*i).tempo->beats_per_minute()));
frame_skip_error -= frame_skip;
skip = (uint32_t) (Timecode::BBT_Time::ticks_per_beat / bbt_beat_subdivision);
mark.label = buf;
mark.position = pos;
pos = (*i).frame + frame_skip;
accumulated_error = frame_skip_error;
if ((bbt_beat_subdivision > 4) && i_am_accented) {
mark.style = ArdourCanvas::Ruler::Mark::Minor;
} else {
mark.style = ArdourCanvas::Ruler::Mark::Micro;
}
i_am_accented = false;
marks.push_back (mark);
tick = skip;
for (t = 0; (tick < Timecode::BBT_Time::ticks_per_beat) && (n < bbt_nmarks) && (pos < next_beat_pos) ; pos += frame_skip, tick += skip, ++t) {
if (t % bbt_accent_modulo == (bbt_accent_modulo - 1)) {
i_am_accented = true;
}
if (pos > bbt_position_of_helper) {
snprintf (buf, sizeof(buf), "%" PRIu32, tick);
} else {
buf[0] = '\0';
}
mark.label = buf;
/* Error compensation for float to framepos_t*/
accumulated_error += frame_skip_error;
if (accumulated_error > 1) {
pos += 1;
accumulated_error -= 1.0f;
}
mark.position = pos;
if ((bbt_beat_subdivision > 4) && i_am_accented) {
mark.style = ArdourCanvas::Ruler::Mark::Minor;
} else {
mark.style = ArdourCanvas::Ruler::Mark::Micro;
}
i_am_accented = false;
marks.push_back (mark);
n++;
tick += skip;
++t;
++n;
}
}
@ -1523,7 +1456,7 @@ Editor::metric_get_bbt (std::vector<ArdourCanvas::Ruler::Mark>& marks, gdouble l
case bbt_show_64:
bbt_nmarks = (gint) (bbt_bars / 64) + 1;
for (n = 0, i = begin; i != end && n < bbt_nmarks; i++) {
for (n = 0, i = grid.begin(); i != grid.end() && n < bbt_nmarks; i++) {
if ((*i).is_bar()) {
if ((*i).bar % 64 == 1) {
if ((*i).bar % 256 == 1) {
@ -1548,7 +1481,7 @@ Editor::metric_get_bbt (std::vector<ArdourCanvas::Ruler::Mark>& marks, gdouble l
case bbt_show_16:
bbt_nmarks = (bbt_bars / 16) + 1;
for (n = 0, i = begin; i != end && n < bbt_nmarks; i++) {
for (n = 0, i = grid.begin(); i != grid.end() && n < bbt_nmarks; i++) {
if ((*i).is_bar()) {
if ((*i).bar % 16 == 1) {
if ((*i).bar % 64 == 1) {
@ -1573,7 +1506,7 @@ Editor::metric_get_bbt (std::vector<ArdourCanvas::Ruler::Mark>& marks, gdouble l
case bbt_show_4:
bbt_nmarks = (bbt_bars / 4) + 1;
for (n = 0, i = begin; i != end && n < bbt_nmarks; ++i) {
for (n = 0, i = grid.begin(); i != grid.end() && n < bbt_nmarks; ++i) {
if ((*i).is_bar()) {
if ((*i).bar % 4 == 1) {
if ((*i).bar % 16 == 1) {
@ -1599,7 +1532,7 @@ Editor::metric_get_bbt (std::vector<ArdourCanvas::Ruler::Mark>& marks, gdouble l
case bbt_show_1:
// default:
bbt_nmarks = bbt_bars + 2;
for (n = 0, i = begin; i != end && n < bbt_nmarks; ++i) {
for (n = 0, i = grid.begin(); i != grid.end() && n < bbt_nmarks; ++i) {
if ((*i).is_bar()) {
if ((*i).bar % 4 == 1) {
snprintf (buf, sizeof(buf), "%" PRIu32, (*i).bar);

View file

@ -114,13 +114,12 @@ Editor::tempo_map_changed (const PropertyChange& /*ignored*/)
tempo_lines->tempo_map_changed();
}
ARDOUR::TempoMap::BBTPointList::const_iterator begin;
ARDOUR::TempoMap::BBTPointList::const_iterator end;
std::vector<TempoMap::BBTPoint> grid;
compute_current_bbt_points (leftmost_frame, leftmost_frame + current_page_samples(), begin, end);
compute_current_bbt_points (grid, leftmost_frame, leftmost_frame + current_page_samples());
_session->tempo_map().apply_with_metrics (*this, &Editor::draw_metric_marks); // redraw metric markers
draw_measures (begin, end);
update_tempo_based_rulers (begin, end);
draw_measures (grid);
update_tempo_based_rulers (grid);
}
void
@ -131,32 +130,31 @@ Editor::redisplay_tempo (bool immediate_redraw)
}
if (immediate_redraw) {
ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_begin;
ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_end;
std::vector<TempoMap::BBTPoint> grid;
compute_current_bbt_points (leftmost_frame, leftmost_frame + current_page_samples(),
current_bbt_points_begin, current_bbt_points_end);
draw_measures (current_bbt_points_begin, current_bbt_points_end);
update_tempo_based_rulers (current_bbt_points_begin, current_bbt_points_end); // redraw rulers and measures
compute_current_bbt_points (grid, leftmost_frame, leftmost_frame + current_page_samples());
draw_measures (grid);
update_tempo_based_rulers (grid); // redraw rulers and measure lines
} else {
Glib::signal_idle().connect (sigc::bind_return (sigc::bind (sigc::mem_fun (*this, &Editor::redisplay_tempo), true), false));
}
}
/* computes a grid starting a beat before and ending a beat after leftmost and rightmost respectively */
void
Editor::compute_current_bbt_points (framepos_t leftmost, framepos_t rightmost,
ARDOUR::TempoMap::BBTPointList::const_iterator& begin,
ARDOUR::TempoMap::BBTPointList::const_iterator& end)
Editor::compute_current_bbt_points (std::vector<TempoMap::BBTPoint>& grid, framepos_t leftmost, framepos_t rightmost)
{
if (!_session) {
return;
}
framecnt_t beat_before_lower_pos = _session->tempo_map().frame_at_beat (floor(_session->tempo_map().beat_at_frame (leftmost)));
framecnt_t beat_after_upper_pos = _session->tempo_map().frame_at_beat (floor (_session->tempo_map().beat_at_frame (rightmost)) + 1.0);
/* prevent negative values of leftmost from creeping into tempomap
*/
_session->tempo_map().get_grid (begin, end, max (leftmost, (framepos_t) 0), rightmost);
_session->tempo_map().get_grid (grid, max (beat_before_lower_pos, (framepos_t) 0), beat_after_upper_pos);
}
void
@ -168,10 +166,9 @@ Editor::hide_measures ()
}
void
Editor::draw_measures (ARDOUR::TempoMap::BBTPointList::const_iterator& begin,
ARDOUR::TempoMap::BBTPointList::const_iterator& end)
Editor::draw_measures (std::vector<ARDOUR::TempoMap::BBTPoint>& grid)
{
if (_session == 0 || _show_measures == false || distance (begin, end) == 0) {
if (_session == 0 || _show_measures == false || distance (grid.begin(), grid.end()) == 0) {
return;
}
@ -180,7 +177,7 @@ Editor::draw_measures (ARDOUR::TempoMap::BBTPointList::const_iterator& begin,
}
const unsigned divisions = get_grid_beat_divisions(leftmost_frame);
tempo_lines->draw (begin, end, divisions, leftmost_frame, _session->frame_rate());
tempo_lines->draw (grid, divisions, leftmost_frame, _session->frame_rate());
}
void
@ -214,7 +211,7 @@ Editor::mouse_add_new_tempo_event (framepos_t frame)
begin_reversible_command (_("add tempo mark"));
XMLNode &before = map.get_state();
map.add_tempo (Tempo (bpm,nt), requested);
map.add_tempo (Tempo (bpm,nt), requested, tempo_dialog.get_tempo_type());
XMLNode &after = map.get_state();
_session->add_command(new MementoCommand<TempoMap>(map, &before, &after));
commit_reversible_command ();
@ -329,7 +326,7 @@ Editor::edit_tempo_section (TempoSection* section)
begin_reversible_command (_("replace tempo mark"));
XMLNode &before = _session->tempo_map().get_state();
_session->tempo_map().replace_tempo (*section, Tempo (bpm, nt), when);
_session->tempo_map().replace_tempo (*section, Tempo (bpm, nt), when, tempo_dialog.get_tempo_type());
XMLNode &after = _session->tempo_map().get_state();
_session->add_command (new MementoCommand<TempoMap>(_session->tempo_map(), &before, &after));
commit_reversible_command ();

View file

@ -106,12 +106,21 @@ TempoDialog::init (const Timecode::BBT_Time& when, double bpm, double note_type,
pulse_selector.set_active_text (strings[3]); // "quarter"
}
strings.clear();
tempo_types.insert (make_pair (_("ramped"), TempoSection::TempoSectionType::Ramp));
strings.push_back (_("ramped"));
tempo_types.insert (make_pair (_("constant"), TempoSection::TempoSectionType::Constant));
strings.push_back (_("constant"));
set_popdown_strings (tempo_type, strings);
tempo_type.set_active_text (strings[0]); // "ramped"
Table* table;
if (UIConfiguration::instance().get_allow_non_quarter_pulse()) {
table = manage (new Table (5, 5));
table = manage (new Table (5, 6));
} else {
table = manage (new Table (5, 4));
table = manage (new Table (5, 5));
}
table->set_spacings (6);
@ -156,8 +165,12 @@ TempoDialog::init (const Timecode::BBT_Time& when, double bpm, double note_type,
table->attach (*when_label, 0, 1, row, row+1);
}
Label* tempo_type_label = manage (new Label(_("Tempo Type:"), ALIGN_LEFT, ALIGN_CENTER));
table->attach (*tempo_type_label, 0, 1, row+1, row+2);
table->attach (tempo_type, 1, 2, row+1, row + 2);
get_vbox()->set_border_width (12);
get_vbox()->pack_end (*table);
table->show_all ();
add_button (Stock::CANCEL, RESPONSE_CANCEL);
@ -258,6 +271,19 @@ TempoDialog::get_note_type ()
return x->second;
}
TempoSection::TempoSectionType
TempoDialog::get_tempo_type ()
{
TempoTypes::iterator x = tempo_types.find (tempo_type.get_active_text());
if (x == tempo_types.end()) {
error << string_compose(_("incomprehensible pulse note type (%1)"), tempo_type.get_active_text()) << endmsg;
return TempoSection::TempoSectionType::Constant;
}
return x->second;
}
void
TempoDialog::pulse_change ()
{

View file

@ -44,6 +44,7 @@ public:
double get_bpm ();
double get_note_type ();
bool get_bbt_time (Timecode::BBT_Time&);
ARDOUR::TempoSection::TempoSectionType get_tempo_type ();
private:
void init (const Timecode::BBT_Time& start, double, double, bool);
@ -59,6 +60,9 @@ private:
typedef std::map<std::string,float> NoteTypes;
NoteTypes note_types;
typedef std::map<std::string, ARDOUR::TempoSection::TempoSectionType> TempoTypes;
TempoTypes tempo_types;
bool tapped; // whether the tap-tempo button has been clicked
double sum_x, sum_xx, sum_xy, sum_y;
double tap_count;
@ -74,6 +78,8 @@ private:
Gtk::Label when_beat_label;
Gtk::Label pulse_selector_label;
Gtk::Button tap_tempo_button;
Gtk::ComboBoxText tempo_type;
};
class MeterDialog : public ArdourDialog

View file

@ -54,12 +54,12 @@ TempoLines::hide ()
}
void
TempoLines::draw_ticks (const ARDOUR::TempoMap::BBTPointList::const_iterator& b,
unsigned divisions,
TempoLines::draw_ticks (std::vector<ARDOUR::TempoMap::BBTPoint>& grid,
unsigned divisions,
framecnt_t leftmost_frame,
framecnt_t frame_rate)
{
const double fpb = b->tempo->frames_per_beat(frame_rate);
const double fpb = grid.begin()->tempo->frames_per_beat(frame_rate);
const uint32_t base = UIConfiguration::instance().color_mod("measure line beat", "measure line beat");
for (unsigned l = 1; l < divisions; ++l) {
@ -74,7 +74,8 @@ TempoLines::draw_ticks (const ARDOUR::TempoMap::BBTPointList::const_iterator& b,
/* draw line with alpha corresponding to coarsest level */
const uint8_t a = max(8, (int)rint(UINT_RGBA_A(base) / (0.8 * log2(level))));
const uint32_t c = UINT_RGBA_CHANGE_A(base, a);
const framepos_t f = b->frame + (l * (fpb / (double)divisions));
const framepos_t f = grid.begin()->frame + (l * (fpb / (double)divisions));
//const framepos_t f = frame_at_tick (last_beat_in_ticks + (l * (BBT_Time::ticks_per_beat / (double)divisions)));
if (f > leftmost_frame) {
lines.add (PublicEditor::instance().sample_to_pixel_unrounded (f), 1.0, c);
}
@ -82,13 +83,12 @@ TempoLines::draw_ticks (const ARDOUR::TempoMap::BBTPointList::const_iterator& b,
}
void
TempoLines::draw (const ARDOUR::TempoMap::BBTPointList::const_iterator& begin,
const ARDOUR::TempoMap::BBTPointList::const_iterator& end,
unsigned divisions,
TempoLines::draw (std::vector<ARDOUR::TempoMap::BBTPoint>& grid,
unsigned divisions,
framecnt_t leftmost_frame,
framecnt_t frame_rate)
{
ARDOUR::TempoMap::BBTPointList::const_iterator i;
std::vector<ARDOUR::TempoMap::BBTPoint>::const_iterator i;
double beat_density;
uint32_t beats = 0;
@ -97,10 +97,10 @@ TempoLines::draw (const ARDOUR::TempoMap::BBTPointList::const_iterator& begin,
/* get the first bar spacing */
i = end;
i = grid.end();
i--;
bars = (*i).bar - (*begin).bar;
beats = distance (begin, end) - bars;
bars = (*i).bar - (*grid.begin()).bar;
beats = distance (grid.begin(), grid.end()) - bars;
beat_density = (beats * 10.0f) / lines.canvas()->width();
@ -116,15 +116,14 @@ TempoLines::draw (const ARDOUR::TempoMap::BBTPointList::const_iterator& begin,
}
lines.clear ();
if (beat_density <= 0.12 && begin != end && begin->frame > 0) {
/* draw subdivisions of the beat before the first visible beat line */
ARDOUR::TempoMap::BBTPointList::const_iterator prev = begin;
--prev;
draw_ticks(prev, divisions, leftmost_frame, frame_rate);
if (beat_density <= 0.12 && grid.begin() != grid.end() && grid.begin()->frame > 0) {
/* draw subdivisions of the beat before the first visible beat line XX this shouldn't happen now */
std::vector<ARDOUR::TempoMap::BBTPoint> vec;
vec.push_back (*i);
draw_ticks (vec, divisions, leftmost_frame, frame_rate);
}
for (i = begin; i != end; ++i) {
for (i = grid.begin(); i != grid.end(); ++i) {
if ((*i).is_bar()) {
color = UIConfiguration::instance().color ("measure line bar");
@ -141,7 +140,10 @@ TempoLines::draw (const ARDOUR::TempoMap::BBTPointList::const_iterator& begin,
if (beat_density <= 0.12) {
/* draw subdivisions of this beat */
draw_ticks(i, divisions, leftmost_frame, frame_rate);
std::vector<ARDOUR::TempoMap::BBTPoint> vec;
vec.push_back (*i);
draw_ticks(vec, divisions, leftmost_frame, frame_rate);
}
}
}

View file

@ -29,9 +29,8 @@ public:
void tempo_map_changed();
void draw (const ARDOUR::TempoMap::BBTPointList::const_iterator& begin,
const ARDOUR::TempoMap::BBTPointList::const_iterator& end,
unsigned divisions,
void draw (std::vector<ARDOUR::TempoMap::BBTPoint>& grid,
unsigned divisions,
ARDOUR::framecnt_t leftmost_frame,
ARDOUR::framecnt_t frame_rate);
@ -39,8 +38,8 @@ public:
void hide();
private:
void draw_ticks (const ARDOUR::TempoMap::BBTPointList::const_iterator& b,
unsigned divisions,
void draw_ticks (std::vector<ARDOUR::TempoMap::BBTPoint>& grid,
unsigned divisions,
ARDOUR::framecnt_t leftmost_frame,
ARDOUR::framecnt_t frame_rate);

View file

@ -55,6 +55,7 @@ class LIBARDOUR_API Tempo {
: _beats_per_minute (bpm), _note_type(type) {}
double beats_per_minute () const { return _beats_per_minute;}
double ticks_per_minute () const { return _beats_per_minute * Timecode::BBT_Time::ticks_per_beat;}
double note_type () const { return _note_type;}
/** audio samples per beat
* @param sr samplerate
@ -146,10 +147,15 @@ class LIBARDOUR_API MeterSection : public MetricSection, public Meter {
/** A section of timeline with a certain Tempo. */
class LIBARDOUR_API TempoSection : public MetricSection, public Tempo {
public:
TempoSection (const Timecode::BBT_Time& start, double qpm, double note_type)
: MetricSection (start), Tempo (qpm, note_type), _bar_offset (-1.0) {}
TempoSection (framepos_t start, double qpm, double note_type)
: MetricSection (start), Tempo (qpm, note_type), _bar_offset (-1.0) {}
enum TempoSectionType {
Ramp,
Constant,
};
TempoSection (const Timecode::BBT_Time& start, double qpm, double note_type, TempoSectionType tempo_type)
: MetricSection (start), Tempo (qpm, note_type), _bar_offset (-1.0), _type (tempo_type) {}
TempoSection (framepos_t start, double qpm, double note_type, TempoSectionType tempo_type)
: MetricSection (start), Tempo (qpm, note_type), _bar_offset (-1.0), _type (tempo_type) {}
TempoSection (const XMLNode&);
static const std::string xml_state_node_name;
@ -160,7 +166,41 @@ class LIBARDOUR_API TempoSection : public MetricSection, public Tempo {
void update_bbt_time_from_bar_offset (const Meter&);
double bar_offset() const { return _bar_offset; }
void set_type (TempoSectionType type);
TempoSectionType type () const { return _type; }
double tempo_at_frame (framepos_t frame, double end_bpm, framepos_t end_frame, framecnt_t frame_rate) const;
framepos_t frame_at_tempo (double tempo, double end_bpm, framepos_t end_frame, framecnt_t frame_rate) const;
double tick_at_frame (framepos_t frame, double end_bpm, framepos_t end_frame, framecnt_t frame_rate) const;
framepos_t frame_at_tick (double tick, double end_bpm, framepos_t end_frame, framecnt_t frame_rate) const;
double beat_at_frame (framepos_t frame, double end_bpm, framepos_t end_frame, framecnt_t frame_rate) const;
framepos_t frame_at_beat (double beat, double end_bpm, framepos_t end_frame, framecnt_t frame_rate) const;
private:
framecnt_t minute_to_frame (double time, framecnt_t frame_rate) const;
double frame_to_minute (framecnt_t frame, framecnt_t frame_rate) const;
/* tempo ramp functions. zero-based with time in minutes,
* 'tick tempo' in ticks per minute and tempo in bpm.
* time relative to section start.
*/
double c_func (double end_tpm, double end_time) const;
double a_func (double begin_tpm, double end_tpm, double end_time) const;
double tempo_at_time (double time, double end_bpm, double end_time) const;
double time_at_tempo (double tempo, double end_bpm, double end_time) const;
double tick_tempo_at_time (double time, double end_tpm, double end_time) const;
double time_at_tick_tempo (double tick_tempo, double end_tpm, double end_time) const;
double tick_at_time (double time, double end_tpm, double end_time) const;
double time_at_tick (double tick, double end_tpm, double end_time) const;
double beat_at_time (double time, double end_tpm, double end_time) const;
double time_at_beat (double beat, double end_tpm, double end_time) const;
/* this value provides a fractional offset into the bar in which
the tempo section is located in. A value of 0.0 indicates that
it occurs on the first beat of the bar, a value of 0.5 indicates
@ -170,6 +210,7 @@ class LIBARDOUR_API TempoSection : public MetricSection, public Tempo {
position within the bar if/when the meter changes.
*/
double _bar_offset;
TempoSectionType _type;
};
typedef std::list<MetricSection*> Metrics;
@ -231,11 +272,11 @@ class LIBARDOUR_API TempoMap : public PBD::StatefulDestructible
struct BBTPoint {
framepos_t frame;
const MeterSection* meter;
const TempoSection* tempo;
const Tempo* tempo;
uint32_t bar;
uint32_t beat;
BBTPoint (const MeterSection& m, const TempoSection& t, framepos_t f,
BBTPoint (const MeterSection& m, const Tempo& t, framepos_t f,
uint32_t b, uint32_t e)
: frame (f), meter (&m), tempo (&t), bar (b), beat (e) {}
@ -245,19 +286,18 @@ class LIBARDOUR_API TempoMap : public PBD::StatefulDestructible
bool is_bar() const { return beat == 1; }
};
typedef std::vector<BBTPoint> BBTPointList;
template<class T> void apply_with_metrics (T& obj, void (T::*method)(const Metrics&)) {
Glib::Threads::RWLock::ReaderLock lm (lock);
(obj.*method)(metrics);
}
void get_grid (BBTPointList::const_iterator&, BBTPointList::const_iterator&,
void get_grid (std::vector<BBTPoint>&,
framepos_t start, framepos_t end);
/* TEMPO- AND METER-SENSITIVE FUNCTIONS
bbt_time(), bbt_time_rt(), frame_time() and bbt_duration_at()
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.
@ -267,11 +307,12 @@ class LIBARDOUR_API TempoMap : public PBD::StatefulDestructible
void bbt_time (framepos_t when, Timecode::BBT_Time&);
/* realtime safe variant of ::bbt_time(), will throw
std::logic_error if the map is not large enough
to provide an answer.
*/
void bbt_time_rt (framepos_t when, Timecode::BBT_Time&);
double tick_at_frame (framecnt_t frame) const;
framecnt_t frame_at_tick (double tick) const;
double beat_at_frame (framecnt_t frame) const;
framecnt_t frame_at_beat (double beat) const;
framepos_t frame_time (const Timecode::BBT_Time&);
framecnt_t bbt_duration_at (framepos_t, const Timecode::BBT_Time&, int dir);
@ -293,19 +334,19 @@ class LIBARDOUR_API TempoMap : public PBD::StatefulDestructible
static const Tempo& default_tempo() { return _default_tempo; }
static const Meter& default_meter() { return _default_meter; }
const Tempo& tempo_at (framepos_t) const;
const Tempo tempo_at (framepos_t) const;
const Meter& meter_at (framepos_t) const;
const TempoSection& tempo_section_at (framepos_t) const;
const MeterSection& meter_section_at (framepos_t) const;
void add_tempo (const Tempo&, Timecode::BBT_Time where);
void add_tempo (const Tempo&, Timecode::BBT_Time where, TempoSection::TempoSectionType type);
void add_meter (const Meter&, Timecode::BBT_Time where);
void remove_tempo (const TempoSection&, bool send_signal);
void remove_meter (const MeterSection&, bool send_signal);
void replace_tempo (const TempoSection&, const Tempo&, const Timecode::BBT_Time& where);
void replace_tempo (const TempoSection&, const Tempo&, const Timecode::BBT_Time& where, TempoSection::TempoSectionType type);
void replace_meter (const MeterSection&, const Meter&, const Timecode::BBT_Time& where);
framepos_t round_to_bar (framepos_t frame, RoundMode dir);
@ -352,32 +393,26 @@ class LIBARDOUR_API TempoMap : public PBD::StatefulDestructible
Metrics metrics;
framecnt_t _frame_rate;
mutable Glib::Threads::RWLock lock;
BBTPointList _map;
void recompute_map (bool reassign_tempo_bbt, framepos_t end = -1);
void extend_map (framepos_t end);
void require_map_to (framepos_t pos);
void require_map_to (const Timecode::BBT_Time&);
void _extend_map (TempoSection* tempo, MeterSection* meter,
Metrics::iterator next_metric,
Timecode::BBT_Time current, framepos_t current_frame, framepos_t end);
BBTPointList::const_iterator bbt_before_or_at (framepos_t);
BBTPointList::const_iterator bbt_before_or_at (const Timecode::BBT_Time&);
BBTPointList::const_iterator bbt_after_or_at (framepos_t);
Timecode::BBT_Time current, framepos_t current_frame, framepos_t end);
framepos_t round_to_type (framepos_t fr, RoundMode dir, BBTPointType);
void bbt_time (framepos_t, Timecode::BBT_Time&, const BBTPointList::const_iterator&);
framecnt_t bbt_duration_at_unlocked (const Timecode::BBT_Time& when, const Timecode::BBT_Time& bbt, int dir);
const MeterSection& first_meter() const;
MeterSection& first_meter();
const TempoSection& first_tempo() const;
TempoSection& first_tempo();
Timecode::BBT_Time beats_to_bbt (double beats);
int32_t bars_in_meter_section (MeterSection* ms) const;
void do_insert (MetricSection* section);
void add_tempo_locked (const Tempo&, Timecode::BBT_Time where, bool recompute);
void add_tempo_locked (const Tempo&, Timecode::BBT_Time where, bool recompute, TempoSection::TempoSectionType type);
void add_meter_locked (const Meter&, Timecode::BBT_Time where, bool recompute);
bool remove_tempo_locked (const TempoSection&);

View file

@ -42,8 +42,7 @@ Pool Click::pool ("click", sizeof (Click), 1024);
void
Session::click (framepos_t start, framecnt_t nframes)
{
TempoMap::BBTPointList::const_iterator points_begin;
TempoMap::BBTPointList::const_iterator points_end;
vector<TempoMap::BBTPoint> points;
Sample *buf;
framecnt_t click_distance;
@ -72,13 +71,13 @@ Session::click (framepos_t start, framecnt_t nframes)
BufferSet& bufs = get_scratch_buffers(ChanCount(DataType::AUDIO, 1));
buf = bufs.get_audio(0).data();
_tempo_map->get_grid (points_begin, points_end, start, end);
_tempo_map->get_grid (points, start, end);
if (distance (points_begin, points_end) == 0) {
if (distance (points.begin(), points.end()) == 0) {
goto run_clicks;
}
for (TempoMap::BBTPointList::const_iterator i = points_begin; i != points_end; ++i) {
for (vector<TempoMap::BBTPoint>::iterator i = points.begin(); i != points.end(); ++i) {
switch ((*i).beat) {
case 1:
if (click_emphasis_data && Config->get_use_click_emphasis () == true) {

View file

@ -223,9 +223,29 @@ intptr_t Session::vst_callback (
Timecode::BBT_Time bbt;
try {
session->tempo_map().bbt_time_rt (now, bbt);
double ppqBar;
double ppqPos = vst_ppq (tm, bbt, ppqBar);
session->tempo_map().bbt_time (now, bbt);
/* PPQ = pulse per quarter
* VST's "pulse" is our "division".
*
* 8 divisions per bar, 1 division = quarter, so 8 quarters per bar, ppq = 1
* 8 divisions per bar, 1 division = eighth, so 4 quarters per bar, ppq = 2
* 4 divisions per bar, 1 division = quarter, so 4 quarters per bar, ppq = 1
* 4 divisions per bar, 1 division = half, so 8 quarters per bar, ppq = 0.5
* 4 divisions per bar, 1 division = fifth, so (4 * 5/4) quarters per bar, ppq = 5/4
*
* general: divs_per_bar / (note_type / 4.0)
*/
double ppq_scaling = tm.meter().note_divisor() / 4.0;
/* Note that this assumes constant meter/tempo throughout the session. Stupid VST */
double ppqBar = double(bbt.bars - 1) * tm.meter().divisions_per_bar();
double ppqBeat = double(bbt.beats - 1);
double ppqTick = double(bbt.ticks) / Timecode::BBT_Time::ticks_per_beat;
ppqBar *= ppq_scaling;
ppqBeat *= ppq_scaling;
ppqTick *= ppq_scaling;
if (value & (kVstPpqPosValid)) {
timeinfo->ppqPos = ppqPos;

File diff suppressed because it is too large Load diff

View file

@ -121,7 +121,7 @@ JACKSession::timebase_callback (jack_transport_state_t /*state*/,
TempoMetric metric (tempo_map.metric_at (tf));
try {
tempo_map.bbt_time_rt (tf, bbt);
tempo_map.bbt_time (tf, bbt);
pos->bar = bbt.bars;
pos->beat = bbt.beats;

View file

@ -165,10 +165,10 @@ Ruler::render (Rect const & area, Cairo::RefPtr<Cairo::Context> cr) const
}
break;
case Mark::Minor:
cr->rel_line_to (0, -height/4.0);
cr->rel_line_to (0, -height/3.0);
break;
case Mark::Micro:
cr->rel_line_to (0, -height/16.0);
cr->rel_line_to (0, -height/5.0);
break;
}
cr->stroke ();