Tempo ramps - improve music-locked meter drags, improve dump().
- dump now shows cross-calculation of tempo positions.
This commit is contained in:
@@ -3185,7 +3185,7 @@ MeterMarkerDrag::motion (GdkEvent* event, bool first_move)
|
||||
framepos_t const pf = adjusted_current_frame (event);
|
||||
_marker->set_position (pf);
|
||||
if (_marker->meter().position_lock_style() == MusicTime) {
|
||||
double const baf = _editor->session()->tempo_map().beat_at_frame (pf);
|
||||
double const baf = _editor->session()->tempo_map().beat_at_frame (_editor->session()->tempo_map().round_to_bar (pf, (RoundMode) 0));
|
||||
_editor->session()->tempo_map().gui_move_meter (_real_section, _marker->meter(), baf);
|
||||
} else {
|
||||
_editor->session()->tempo_map().gui_move_meter (_real_section, _marker->meter(), pf);
|
||||
|
||||
@@ -336,8 +336,9 @@ Editor::edit_meter_section (MeterSection* section)
|
||||
meter_dialog.get_bbt_time(when);
|
||||
framepos_t const frame = _session->tempo_map().frame_at_beat (_session->tempo_map().bbt_to_beats (when));
|
||||
|
||||
begin_reversible_command (_("replace tempo mark"));
|
||||
begin_reversible_command (_("replace meter mark"));
|
||||
XMLNode &before = _session->tempo_map().get_state();
|
||||
section->set_position_lock_style (meter_dialog.get_lock_style());
|
||||
if (meter_dialog.get_lock_style() == MusicTime) {
|
||||
_session->tempo_map().replace_meter (*section, Meter (bpb, note_type), when);
|
||||
} else {
|
||||
|
||||
@@ -770,6 +770,7 @@ TempoMap::do_insert (MetricSection* section)
|
||||
*/
|
||||
|
||||
*(dynamic_cast<Meter*>(*i)) = *(dynamic_cast<Meter*>(insert_meter));
|
||||
(*i)->set_position_lock_style (insert_meter->position_lock_style());
|
||||
need_add = false;
|
||||
} else {
|
||||
_metrics.erase (i);
|
||||
@@ -917,12 +918,14 @@ TempoMap::replace_meter (const MeterSection& ms, const Meter& meter, const BBT_T
|
||||
{
|
||||
Glib::Threads::RWLock::WriterLock lm (lock);
|
||||
MeterSection& first (first_meter());
|
||||
const PositionLockStyle pl = ms.position_lock_style();
|
||||
if (ms.pulse() != first.pulse()) {
|
||||
remove_meter_locked (ms);
|
||||
add_meter_locked (meter, bbt_to_beats_locked (_metrics, where), where, true);
|
||||
} else {
|
||||
/* cannot move the first meter section */
|
||||
*static_cast<Meter*>(&first) = meter;
|
||||
first.set_position_lock_style (pl);
|
||||
recompute_map (_metrics);
|
||||
}
|
||||
}
|
||||
@@ -936,12 +939,14 @@ TempoMap::replace_meter (const MeterSection& ms, const Meter& meter, const frame
|
||||
{
|
||||
Glib::Threads::RWLock::WriterLock lm (lock);
|
||||
MeterSection& first (first_meter());
|
||||
const PositionLockStyle pl = ms.position_lock_style();
|
||||
if (ms.pulse() != first.pulse()) {
|
||||
remove_meter_locked (ms);
|
||||
add_meter_locked (meter, frame, true);
|
||||
} else {
|
||||
/* cannot move the first meter section */
|
||||
*static_cast<Meter*>(&first) = meter;
|
||||
first.set_position_lock_style (pl);
|
||||
recompute_map (_metrics);
|
||||
}
|
||||
}
|
||||
@@ -1000,7 +1005,6 @@ TempoMap::add_meter_locked (const Meter& meter, double beat, BBT_Time where, boo
|
||||
where.beats = 1;
|
||||
where.bars++;
|
||||
}
|
||||
|
||||
/* new meters *always* start on a beat. */
|
||||
where.ticks = 0;
|
||||
double pulse = pulse_at_beat (_metrics, beat);
|
||||
@@ -1285,7 +1289,7 @@ TempoMap::first_meter () const
|
||||
}
|
||||
}
|
||||
|
||||
fatal << _("programming error: no tempo section in tempo map!") << endmsg;
|
||||
fatal << _("programming error: no meter section in tempo map!") << endmsg;
|
||||
abort(); /*NOTREACHED*/
|
||||
return *m;
|
||||
}
|
||||
@@ -1373,21 +1377,25 @@ TempoMap::recompute_meters (Metrics& metrics)
|
||||
MeterSection* meter = 0;
|
||||
MeterSection* prev_m = 0;
|
||||
double accumulated_beats = 0.0;
|
||||
|
||||
uint32_t accumulated_bars = 0;
|
||||
for (Metrics::const_iterator mi = metrics.begin(); mi != metrics.end(); ++mi) {
|
||||
if ((meter = dynamic_cast<MeterSection*> (*mi)) != 0) {
|
||||
if (prev_m) {
|
||||
accumulated_beats += (meter->pulse() - prev_m->pulse()) * prev_m->note_divisor();
|
||||
const double beats_in_m = (meter->pulse() - prev_m->pulse()) * prev_m->note_divisor();
|
||||
accumulated_beats += beats_in_m;
|
||||
accumulated_bars += (beats_in_m + 1) / prev_m->divisions_per_bar();
|
||||
}
|
||||
|
||||
if (meter->position_lock_style() == AudioTime) {
|
||||
pair<double, BBT_Time> pr;
|
||||
pr.first = ceil (pulse_at_frame_locked (metrics, meter->frame()));
|
||||
BBT_Time const where = beats_to_bbt_locked (metrics, accumulated_beats);
|
||||
pr.first = pulse_at_frame_locked (metrics, meter->frame());
|
||||
BBT_Time const where = BBT_Time (accumulated_bars + 1, 1, 0);
|
||||
pr.second = where;
|
||||
meter->set_pulse (pr);
|
||||
} else {
|
||||
meter->set_frame (frame_at_pulse_locked (metrics, meter->pulse()));
|
||||
}
|
||||
|
||||
meter->set_beat (accumulated_beats);
|
||||
prev_m = meter;
|
||||
}
|
||||
@@ -1706,51 +1714,6 @@ TempoMap::pulse_to_bbt (const double& pulse)
|
||||
return ret;
|
||||
}
|
||||
|
||||
double
|
||||
TempoMap::beat_offset_at (const Metrics& metrics, const double& beat) 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 (prev_m) {
|
||||
if (m->beat() > beat) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (m->position_lock_style() == AudioTime) {
|
||||
beat_off += ((m->pulse() - prev_m->pulse()) / prev_m->note_divisor()) - floor ((m->pulse() - prev_m->pulse()) / prev_m->note_divisor());
|
||||
}
|
||||
}
|
||||
prev_m = m;
|
||||
}
|
||||
}
|
||||
|
||||
return beat_off;
|
||||
}
|
||||
|
||||
frameoffset_t
|
||||
TempoMap::frame_offset_at (const Metrics& metrics, const framepos_t& frame) const
|
||||
{
|
||||
frameoffset_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_pulse_locked (metrics, m->pulse()) - m->frame();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return frame_off;
|
||||
}
|
||||
|
||||
double
|
||||
TempoMap::beat_at_frame (const framecnt_t& frame) const
|
||||
{
|
||||
@@ -1841,6 +1804,51 @@ TempoMap::frame_at_pulse_locked (const Metrics& metrics, const double& pulse) co
|
||||
return ret;
|
||||
}
|
||||
|
||||
double
|
||||
TempoMap::beat_offset_at (const Metrics& metrics, const double& beat) 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 (prev_m) {
|
||||
if (m->beat() > beat) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (m->position_lock_style() == AudioTime) {
|
||||
beat_off += ((m->pulse() - prev_m->pulse()) / prev_m->note_divisor()) - floor ((m->pulse() - prev_m->pulse()) / prev_m->note_divisor());
|
||||
}
|
||||
}
|
||||
prev_m = m;
|
||||
}
|
||||
}
|
||||
|
||||
return beat_off;
|
||||
}
|
||||
|
||||
frameoffset_t
|
||||
TempoMap::frame_offset_at (const Metrics& metrics, const framepos_t& frame) const
|
||||
{
|
||||
frameoffset_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_pulse_locked (metrics, m->pulse()) - m->frame();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return frame_off;
|
||||
}
|
||||
|
||||
framepos_t
|
||||
TempoMap::frame_time (const BBT_Time& bbt)
|
||||
{
|
||||
@@ -1883,7 +1891,6 @@ TempoMap::check_solved (Metrics& metrics, bool by_frame)
|
||||
if (by_frame && t->frame() != prev_ts->frame_at_tempo (t->pulses_per_minute(), t->pulse(), _frame_rate)) {
|
||||
return false;
|
||||
}
|
||||
/*
|
||||
if (!by_frame && fabs (t->pulse() - prev_ts->pulse_at_tempo (t->pulses_per_minute(), t->frame(), _frame_rate)) > 0.00001) {
|
||||
std::cerr << "beat precision too low for bpm: " << t->beats_per_minute() << std::endl <<
|
||||
" |error :" << t->pulse() - prev_ts->pulse_at_tempo (t->pulses_per_minute(), t->frame(), _frame_rate) << std::endl <<
|
||||
@@ -1891,7 +1898,6 @@ TempoMap::check_solved (Metrics& metrics, bool by_frame)
|
||||
" |frame at tempo : " << prev_ts->frame_at_tempo (t->pulses_per_minute(), t->pulse(), _frame_rate) << std::endl;
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
}
|
||||
prev_ts = t;
|
||||
}
|
||||
@@ -2067,28 +2073,37 @@ TempoMap::solve_map (Metrics& imaginary, MeterSection* section, const Meter& mt,
|
||||
{
|
||||
MeterSection* prev_ms = 0;
|
||||
|
||||
pair<double, BBT_Time> b_bbt = make_pair (pulse, beats_to_bbt_locked (imaginary, pulse));
|
||||
pair<double, BBT_Time> b_bbt = make_pair (pulse, BBT_Time (1, 1, 0));
|
||||
double accumulated_beats = 0.0;
|
||||
uint32_t accumulated_bars = 0;
|
||||
|
||||
section->set_pulse (b_bbt);
|
||||
MetricSectionSorter cmp;
|
||||
imaginary.sort (cmp);
|
||||
|
||||
for (Metrics::iterator i = imaginary.begin(); i != imaginary.end(); ++i) {
|
||||
MeterSection* m;
|
||||
if ((m = dynamic_cast<MeterSection*> (*i)) != 0) {
|
||||
if (prev_ms) {
|
||||
if (m == section){
|
||||
section->set_frame (frame_at_pulse_locked (imaginary, pulse_at_beat (imaginary, pulse)));
|
||||
prev_ms = section;
|
||||
continue;
|
||||
}
|
||||
double const beats_in_m = (m->pulse() - prev_ms->pulse()) * prev_ms->note_divisor();
|
||||
accumulated_beats += beats_in_m;
|
||||
accumulated_bars += (beats_in_m + 1) / prev_ms->divisions_per_bar();
|
||||
}
|
||||
if (m == section){
|
||||
section->set_frame (frame_at_pulse_locked (imaginary, pulse));
|
||||
b_bbt = make_pair (pulse, BBT_Time (accumulated_bars + 1, 1, 0));
|
||||
section->set_pulse (b_bbt);
|
||||
m->set_beat (accumulated_beats);
|
||||
prev_ms = section;
|
||||
continue;
|
||||
}
|
||||
if (prev_ms) {
|
||||
if (m->position_lock_style() == MusicTime) {
|
||||
m->set_frame (frame_at_pulse_locked (imaginary, m->pulse()));
|
||||
} else {
|
||||
pair<double, BBT_Time> b_bbt = make_pair (pulse_at_frame_locked (imaginary, m->frame()), BBT_Time (1, 1, 0));
|
||||
b_bbt.second = beats_to_bbt_locked (imaginary, beat_at_pulse (imaginary, b_bbt.first));
|
||||
pair<double, BBT_Time> b_bbt = make_pair (pulse_at_frame_locked (imaginary, m->frame()), BBT_Time (accumulated_bars + 1, 1, 0));
|
||||
m->set_pulse (b_bbt);
|
||||
}
|
||||
}
|
||||
m->set_beat (accumulated_beats);
|
||||
prev_ms = m;
|
||||
}
|
||||
}
|
||||
@@ -2107,33 +2122,43 @@ void
|
||||
TempoMap::solve_map (Metrics& imaginary, MeterSection* section, const Meter& mt, const framepos_t& frame)
|
||||
{
|
||||
MeterSection* prev_ms = 0;
|
||||
double accumulated_beats = 0.0;
|
||||
uint32_t accumulated_bars = 0;
|
||||
|
||||
section->set_frame (frame);
|
||||
|
||||
for (Metrics::iterator i = imaginary.begin(); i != imaginary.end(); ++i) {
|
||||
MeterSection* m;
|
||||
if ((m = dynamic_cast<MeterSection*> (*i)) != 0) {
|
||||
if (prev_ms) {
|
||||
if (m == section){
|
||||
const double beats_in_m = (m->pulse() - prev_ms->pulse()) * prev_ms->note_divisor();
|
||||
accumulated_beats += beats_in_m;
|
||||
accumulated_bars += (beats_in_m + 1) / prev_ms->divisions_per_bar();
|
||||
}
|
||||
if (m == section){
|
||||
/*
|
||||
here we define the pulse 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 pulses to keep us sane)
|
||||
*/
|
||||
double const pulse_at_f = ceil (pulse_at_frame_locked (imaginary, m->frame()));
|
||||
pair<double, BBT_Time> b_bbt = make_pair (pulse_at_f, beats_to_bbt_locked (imaginary, beat_at_pulse (imaginary, pulse_at_f)));
|
||||
double const pulse_at_f = pulse_at_frame_locked (imaginary, m->frame());
|
||||
pair<double, BBT_Time> b_bbt = make_pair (pulse_at_f, BBT_Time (accumulated_bars + 1, 1, 0));
|
||||
m->set_pulse (b_bbt);
|
||||
m->set_beat (accumulated_beats);
|
||||
prev_ms = m;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (prev_ms) {
|
||||
if (m->position_lock_style() == MusicTime) {
|
||||
m->set_frame (frame_at_pulse_locked (imaginary, m->pulse()));
|
||||
} else {
|
||||
double const pulse_at_f = ceil (pulse_at_frame_locked (imaginary, frame));
|
||||
pair<double, BBT_Time> b_bbt = make_pair (pulse_at_f, beats_to_bbt_locked (imaginary, beat_at_pulse (imaginary, pulse_at_f)));
|
||||
pair<double, BBT_Time> b_bbt = make_pair (pulse_at_f, BBT_Time (accumulated_bars + 1, 1, 0));
|
||||
m->set_pulse (b_bbt);
|
||||
}
|
||||
}
|
||||
m->set_beat (accumulated_beats);
|
||||
prev_ms = m;
|
||||
}
|
||||
}
|
||||
@@ -2619,19 +2644,19 @@ TempoMap::dump (Metrics& metrics, std::ostream& o) const
|
||||
|
||||
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->pulse() << " frame= " << t->frame() << " (movable? "
|
||||
<< t->movable() << ')' << endl;
|
||||
<< t->movable() << ')' << " pos lock: " << enum_2_string (t->position_lock_style()) << std::endl;
|
||||
o << "current : " << t->beats_per_minute() << " | " << t->pulse() << " | " << t->frame() << std::endl;
|
||||
if (prev_ts) {
|
||||
o << "current : " << t->beats_per_minute() << " | " << t->pulse() << " | " << t->frame() << std::endl;
|
||||
o << "previous : " << prev_ts->beats_per_minute() << " | " << prev_ts->pulse() << " | " << prev_ts->frame() << std::endl;
|
||||
o << "calculated : " << prev_ts->tempo_at_pulse (t->pulse()) << " | " << prev_ts->pulse_at_tempo (t->pulses_per_minute(), t->frame(), _frame_rate) << " | " << prev_ts->frame_at_tempo (t->pulses_per_minute(), t->pulse(), _frame_rate) << std::endl;
|
||||
o << "------" << std::endl;
|
||||
o << "calculated : " << prev_ts->tempo_at_pulse (t->pulse()) * prev_ts->note_type() << " | " << prev_ts->pulse_at_tempo (t->pulses_per_minute(), t->frame(), _frame_rate) << " | " << prev_ts->frame_at_tempo (t->pulses_per_minute(), t->pulse(), _frame_rate) << std::endl;
|
||||
}
|
||||
prev_ts = t;
|
||||
} 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;
|
||||
<< " pulse: " << m->pulse() << " pos lock: " << enum_2_string (m->position_lock_style()) << " (movable? " << m->movable() << ')' << endl;
|
||||
}
|
||||
prev_ts = t;
|
||||
}
|
||||
o << "------" << std::endl;
|
||||
}
|
||||
|
||||
int
|
||||
|
||||
Reference in New Issue
Block a user