double pulse;
uint32_t frame;
+ _legacy_bbt = BBT_Time (0, 0, 0);
+
if ((prop = node.property ("start")) != 0) {
if (sscanf (prop->value().c_str(), "%" PRIu32 "|%" PRIu32 "|%" PRIu32,
&bbt.bars,
/* legacy session - start used to be in bbt*/
_legacy_bbt = bbt;
pulse = -1.0;
- set_pulse (pulse);
+ info << _("Legacy session detected. TempoSection XML node will be altered.") << endmsg;
}
- } else {
- warning << _("TempoSection XML node has no \"start\" property") << endmsg;
}
-
if ((prop = node.property ("pulse")) != 0) {
- if (sscanf (prop->value().c_str(), "%lf", &pulse) != 1 || pulse < 0.0) {
- error << _("TempoSection XML node has an illegal \"beat\" value") << endmsg;
- } else {
- set_pulse (pulse);
+ if (sscanf (prop->value().c_str(), "%lf", &pulse) != 1) {
+ error << _("TempoSection XML node has an illegal \"pulse\" value") << endmsg;
}
}
+
+ set_pulse (pulse);
+
if ((prop = node.property ("frame")) != 0) {
if (sscanf (prop->value().c_str(), "%" PRIu32, &frame) != 1) {
error << _("TempoSection XML node has an illegal \"frame\" value") << endmsg;
}
if ((prop = node.property ("lock-style")) == 0) {
- set_position_lock_style (MusicTime);
+ if (movable()) {
+ set_position_lock_style (MusicTime);
+ } else {
+ set_position_lock_style (AudioTime);
+ }
} else {
set_position_lock_style (PositionLockStyle (string_2_enum (prop->value(), position_lock_style())));
}
TempoSection::tempo_at_frame (const framepos_t& f, const framecnt_t& frame_rate) const
{
- if (_type == Constant) {
+ if (_type == Constant || _c_func == 0.0) {
return pulses_per_minute();
}
framepos_t
TempoSection::frame_at_tempo (const double& ppm, const double& b, const framecnt_t& frame_rate) const
{
- if (_type == Constant) {
+ if (_type == Constant || _c_func == 0.0) {
return ((b - pulse()) * frames_per_pulse (frame_rate)) + frame();
}
TempoSection::tempo_at_pulse (const double& p) const
{
- if (_type == Constant) {
+ if (_type == Constant || _c_func == 0.0) {
return pulses_per_minute();
}
double const ppm = pulse_tempo_at_pulse (p - pulse());
double
TempoSection::pulse_at_tempo (const double& ppm, const framepos_t& f, const framecnt_t& frame_rate) const
{
- if (_type == Constant) {
+ if (_type == Constant || _c_func == 0.0) {
double const pulses = ((f - frame()) / frames_per_pulse (frame_rate)) + pulse();
return pulses;
}
double
TempoSection::pulse_at_frame (const framepos_t& f, const framecnt_t& frame_rate) const
{
- if (_type == Constant) {
+ if (_type == Constant || _c_func == 0.0) {
return ((f - frame()) / frames_per_pulse (frame_rate)) + pulse();
}
framepos_t
TempoSection::frame_at_pulse (const double& p, const framecnt_t& frame_rate) const
{
- if (_type == Constant) {
+ if (_type == Constant || _c_func == 0.0) {
return (framepos_t) floor ((p - pulse()) * frames_per_pulse (frame_rate)) + frame();
}
error << _("MeterSection XML node has an illegal \"start\" value") << endmsg;
} else {
/* legacy session - start used to be in bbt*/
+ info << _("Legacy session detected - MeterSection XML node will be altered.") << endmsg;
pulse = -1.0;
}
- } else {
- error << _("MeterSection XML node has no \"start\" property") << endmsg;
}
if ((prop = node.property ("pulse")) != 0) {
- if (sscanf (prop->value().c_str(), "%lf", &pulse) != 1 || pulse < 0.0) {
+ if (sscanf (prop->value().c_str(), "%lf", &pulse) != 1) {
error << _("MeterSection XML node has an illegal \"pulse\" value") << endmsg;
}
}
if ((prop = node.property ("beat")) != 0) {
if (sscanf (prop->value().c_str(), "%lf", &beat) != 1) {
- error << _("MeterSection XML node has an illegal \"beat\" vlue") << endmsg;
+ error << _("MeterSection XML node has an illegal \"beat\" value") << endmsg;
}
}
start.first = beat;
if ((prop = node.property ("bbt")) == 0) {
- error << _("MeterSection XML node has no \"bbt\" property") << endmsg;
+ warning << _("MeterSection XML node has no \"bbt\" property") << endmsg;
} else if (sscanf (prop->value().c_str(), "%" PRIu32 "|%" PRIu32 "|%" PRIu32,
&bbt.bars,
&bbt.beats,
&bbt.ticks) < 3) {
error << _("MeterSection XML node has an illegal \"bbt\" value") << endmsg;
- //throw failed_constructor();
+ throw failed_constructor();
}
start.second = bbt;
throw failed_constructor();
}
- if ((prop = node.property ("lock-style")) == 0) {
- warning << _("MeterSection XML node has no \"lock-style\" property") << endmsg;
- set_position_lock_style (MusicTime);
- } else {
- set_position_lock_style (PositionLockStyle (string_2_enum (prop->value(), position_lock_style())));
- }
-
if ((prop = node.property ("movable")) == 0) {
error << _("MeterSection XML node has no \"movable\" property") << endmsg;
throw failed_constructor();
}
set_movable (string_is_affirmative (prop->value()));
+
+ if ((prop = node.property ("lock-style")) == 0) {
+ warning << _("MeterSection XML node has no \"lock-style\" property") << endmsg;
+ if (movable()) {
+ set_position_lock_style (MusicTime);
+ } else {
+ set_position_lock_style (AudioTime);
+ }
+ } else {
+ set_position_lock_style (PositionLockStyle (string_2_enum (prop->value(), position_lock_style())));
+ }
}
XMLNode&
BBT_Time start (1, 1, 0);
TempoSection *t = new TempoSection (0.0, _default_tempo.beats_per_minute(), _default_tempo.note_type(), TempoSection::Constant);
- MeterSection *m = new MeterSection (0.0, 0.0, start, _default_meter.divisions_per_bar(), _default_meter.note_divisor());
+ MeterSection *m = new MeterSection ((framepos_t) 0, 0.0, start, _default_meter.divisions_per_bar(), _default_meter.note_divisor());
t->set_movable (false);
m->set_movable (false);
*/
*(dynamic_cast<Meter*>(*i)) = *(dynamic_cast<Meter*>(insert_meter));
- (*i)->set_position_lock_style (insert_meter->position_lock_style());
+ (*i)->set_position_lock_style (AudioTime);
need_add = false;
} else {
_metrics.erase (i);
PropertyChanged (PropertyChange ());
}
-void
+TempoSection*
TempoMap::add_tempo (const Tempo& tempo, const double& pulse, ARDOUR::TempoSection::Type type)
{
+ TempoSection* ts = 0;
{
Glib::Threads::RWLock::WriterLock lm (lock);
- add_tempo_locked (tempo, pulse, true, type);
+ ts = add_tempo_locked (tempo, pulse, true, type);
}
PropertyChanged (PropertyChange ());
+
+ return ts;
}
-void
+TempoSection*
TempoMap::add_tempo (const Tempo& tempo, const framepos_t& frame, ARDOUR::TempoSection::Type type)
{
+ TempoSection* ts = 0;
{
Glib::Threads::RWLock::WriterLock lm (lock);
- add_tempo_locked (tempo, frame, true, type);
+ ts = add_tempo_locked (tempo, frame, true, type);
}
PropertyChanged (PropertyChange ());
+
+ return ts;
}
-void
+TempoSection*
TempoMap::add_tempo_locked (const Tempo& tempo, double pulse, bool recompute, ARDOUR::TempoSection::Type type)
{
- TempoSection* ts = new TempoSection (pulse, tempo.beats_per_minute(), tempo.note_type(), type);
+ TempoSection* t = new TempoSection (pulse, tempo.beats_per_minute(), tempo.note_type(), type);
- do_insert (ts);
+ do_insert (t);
if (recompute) {
- solve_map (_metrics, ts, ts->pulse());
+ solve_map (_metrics, t, t->pulse());
}
+
+ return t;
}
-void
+TempoSection*
TempoMap::add_tempo_locked (const Tempo& tempo, framepos_t frame, bool recompute, ARDOUR::TempoSection::Type type)
{
- TempoSection* ts = new TempoSection (frame, tempo.beats_per_minute(), tempo.note_type(), type);
+ TempoSection* t = new TempoSection (frame, tempo.beats_per_minute(), tempo.note_type(), type);
- do_insert (ts);
+ do_insert (t);
if (recompute) {
- solve_map (_metrics, ts, ts->frame());
+ solve_map (_metrics, t, t->frame());
}
+
+ return t;
}
void
add_meter_locked (meter, bbt_to_beats_locked (_metrics, where), where, true);
} else {
MeterSection& first (first_meter());
- const PositionLockStyle pl = ms.position_lock_style();
/* cannot move the first meter section */
*static_cast<Meter*>(&first) = meter;
- first.set_position_lock_style (pl);
+ first.set_position_lock_style (AudioTime);
}
recompute_map (_metrics);
}
#endif
PropertyChanged (PropertyChange ());
- dump (_metrics, std::cerr);
+
return m;
}
MeterSection*
TempoMap::add_meter_locked (const Meter& meter, framepos_t frame, double beat, Timecode::BBT_Time where, bool recompute)
{
-
MeterSection* new_meter = new MeterSection (frame, beat, where, meter.divisions_per_bar(), meter.note_divisor());
double pulse = pulse_at_frame_locked (_metrics, frame);
if (!t->active()) {
continue;
}
+ if (!t->movable()) {
+ t->set_pulse (0.0);
+ prev_t = t;
+ continue;
+ }
if (prev_t) {
if (t->position_lock_style() == AudioTime) {
prev_t->set_c_func (prev_t->compute_c_func_frame (t->pulses_per_minute(), t->frame(), _frame_rate));
pair<double, BBT_Time> b_bbt;
if (meter->movable()) {
const double beats = ((pulse_at_frame_locked (metrics, meter->frame()) - prev_m->pulse()) * prev_m->note_divisor());
- const double ceil_beats = beats - fmod (beats, prev_m->divisions_per_bar());
- b_bbt = make_pair (ceil_beats + prev_m->beat(), BBT_Time ((ceil_beats / prev_m->divisions_per_bar()) + prev_m->bbt().bars, 1, 0));
- const double true_pulse = prev_m->pulse() + (ceil_beats / prev_m->note_divisor());
- const double pulse_off = true_pulse - (beats / prev_m->note_divisor());
+ const double floor_beats = beats - fmod (beats, prev_m->divisions_per_bar());
+ b_bbt = make_pair (floor_beats + prev_m->beat(), BBT_Time ((floor_beats / prev_m->divisions_per_bar()) + prev_m->bbt().bars, 1, 0));
+ const double true_pulse = prev_m->pulse() + (floor_beats / prev_m->note_divisor());
+ const double pulse_off = true_pulse - (beats / prev_m->note_divisor()) - prev_m->pulse();
pulse = true_pulse - pulse_off;
} else {
b_bbt = make_pair (0.0, BBT_Time (1, 1, 0));
meter->set_pulse (pulse);
} else {
double pulse = 0.0;
+ pair<double, BBT_Time> new_beat;
if (prev_m) {
- pulse = prev_m->pulse() + (meter->beat() - prev_m->beat()) / prev_m->note_divisor();
+ pulse = prev_m->pulse() + ((meter->bbt().bars - prev_m->bbt().bars) * prev_m->divisions_per_bar() / prev_m->note_divisor());
+ new_beat = make_pair (((pulse - prev_m->pulse()) * prev_m->note_divisor()) + prev_m->beat(), meter->bbt());
} else {
+ /* shouldn't happen - the first is audio-locked */
pulse = pulse_at_beat_locked (metrics, meter->beat());
+ new_beat = make_pair (pulse, meter->bbt());
}
+
+ meter->set_beat (new_beat);
meter->set_frame (frame_at_pulse_locked (metrics, pulse));
meter->set_pulse (pulse);
}
prev_m = meter;
}
}
+ //dump (_metrics, std::cerr;
}
void
return m;
}
-double
-TempoMap::pulse_at_frame_locked (const Metrics& metrics, const framecnt_t& frame) const
-{
- /* HOLD (at least) THE READER LOCK */
- TempoSection* prev_t = 0;
- double accumulated_pulses = 0.0;
-
- for (Metrics::const_iterator 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) {
- /*the previous ts is the one containing the frame */
- const double ret = prev_t->pulse_at_frame (frame, _frame_rate);
- return ret;
- }
- accumulated_pulses = t->pulse();
- prev_t = t;
- }
- }
-
- /* treated as constant for this ts */
- const double pulses_in_section = (frame - prev_t->frame()) / prev_t->frames_per_pulse (_frame_rate);
-
- return pulses_in_section + accumulated_pulses;
-}
-
double
TempoMap::pulse_at_beat_locked (const Metrics& metrics, const double& beat) const
{
MeterSection* prev_m = 0;
- double accumulated_beats = 0.0;
for (Metrics::const_iterator i = metrics.begin(); i != metrics.end(); ++i) {
MeterSection* m;
if (prev_m && m->beat() > beat) {
break;
}
- accumulated_beats = m->beat();
prev_m = m;
}
}
- double const ret = prev_m->pulse() + ((beat - accumulated_beats) / prev_m->note_divisor());
+ double const ret = prev_m->pulse() + ((beat - prev_m->beat()) / prev_m->note_divisor());
return ret;
}
TempoMap::beat_at_pulse_locked (const Metrics& metrics, const double& pulse) const
{
MeterSection* prev_m = 0;
- double accumulated_beats = 0.0;
for (Metrics::const_iterator i = metrics.begin(); i != metrics.end(); ++i) {
MeterSection* m;
if (prev_m && m->pulse() > pulse) {
break;
}
- accumulated_beats = m->beat();
prev_m = m;
}
}
double const beats_in_section = (pulse - prev_m->pulse()) * prev_m->note_divisor();
- return beats_in_section + accumulated_beats;
+ return beats_in_section + prev_m->beat();
}
double
return beat_at_pulse_locked (_metrics, pulse);
}
+double
+TempoMap::pulse_at_frame_locked (const Metrics& metrics, const framecnt_t& frame) const
+{
+ /* HOLD (at least) THE READER LOCK */
+ TempoSection* prev_t = 0;
+
+ for (Metrics::const_iterator 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) {
+ /*the previous ts is the one containing the frame */
+ const double ret = prev_t->pulse_at_frame (frame, _frame_rate);
+ return ret;
+ }
+ prev_t = t;
+ }
+ }
+
+ /* treated as constant for this ts */
+ const double pulses_in_section = (frame - prev_t->frame()) / prev_t->frames_per_pulse (_frame_rate);
+
+ return pulses_in_section + prev_t->pulse();
+}
+
framecnt_t
TempoMap::frame_at_pulse_locked (const Metrics& metrics, const double& pulse) const
{
{
/* CALLER HOLDS READ LOCK */
- double accumulated_beats = 0.0;
- double accumulated_bars = 0.0;
MeterSection* prev_m = 0;
/* because audio-locked meters have 'fake' integral beats,
if ((m = dynamic_cast<MeterSection*> (*i)) != 0) {
if (prev_m) {
const double bars_to_m = (m->beat() - prev_m->beat()) / prev_m->divisions_per_bar();
- if ((bars_to_m + accumulated_bars) > (bbt.bars - 1)) {
+ if ((bars_to_m + (prev_m->bbt().bars - 1)) > (bbt.bars - 1)) {
break;
}
- accumulated_beats = m->beat();
- accumulated_bars += bars_to_m;
}
prev_m = m;
}
}
- const double remaining_bars = (bbt.bars - 1) - accumulated_bars;
+ const double remaining_bars = bbt.bars - prev_m->bbt().bars;
const double remaining_bars_in_beats = remaining_bars * prev_m->divisions_per_bar();
- const double ret = remaining_bars_in_beats + accumulated_beats + (bbt.beats - 1) + (bbt.ticks / BBT_Time::ticks_per_beat);
+ const double ret = remaining_bars_in_beats + prev_m->beat() + (bbt.beats - 1) + (bbt.ticks / BBT_Time::ticks_per_beat);
return ret;
}
/* CALLER HOLDS READ LOCK */
MeterSection* prev_m = 0;
const double beats = (b < 0.0) ? 0.0 : b;
- uint32_t accumulated_bars = 0;
- double accumulated_beats = 0.0;
for (Metrics::const_iterator i = metrics.begin(); i != metrics.end(); ++i) {
MeterSection* m = 0;
/* this is the meter after the one our beat is on*/
break;
}
- const double beats_to_m = m->beat() - prev_m->beat();
- /* we need a whole number of bars. */
- accumulated_bars += (beats_to_m + 1) / prev_m->divisions_per_bar();
- accumulated_beats += beats_to_m;
}
prev_m = m;
}
}
- const double beats_in_ms = beats - accumulated_beats;
+ const double beats_in_ms = beats - prev_m->beat();
const uint32_t bars_in_ms = (uint32_t) floor (beats_in_ms / prev_m->divisions_per_bar());
- const uint32_t total_bars = bars_in_ms + accumulated_bars;
+ const uint32_t total_bars = bars_in_ms + (prev_m->bbt().bars - 1);
const double remaining_beats = beats_in_ms - (bars_in_ms * prev_m->divisions_per_bar());
const double remaining_ticks = (remaining_beats - floor (remaining_beats)) * BBT_Time::ticks_per_beat;
{
Glib::Threads::RWLock::ReaderLock lm (lock);
MeterSection* prev_m = 0;
- uint32_t accumulated_bars = 0;
- double accumulated_pulses = 0.0;
for (Metrics::const_iterator i = _metrics.begin(); i != _metrics.end(); ++i) {
MeterSection* m = 0;
if (prev_m) {
double const pulses_to_m = m->pulse() - prev_m->pulse();
- if (accumulated_pulses + pulses_to_m > pulse) {
+ if (prev_m->pulse() + pulses_to_m > pulse) {
/* this is the meter after the one our beat is on*/
break;
}
-
- /* we need a whole number of bars. */
- accumulated_pulses += pulses_to_m;
- accumulated_bars += ((pulses_to_m * prev_m->note_divisor()) + 1) / prev_m->divisions_per_bar();
}
prev_m = m;
}
}
+
const double beats_in_ms = (pulse - prev_m->pulse()) * prev_m->note_divisor();
const uint32_t bars_in_ms = (uint32_t) floor (beats_in_ms / prev_m->divisions_per_bar());
- const uint32_t total_bars = bars_in_ms + accumulated_bars;
+ const uint32_t total_bars = bars_in_ms + (prev_m->bbt().bars - 1);
const double remaining_beats = beats_in_ms - (bars_in_ms * prev_m->divisions_per_bar());
const double remaining_ticks = (remaining_beats - floor (remaining_beats)) * BBT_Time::ticks_per_beat;
throw std::logic_error ("beats are counted from one");
}
Glib::Threads::RWLock::ReaderLock lm (lock);
- const double beat = bbt_to_beats_locked (_metrics, bbt);
- const framecnt_t frame = frame_at_beat_locked (_metrics, beat);
- return frame;
+ return frame_time_locked (_metrics, bbt);
}
bool
return false;
}
- /* precision check ensures pulses and frames align independent of lock style.*/
- if (by_frame && t->frame() != prev_t->frame_at_pulse (t->pulse(), _frame_rate)) {
+ /* precision check ensures pulses and frames align.*/
+ if (t->frame() != prev_t->frame_at_pulse (t->pulse(), _frame_rate)) {
return false;
}
}
}
if (section->movable() && frame <= first_m_frame) {
return false;
- } else {
- section->set_active (true);
}
+
+ section->set_active (true);
section->set_frame (frame);
for (Metrics::iterator i = imaginary.begin(); i != imaginary.end(); ++i) {
} else {
recompute_tempos (imaginary);
}
+
if (check_solved (imaginary, true)) {
recompute_meters (imaginary);
return true;
}
-
+#if (0)
MetricSectionSorter cmp;
imaginary.sort (cmp);
if (section->position_lock_style() == MusicTime) {
} else {
recompute_tempos (imaginary);
}
+
if (check_solved (imaginary, true)) {
recompute_meters (imaginary);
return true;
}
+#endif
//dump (imaginary, std::cerr);
return false;
if (!t->active()) {
continue;
}
+ if (!t->movable()) {
+ t->set_pulse (0.0);
+ prev_t = t;
+ continue;
+ }
if (prev_t) {
if (t == section) {
section_prev = prev_t;
} else {
recompute_tempos (imaginary);
}
+
if (check_solved (imaginary, false)) {
recompute_meters (imaginary);
return true;
recompute_meters (imaginary);
return true;
}
-
+#if (0)
MetricSectionFrameSorter fcmp;
imaginary.sort (fcmp);
if (section->position_lock_style() == AudioTime) {
recompute_meters (imaginary);
return true;
}
-
+#endif
//dump (imaginary, std::cerr);
return false;
if (m == section){
/*
here we set the beat for this frame.
- we set it 'incorrectly' to the next bar's beat
- and use this difference to find the meter's pulse.
+ we set it 'incorrectly' to the next bar's first beat
+ and use the delat to find the meter's pulse.
*/
- double pulse = 0.0;
+ double new_pulse = 0.0;
pair<double, BBT_Time> b_bbt;
- if (m->movable()) {
+
+ if (section->movable()) {
const double beats = ((pulse_at_frame_locked (imaginary, frame) - prev_m->pulse()) * prev_m->note_divisor());
- const double ceil_beats = beats - fmod (beats, prev_m->divisions_per_bar());
- b_bbt = make_pair (ceil_beats + prev_m->beat(), BBT_Time ((ceil_beats / prev_m->divisions_per_bar()) + prev_m->bbt().bars, 1, 0));
- const double true_pulse = prev_m->pulse() + (ceil_beats / prev_m->note_divisor());
- const double pulse_off = true_pulse - (beats / prev_m->note_divisor());
- pulse = true_pulse - pulse_off;
+ const double floor_beats = beats - fmod (beats, prev_m->divisions_per_bar());
+ b_bbt = make_pair (floor_beats + prev_m->beat(), BBT_Time ((floor_beats / prev_m->divisions_per_bar()) + prev_m->bbt().bars, 1, 0));
+ const double true_pulse = prev_m->pulse() + (floor_beats / prev_m->note_divisor());
+ const double pulse_off = true_pulse - (beats / prev_m->note_divisor()) - prev_m->pulse();
+ new_pulse = true_pulse - pulse_off;
} else {
b_bbt = make_pair (0.0, BBT_Time (1, 1, 0));
}
- m->set_beat (b_bbt);
- m->set_pulse (pulse);
+
+ section->set_beat (b_bbt);
+ section->set_pulse (new_pulse);
prev_m = m;
+
continue;
}
if (prev_m) {
+ double new_pulse = 0.0;
if (m->position_lock_style() == MusicTime) {
- const double pulse = prev_m->pulse() + (m->beat() - prev_m->beat()) / prev_m->note_divisor();
- m->set_frame (frame_at_pulse_locked (imaginary, pulse));
- m->set_pulse (pulse);
+ new_pulse = prev_m->pulse() + ((m->bbt().bars - prev_m->bbt().bars) * prev_m->divisions_per_bar() / prev_m->note_divisor());
+ m->set_frame (frame_at_pulse_locked (imaginary, new_pulse));
+ if (m->frame() > section->frame()) {
+ /* moving 'section' will affect later meters' beat (but not bbt).*/
+ pair<double, BBT_Time> new_beat (((new_pulse - prev_m->pulse()) * prev_m->note_divisor()) + prev_m->beat(), m->bbt());
+ m->set_beat (new_beat);
+ }
} else {
- double pulse = 0.0;
pair<double, BBT_Time> b_bbt;
if (m->movable()) {
const double beats = ((pulse_at_frame_locked (imaginary, m->frame()) - prev_m->pulse()) * prev_m->note_divisor());
- const double ceil_beats = beats - fmod (beats , prev_m->divisions_per_bar());
- b_bbt = make_pair (ceil_beats + prev_m->beat(), BBT_Time ((ceil_beats / prev_m->divisions_per_bar()) + prev_m->bbt().bars, 1, 0));
- const double true_pulse = prev_m->pulse() + (ceil_beats / prev_m->note_divisor());
- const double pulse_off = true_pulse - (beats / prev_m->note_divisor());
- pulse = true_pulse - pulse_off;
+ const double floor_beats = beats - fmod (beats , prev_m->divisions_per_bar());
+ b_bbt = make_pair (floor_beats + prev_m->beat()
+ , BBT_Time ((floor_beats / prev_m->divisions_per_bar()) + prev_m->bbt().bars, 1, 0));
+ const double true_pulse = prev_m->pulse() + (floor_beats / prev_m->note_divisor());
+ const double pulse_off = true_pulse - (beats / prev_m->note_divisor()) - prev_m->pulse();
+ new_pulse = true_pulse - pulse_off;
} else {
b_bbt = make_pair (0.0, BBT_Time (1, 1, 0));
- pulse = 0.0;
+ new_pulse = 0.0;
}
m->set_beat (b_bbt);
- m->set_pulse (pulse);
}
+ m->set_pulse (new_pulse);
}
prev_m = m;
}
}
+ MetricSectionFrameSorter fcmp;
+ imaginary.sort (fcmp);
if (section->position_lock_style() == MusicTime) {
/* we're setting the frame */
section->set_position_lock_style (AudioTime);
TempoMap::solve_map (Metrics& imaginary, MeterSection* section, const double& pulse)
{
MeterSection* prev_m = 0;
+ MeterSection* section_prev = 0;
section->set_pulse (pulse);
MeterSection* m;
if ((m = dynamic_cast<MeterSection*> (*i)) != 0) {
if (m == section){
- section->set_frame (frame_at_pulse_locked (imaginary, pulse));
- const double beats = ((pulse - prev_m->pulse()) * prev_m->note_divisor());
- const int32_t bars = (beats + 1) / prev_m->divisions_per_bar();
- pair<double, BBT_Time> b_bbt = make_pair (beats + prev_m->beat(), BBT_Time (bars + prev_m->bbt().bars, 1, 0));
- section->set_beat (b_bbt);
- prev_m = section;
+ section_prev = prev_m;
continue;
}
if (prev_m) {
- double pulse = 0.0;
+ double new_pulse = 0.0;
if (m->position_lock_style() == MusicTime) {
- pulse = prev_m->pulse() + (m->beat() - prev_m->beat()) / prev_m->note_divisor();
- m->set_frame (frame_at_pulse_locked (imaginary, pulse));
+ new_pulse = prev_m->pulse() + ((m->bbt().bars - prev_m->bbt().bars) * prev_m->divisions_per_bar() / prev_m->note_divisor());
+ m->set_frame (frame_at_pulse_locked (imaginary, new_pulse));
+
+ if (new_pulse > section->pulse()) {
+ /* moving 'section' will affect later meters' beat (but not bbt).*/
+ pair<double, BBT_Time> new_beat (((new_pulse - prev_m->pulse()) * prev_m->note_divisor()) + prev_m->beat(), m->bbt());
+ m->set_beat (new_beat);
+ }
} else {
pair<double, BBT_Time> b_bbt;
if (m->movable()) {
const double beats = ((pulse_at_frame_locked (imaginary, m->frame()) - prev_m->pulse()) * prev_m->note_divisor());
- const double ceil_beats = beats - fmod (beats, prev_m->divisions_per_bar());
- b_bbt = make_pair (ceil_beats + prev_m->beat(), BBT_Time ((ceil_beats / prev_m->divisions_per_bar()) + prev_m->bbt().bars, 1, 0));
- const double true_pulse = prev_m->pulse() + (ceil_beats / prev_m->note_divisor());
- const double pulse_off = true_pulse - (beats / prev_m->note_divisor());
- pulse = true_pulse - pulse_off;
+ const double floor_beats = beats - fmod (beats, prev_m->divisions_per_bar());
+ b_bbt = make_pair (floor_beats + prev_m->beat()
+ , BBT_Time ((floor_beats / prev_m->divisions_per_bar()) + prev_m->bbt().bars, 1, 0));
+ const double true_pulse = prev_m->pulse() + (floor_beats / prev_m->note_divisor());
+ const double pulse_off = true_pulse - (beats / prev_m->note_divisor()) - prev_m->pulse();
+ new_pulse = true_pulse - pulse_off;
} else {
b_bbt = make_pair (0.0, BBT_Time (1, 1, 0));
}
m->set_beat (b_bbt);
}
- m->set_pulse (pulse);
+ m->set_pulse (new_pulse);
}
prev_m = m;
}
}
+ if (section_prev) {
+ const double beats = ((pulse - section_prev->pulse()) * section_prev->note_divisor());
+ const int32_t bars = (beats + 1) / section_prev->divisions_per_bar();
+ pair<double, BBT_Time> b_bbt = make_pair (beats + section_prev->beat(), BBT_Time (bars + section_prev->bbt().bars, 1, 0));
+ section->set_beat (b_bbt);
+ section->set_frame (frame_at_pulse_locked (imaginary, pulse));
+ }
+
+ MetricSectionSorter cmp;
+ imaginary.sort (cmp);
if (section->position_lock_style() == AudioTime) {
/* we're setting the pulse */
section->set_position_lock_style (MusicTime);
}
/** places a copy of _metrics into copy and returns a pointer
- * to section's equivalent.
+ * to section's equivalent in copy.
*/
TempoSection*
TempoMap::copy_metrics_and_point (Metrics& copy, TempoSection* section)
{
TempoSection* t;
- TempoSection* ret = 0;
MeterSection* m;
+ TempoSection* ret = 0;
for (Metrics::iterator i = _metrics.begin(); i != _metrics.end(); ++i) {
if ((t = dynamic_cast<TempoSection*> (*i)) != 0) {
if (t == section) {
if (t->position_lock_style() == MusicTime) {
ret = new TempoSection (t->pulse(), t->beats_per_minute(), t->note_type(), t->type());
+ ret->set_frame (t->frame());
} else {
ret = new TempoSection (t->frame(), t->beats_per_minute(), t->note_type(), t->type());
+ ret->set_pulse (t->pulse());
}
ret->set_active (t->active());
ret->set_movable (t->movable());
TempoSection* cp = 0;
if (t->position_lock_style() == MusicTime) {
cp = new TempoSection (t->pulse(), t->beats_per_minute(), t->note_type(), t->type());
+ cp->set_frame (t->frame());
} else {
cp = new TempoSection (t->frame(), t->beats_per_minute(), t->note_type(), t->type());
+ cp->set_pulse (t->pulse());
}
cp->set_active (t->active());
cp->set_movable (t->movable());
copy.push_back (cp);
}
}
- //recompute_map (copy);
+
return ret;
}
TempoSection* new_section = copy_metrics_and_point (future_map, section);
const double beat = bbt_to_beats_locked (future_map, bbt);
+
if (solve_map (future_map, new_section, pulse_at_beat_locked (future_map, beat))) {
ret = new_section->frame();
} else {
const double tick_at_time = beat_at_frame_locked (_metrics, pos) * BBT_Time::ticks_per_beat;
const double bbt_ticks = bbt.ticks + (bbt.beats * BBT_Time::ticks_per_beat);
const double total_beats = (tick_at_time + bbt_ticks) / BBT_Time::ticks_per_beat;
- const framecnt_t time_at_bbt = frame_at_beat_locked (_metrics, total_beats);
- const framecnt_t ret = time_at_bbt;
- return ret;
+ return frame_at_beat_locked (_metrics, total_beats);
}
framepos_t
/* find bar previous to 'frame' */
bbt.beats = 1;
bbt.ticks = 0;
- return frame_time (bbt);
+ return frame_time_locked (_metrics, bbt);
} else if (dir > 0) {
/* find bar following 'frame' */
++bbt.bars;
bbt.beats = 1;
bbt.ticks = 0;
- return frame_time (bbt);
+ return frame_time_locked (_metrics, bbt);
} else {
/* true rounding: find nearest bar */
- framepos_t raw_ft = frame_time (bbt);
+ framepos_t raw_ft = frame_time_locked (_metrics, bbt);
bbt.beats = 1;
bbt.ticks = 0;
- framepos_t prev_ft = frame_time (bbt);
+ framepos_t prev_ft = frame_time_locked (_metrics, bbt);
++bbt.bars;
- framepos_t next_ft = frame_time (bbt);
+ framepos_t next_ft = frame_time_locked (_metrics, bbt);
if ((raw_ft - prev_ft) > (next_ft - prev_ft) / 2) {
return next_ft;
const TempoSection tempo = tempo_section_at_locked (pos);
const MeterSection meter = meter_section_at_locked (pos);
const BBT_Time bbt = beats_to_bbt (cnt);
- points.push_back (BBTPoint (meter, tempo_at_locked (pos), pos, bbt.bars, bbt.beats, tempo.get_c_func()));
+ points.push_back (BBTPoint (meter, tempo_at_locked (pos), pos, bbt.bars, bbt.beats, tempo.c_func()));
++cnt;
}
}
}
if ((prev_t) && t->frame() > frame) {
/* t is the section past frame */
- const double ret = prev_t->tempo_at_frame (frame, _frame_rate) * prev_t->note_type();
- const Tempo ret_tempo (ret, prev_t->note_type());
+ 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 MeterSection&
TempoMap::meter_section_at_locked (framepos_t frame) const
{
- //framepos_t const frame_off = frame + frame_offset_at (_metrics, frame);
Metrics::const_iterator i;
MeterSection* prev = 0;
return *prev_m;
}
+void
+TempoMap::fix_legacy_session ()
+{
+ MeterSection* prev_m = 0;
+ TempoSection* prev_t = 0;
+
+ for (Metrics::iterator i = _metrics.begin(); i != _metrics.end(); ++i) {
+ MeterSection* m;
+ TempoSection* t;
+
+ if ((m = dynamic_cast<MeterSection*>(*i)) != 0) {
+ if (!m->movable()) {
+ pair<double, BBT_Time> bbt = make_pair (0.0, BBT_Time (1, 1, 0));
+ m->set_beat (bbt);
+ m->set_pulse (0.0);
+ m->set_frame (0);
+ m->set_position_lock_style (AudioTime);
+ prev_m = m;
+ continue;
+ }
+ if (prev_m) {
+ pair<double, BBT_Time> start = make_pair (((m->bbt().bars - 1) * prev_m->note_divisor())
+ + (m->bbt().beats - 1)
+ + (m->bbt().ticks / BBT_Time::ticks_per_beat)
+ , m->bbt());
+ m->set_beat (start);
+ const double start_beat = ((m->bbt().bars - 1) * prev_m->note_divisor())
+ + (m->bbt().beats - 1)
+ + (m->bbt().ticks / BBT_Time::ticks_per_beat);
+ m->set_pulse (start_beat / prev_m->note_divisor());
+ }
+ prev_m = m;
+ } else if ((t = dynamic_cast<TempoSection*>(*i)) != 0) {
+
+ if (!t->active()) {
+ continue;
+ }
+
+ if (!t->movable()) {
+ t->set_pulse (0.0);
+ t->set_frame (0);
+ t->set_position_lock_style (AudioTime);
+ prev_t = t;
+ continue;
+ }
+
+ if (prev_t) {
+ const double beat = ((t->legacy_bbt().bars - 1) * ((prev_m) ? prev_m->note_divisor() : 4.0))
+ + (t->legacy_bbt().beats - 1)
+ + (t->legacy_bbt().ticks / BBT_Time::ticks_per_beat);
+ if (prev_m) {
+ t->set_pulse (beat / prev_m->note_divisor());
+ } else {
+ /* really shouldn't happen but.. */
+ t->set_pulse (beat / 4.0);
+ }
+ }
+ prev_t = t;
+ }
+ }
+}
+
XMLNode&
TempoMap::get_state ()
{
MetricSectionSorter cmp;
_metrics.sort (cmp);
}
+
/* check for legacy sessions where bbt was the base musical unit for tempo */
- for (Metrics::iterator i = _metrics.begin(); i != _metrics.end(); ++i) {
- MeterSection* m;
+ for (Metrics::const_iterator i = _metrics.begin(); i != _metrics.end(); ++i) {
TempoSection* t;
- MeterSection* prev_m = 0;
- TempoSection* prev_t = 0;
- if ((m = dynamic_cast<MeterSection*>(*i)) != 0) {
- if (prev_m && prev_m->pulse() < 0.0) {
- /*XX we cannot possibly make this work??. */
- pair<double, BBT_Time> start = make_pair (((prev_m->bbt().bars - 1) * prev_m->note_divisor()) + (prev_m->bbt().beats - 1) + (prev_m->bbt().ticks / BBT_Time::ticks_per_beat), prev_m->bbt());
- prev_m->set_beat (start);
- const double start_pulse = ((prev_m->bbt().bars - 1) * prev_m->note_divisor()) + (prev_m->bbt().beats - 1) + (prev_m->bbt().ticks / BBT_Time::ticks_per_beat);
- prev_m->set_pulse (start_pulse);
- }
- prev_m = m;
- } else if ((t = dynamic_cast<TempoSection*>(*i)) != 0) {
- if (!t->active()) {
- continue;
- }
- if (prev_t && prev_t->pulse() < 0.0) {
- double const start = ((prev_t->legacy_bbt().bars - 1) * prev_m->note_divisor()) + (prev_t->legacy_bbt().beats - 1) + (prev_t->legacy_bbt().ticks / BBT_Time::ticks_per_beat);
- prev_t->set_pulse (start);
+ if ((t = dynamic_cast<TempoSection*> (*i)) != 0) {
+ if (t->legacy_bbt().bars != 0) {
+ fix_legacy_session();
+ break;
}
- prev_t = t;
+ break;
}
}
+
/* check for multiple tempo/meters at the same location, which
ardour2 somehow allowed.
*/