}
_metrics.insert (i, section);
- //dump (_metrics, std::cerr);
+ //dump (_metrics, std::cout);
}
}
}
MeterSection*
-TempoMap::add_meter_locked (const Meter& meter, double beat, BBT_Time where, bool recompute)
+TempoMap::add_meter_locked (const Meter& meter, double beat, const BBT_Time& where, bool recompute)
{
/* a new meter always starts a new bar on the first beat. so
round the start time appropriately. remember that
*/
- if (where.beats != 1) {
- where.beats = 1;
- where.bars++;
- }
- /* new meters *always* start on a beat. */
- where.ticks = 0;
const double pulse = pulse_at_beat_locked (_metrics, beat);
MeterSection* new_meter = new MeterSection (pulse, beat, where, meter.divisions_per_bar(), meter.note_divisor());
+
do_insert (new_meter);
if (recompute) {
}
MeterSection*
-TempoMap::add_meter_locked (const Meter& meter, framepos_t frame, double beat, Timecode::BBT_Time where, bool recompute)
+TempoMap::add_meter_locked (const Meter& meter, framepos_t frame, double beat, const Timecode::BBT_Time& where, bool recompute)
{
+ /* add meter-locked tempo */
+ TempoSection* t = add_tempo_locked (tempo_at_locked (_metrics, frame), frame, true, TempoSection::Ramp);
+ if (t) {
+ t->set_locked_to_meter (true);
+ }
+
MeterSection* new_meter = new MeterSection (frame, beat, where, meter.divisions_per_bar(), meter.note_divisor());
- TempoSection* t = 0;
- double pulse = pulse_at_frame_locked (_metrics, frame);
- new_meter->set_pulse (pulse);
+ new_meter->set_pulse (pulse_at_frame_locked (_metrics, frame));
do_insert (new_meter);
- /* add meter-locked tempo */
- t = add_tempo_locked (tempo_at_locked (_metrics, frame), frame, true, TempoSection::Ramp);
- t->set_locked_to_meter (true);
-
if (recompute) {
solve_map (_metrics, new_meter, frame);
}
}
if (meter_locked_tempo) {
meter_locked_tempo->set_pulse (pulse);
- recompute_tempos (metrics);
}
meter->set_beat (b_bbt);
meter->set_pulse (pulse);
prev_m = meter;
}
}
- //dump (_metrics, std::cerr;
}
void
return true;
}
- //dump (imaginary, std::cerr);
-
return false;
}
return true;
}
- //dump (imaginary, std::cerr);
-
return false;
}
} else {
recompute_meters (imaginary);
}
- //dump (imaginary, std::cerr);
+
return true;
}
for (Metrics::iterator i = imaginary.begin(); i != imaginary.end(); ++i) {
MeterSection* m;
if ((m = dynamic_cast<MeterSection*> (*i)) != 0) {
- if (m->bbt().bars == when.bars) {
+ if (m != section && m->bbt().bars == when.bars) {
return false;
}
}
MetricSectionSorter cmp;
imaginary.sort (cmp);
+
if (section->position_lock_style() == AudioTime) {
/* we're setting the pulse */
section->set_position_lock_style (MusicTime);
MetricPositionChanged (); // Emit Signal
}
-void
-TempoMap::gui_move_tempo_pulse (TempoSection* ts, const double& pulse)
-{
- Metrics future_map;
- {
- Glib::Threads::RWLock::WriterLock lm (lock);
- TempoSection* tempo_copy = copy_metrics_and_point (_metrics, future_map, ts);
- if (solve_map (future_map, tempo_copy, pulse)) {
- solve_map (_metrics, ts, pulse);
- recompute_meters (_metrics);
- }
- }
-
- Metrics::const_iterator d = future_map.begin();
- while (d != future_map.end()) {
- delete (*d);
- ++d;
- }
-
- MetricPositionChanged (); // Emit Signal
-}
-
void
TempoMap::gui_move_meter (MeterSection* ms, const framepos_t& frame)
{
Metrics future_map;
TempoSection* ts = 0;
+ if (frame <= first_meter().frame()) {
+ return;
+ }
+
if (ms->position_lock_style() == AudioTime) {
/* disabled for now due to faked tempo locked to meter pulse */
return;
constant to constant is straightforward, as the tempo prev to prev_t has constant slope.
*/
double contribution = 0.0;
- frameoffset_t frame_contribution = 0.0;
- frameoffset_t prev_t_frame_contribution = 0.0;
+ frameoffset_t frame_contribution = 0;
+ frameoffset_t prev_t_frame_contribution = fr_off;
if (prev_to_prev_t && prev_to_prev_t->type() == TempoSection::Ramp) {
/* prev to prev_t's position will remain constant in terms of frame and pulse. lets use frames. */
new_bpm = prev_t->tempo_at_frame (prev_t->frame() + fr_off, _frame_rate) * (double) prev_t->note_type();
}
- const double diff = (prev_t->tempo_at_frame (frame, _frame_rate) * prev_t->note_type()) - prev_t->beats_per_minute();
- if (diff > -0.1 && diff < 0.1) {
- new_bpm = prev_t->beats_per_minute() * ((ms->frame() - prev_t->frame())
- / (double) ((ms->frame() + prev_t_frame_contribution) - prev_t->frame()));
- }
-
} else if (prev_t->c_func() > 0.0) {
if (prev_to_prev_t && prev_to_prev_t->type() == TempoSection::Ramp) {
new_bpm = prev_t->tempo_at_frame (prev_t->frame() - frame_contribution, _frame_rate) * (double) prev_t->note_type();
/* prev_to_prev_t is irrelevant */
new_bpm = prev_t->tempo_at_frame (prev_t->frame() - fr_off, _frame_rate) * (double) prev_t->note_type();
}
+ }
- /* limits - a bit clunky, but meh */
- const double diff = (prev_t->tempo_at_frame (frame, _frame_rate) * prev_t->note_type()) - prev_t->beats_per_minute();
- if (diff > -0.1 && diff < 0.1) {
- new_bpm = prev_t->beats_per_minute() * ((ms->frame() - prev_t->frame())
- / (double) ((ms->frame() + prev_t_frame_contribution) - prev_t->frame()));
- }
+ /* limits - a bit clunky, but meh */
+ const double diff = (prev_t->tempo_at_frame (frame, _frame_rate) * prev_t->note_type()) - prev_t->beats_per_minute();
+ if (diff > -1.0 && diff < 1.0) {
+ new_bpm = prev_t->beats_per_minute() * ((ms->frame() - prev_t->frame())
+ / (double) ((ms->frame() + prev_t_frame_contribution) - prev_t->frame()));
}
prev_t->set_beats_per_minute (new_bpm);
MetricPositionChanged (); // Emit Signal
}
+void
+TempoMap::gui_dilate_tempo (TempoSection* ts, const framepos_t& frame, const framepos_t& end_frame, const double& pulse)
+{
+ /*
+ Ts (future prev_t) Tnext
+ | |
+ | [drag^] |
+ |----------|----------
+ e_f pulse(frame)
+ */
+
+ Metrics future_map;
+
+ {
+ Glib::Threads::RWLock::WriterLock lm (lock);
+
+ if (!ts) {
+ return;
+ }
+
+ TempoSection* prev_t = copy_metrics_and_point (_metrics, future_map, ts);
+ TempoSection* prev_to_prev_t = 0;
+ const frameoffset_t fr_off = end_frame - frame;
+
+ if (prev_t && prev_t->pulse() > 0.0) {
+ prev_to_prev_t = const_cast<TempoSection*>(&tempo_section_at_locked (future_map, prev_t->frame() - 1));
+ }
+
+ TempoSection* next_t = 0;
+ for (Metrics::iterator i = future_map.begin(); i != future_map.end(); ++i) {
+ TempoSection* t = 0;
+ if ((t = dynamic_cast<TempoSection*> (*i)) != 0) {
+ if (t->frame() > ts->frame()) {
+ next_t = t;
+ break;
+ }
+ }
+ }
+
+ /* the change in frames is the result of changing the slope of at most 2 previous tempo sections.
+ constant to constant is straightforward, as the tempo prev to prev_t has constant slope.
+ */
+ double contribution = 0.0;
+ double start_pulse = prev_t->pulse_at_frame (frame, _frame_rate);
+
+ if (next_t && prev_to_prev_t && prev_to_prev_t->type() == TempoSection::Ramp) {
+ contribution = (prev_t->frame() - prev_to_prev_t->frame()) / (double) (next_t->frame() - prev_to_prev_t->frame());
+ }
+
+ frameoffset_t prev_t_frame_contribution = fr_off - (contribution * (double) fr_off);
+ double end_pulse = prev_t->pulse_at_frame (end_frame, _frame_rate);
+ double new_bpm;
+
+ if (prev_t->type() == TempoSection::Constant || prev_t->c_func() == 0.0) {
+
+ if (prev_t->position_lock_style() == MusicTime) {
+ if (prev_to_prev_t && prev_to_prev_t->type() == TempoSection::Ramp) {
+
+ new_bpm = prev_t->beats_per_minute() * ((frame - prev_to_prev_t->frame())
+ / (double) ((frame + prev_t_frame_contribution) - prev_to_prev_t->frame()));
+
+ } else {
+ /* prev to prev is irrelevant */
+
+ if (start_pulse != prev_t->pulse()) {
+ new_bpm = prev_t->beats_per_minute() * ((start_pulse - prev_t->pulse()) / (end_pulse - prev_t->pulse()));
+ } else {
+ new_bpm = prev_t->beats_per_minute();
+ }
+ }
+ } else {
+ /* AudioTime */
+ if (prev_to_prev_t && prev_to_prev_t->type() == TempoSection::Ramp) {
+ new_bpm = prev_t->beats_per_minute() * ((frame - prev_t->frame())
+ / (double) ((frame + prev_t_frame_contribution) - prev_t->frame()));
+ } else {
+ /* prev_to_prev_t is irrelevant */
+
+ if (end_frame != prev_t->frame()) {
+ new_bpm = prev_t->beats_per_minute() * ((frame - prev_t->frame()) / (double) (end_frame - prev_t->frame()));
+ } else {
+ new_bpm = prev_t->beats_per_minute();
+ }
+ }
+ }
+ } else {
+
+ double frame_ratio;
+ double pulse_ratio;
+ const framepos_t pulse_pos = prev_t->frame_at_pulse (pulse, _frame_rate);
+
+ if (prev_to_prev_t) {
+
+ frame_ratio = (((pulse_pos - fr_off) - prev_to_prev_t->frame()) / (double) ((pulse_pos) - prev_to_prev_t->frame()));
+ pulse_ratio = ((start_pulse - prev_to_prev_t->pulse()) / (end_pulse - prev_to_prev_t->pulse()));
+ } else {
+
+ frame_ratio = (((pulse_pos - fr_off) - prev_t->frame()) / (double) ((pulse_pos) - prev_t->frame()));
+ pulse_ratio = (start_pulse / end_pulse);
+ }
+ new_bpm = prev_t->beats_per_minute() * (pulse_ratio * frame_ratio);
+ }
+
+ prev_t->set_beats_per_minute (new_bpm);
+ recompute_tempos (future_map);
+ recompute_meters (future_map);
+
+ if (check_solved (future_map, true)) {
+ ts->set_beats_per_minute (new_bpm);
+ recompute_tempos (_metrics);
+ recompute_meters (_metrics);
+ }
+ }
+
+ Metrics::const_iterator d = future_map.begin();
+ while (d != future_map.end()) {
+ delete (*d);
+ ++d;
+ }
+
+ MetricPositionChanged (); // Emit Signal
+}
+
framecnt_t
TempoMap::bbt_duration_at (framepos_t pos, const BBT_Time& bbt, int dir)
{