mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-17 04:06:26 +01:00
Tempo ramps - rework mouse dragging of tempo marks, derive beat_at_tempo() and tempo_at_beat().
This commit is contained in:
parent
38df1063d3
commit
452e484faf
4 changed files with 211 additions and 93 deletions
|
|
@ -3122,6 +3122,8 @@ MeterMarkerDrag::MeterMarkerDrag (Editor* e, ArdourCanvas::Item* i, bool c)
|
||||||
DEBUG_TRACE (DEBUG::Drags, "New MeterMarkerDrag\n");
|
DEBUG_TRACE (DEBUG::Drags, "New MeterMarkerDrag\n");
|
||||||
_marker = reinterpret_cast<MeterMarker*> (_item->get_data ("marker"));
|
_marker = reinterpret_cast<MeterMarker*> (_item->get_data ("marker"));
|
||||||
assert (_marker);
|
assert (_marker);
|
||||||
|
_real_section = &_marker->meter();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -3151,15 +3153,15 @@ MeterMarkerDrag::motion (GdkEvent* event, bool first_move)
|
||||||
// leave or lose the original marker (leave if its a copy; lose if its
|
// leave or lose the original marker (leave if its a copy; lose if its
|
||||||
// not, because we'll remove it from the map).
|
// not, because we'll remove it from the map).
|
||||||
|
|
||||||
|
char name[64];
|
||||||
|
snprintf (name, sizeof(name), "%g/%g", _marker->meter().divisions_per_bar(), _marker->meter().note_divisor ());
|
||||||
|
|
||||||
MeterSection section (_marker->meter());
|
MeterSection section (_marker->meter());
|
||||||
|
|
||||||
if (!section.movable()) {
|
if (!section.movable()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
char name[64];
|
|
||||||
snprintf (name, sizeof(name), "%g/%g", _marker->meter().divisions_per_bar(), _marker->meter().note_divisor ());
|
|
||||||
|
|
||||||
_marker = new MeterMarker (
|
_marker = new MeterMarker (
|
||||||
*_editor,
|
*_editor,
|
||||||
*_editor->meter_group,
|
*_editor->meter_group,
|
||||||
|
|
@ -3172,17 +3174,22 @@ MeterMarkerDrag::motion (GdkEvent* event, bool first_move)
|
||||||
swap_grab (&_marker->the_item(), 0, GDK_CURRENT_TIME);
|
swap_grab (&_marker->the_item(), 0, GDK_CURRENT_TIME);
|
||||||
|
|
||||||
if (!_copy) {
|
if (!_copy) {
|
||||||
|
_editor->begin_reversible_command (_("move meter mark"));
|
||||||
TempoMap& map (_editor->session()->tempo_map());
|
TempoMap& map (_editor->session()->tempo_map());
|
||||||
/* get current state */
|
/* get current state */
|
||||||
before_state = &map.get_state();
|
before_state = &map.get_state();
|
||||||
/* remove the section while we drag it */
|
/* remove the section while we drag it */
|
||||||
map.remove_meter (section, true);
|
//map.remove_meter (section, true);
|
||||||
}
|
}
|
||||||
|
_marker->hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
framepos_t const pf = adjusted_current_frame (event);
|
framepos_t const pf = adjusted_current_frame (event, false);
|
||||||
|
double const baf = _editor->session()->tempo_map().beat_at_frame (pf);
|
||||||
|
|
||||||
_marker->set_position (pf);
|
_marker->set_position (pf);
|
||||||
|
_editor->session()->tempo_map().gui_move_meter (_real_section, _marker->meter(), pf, baf);
|
||||||
|
|
||||||
show_verbose_cursor_time (pf);
|
show_verbose_cursor_time (pf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3222,8 +3229,6 @@ MeterMarkerDrag::finished (GdkEvent* event, bool movement_occurred)
|
||||||
_editor->commit_reversible_command ();
|
_editor->commit_reversible_command ();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
_editor->begin_reversible_command (_("move meter mark"));
|
|
||||||
|
|
||||||
/* we removed it before, so add it back now */
|
/* we removed it before, so add it back now */
|
||||||
if (_marker->meter().position_lock_style() == AudioTime) {
|
if (_marker->meter().position_lock_style() == AudioTime) {
|
||||||
map.add_meter (_marker->meter(), _marker->position());
|
map.add_meter (_marker->meter(), _marker->position());
|
||||||
|
|
@ -3325,9 +3330,9 @@ TempoMarkerDrag::motion (GdkEvent* event, bool first_move)
|
||||||
|
|
||||||
framepos_t const pf = adjusted_current_frame (event, false);
|
framepos_t const pf = adjusted_current_frame (event, false);
|
||||||
double const baf = _editor->session()->tempo_map().beat_at_frame (pf);
|
double const baf = _editor->session()->tempo_map().beat_at_frame (pf);
|
||||||
|
Tempo const tp = _marker->tempo();
|
||||||
_marker->set_position (adjusted_current_frame (event, false));
|
_marker->set_position (pf);
|
||||||
_editor->session()->tempo_map().gui_set_tempo_frame (*_real_section, pf, baf);
|
_editor->session()->tempo_map().gui_move_tempo (_real_section, tp, pf, baf);
|
||||||
|
|
||||||
show_verbose_cursor_time (pf);
|
show_verbose_cursor_time (pf);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -705,6 +705,8 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MeterMarker* _marker;
|
MeterMarker* _marker;
|
||||||
|
ARDOUR::MeterSection* _real_section;
|
||||||
|
|
||||||
bool _copy;
|
bool _copy;
|
||||||
XMLNode* before_state;
|
XMLNode* before_state;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -185,6 +185,9 @@ class LIBARDOUR_API TempoSection : public MetricSection, public Tempo {
|
||||||
double tempo_at_frame (framepos_t frame, framecnt_t frame_rate) const;
|
double tempo_at_frame (framepos_t frame, framecnt_t frame_rate) const;
|
||||||
framepos_t frame_at_tempo (double tempo, framecnt_t frame_rate) const;
|
framepos_t frame_at_tempo (double tempo, framecnt_t frame_rate) const;
|
||||||
|
|
||||||
|
double tempo_at_beat (double beat) const;
|
||||||
|
double beat_at_tempo (double tempo) const;
|
||||||
|
|
||||||
double tick_at_frame (framepos_t frame, framecnt_t frame_rate) const;
|
double tick_at_frame (framepos_t frame, framecnt_t frame_rate) const;
|
||||||
framepos_t frame_at_tick (double tick, framecnt_t frame_rate) const;
|
framepos_t frame_at_tick (double tick, framecnt_t frame_rate) const;
|
||||||
|
|
||||||
|
|
@ -193,6 +196,7 @@ class LIBARDOUR_API TempoSection : public MetricSection, public Tempo {
|
||||||
|
|
||||||
void set_c_func_from_tempo_and_beat (double end_bpm, double end_beat, framecnt_t frame_rate);
|
void set_c_func_from_tempo_and_beat (double end_bpm, double end_beat, framecnt_t frame_rate);
|
||||||
double compute_c_func (double end_bpm, framepos_t end_frame, framecnt_t frame_rate) const;
|
double compute_c_func (double end_bpm, framepos_t end_frame, framecnt_t frame_rate) const;
|
||||||
|
|
||||||
double get_c_func () const { return _c_func; }
|
double get_c_func () const { return _c_func; }
|
||||||
void set_c_func (double c_func) { _c_func = c_func; }
|
void set_c_func (double c_func) { _c_func = c_func; }
|
||||||
|
|
||||||
|
|
@ -213,6 +217,9 @@ class LIBARDOUR_API TempoSection : public MetricSection, public Tempo {
|
||||||
double tick_tempo_at_time (double time) const;
|
double tick_tempo_at_time (double time) const;
|
||||||
double time_at_tick_tempo (double tick_tempo) const;
|
double time_at_tick_tempo (double tick_tempo) const;
|
||||||
|
|
||||||
|
double tick_tempo_at_tick (double tick) const;
|
||||||
|
double tick_at_tick_tempo (double tick_tempo) const;
|
||||||
|
|
||||||
double tick_at_time (double time) const;
|
double tick_at_time (double time) const;
|
||||||
double time_at_tick (double tick) const;
|
double time_at_tick (double tick) const;
|
||||||
|
|
||||||
|
|
@ -369,10 +376,15 @@ class LIBARDOUR_API TempoMap : public PBD::StatefulDestructible
|
||||||
void remove_meter (const MeterSection&, bool send_signal);
|
void remove_meter (const MeterSection&, bool send_signal);
|
||||||
|
|
||||||
framepos_t compute_replacement_tempo_section (TempoSection* section, const double& tempo, const double& beat);
|
framepos_t compute_replacement_tempo_section (TempoSection* section, const double& tempo, const double& beat);
|
||||||
void replace_tempo (const TempoSection&, const Tempo&, const double& where, TempoSection::Type type);
|
Metrics imagine_new_order (TempoSection* section, const Tempo& bpm, const framepos_t& frame, const double& beat);
|
||||||
void replace_tempo (const TempoSection&, const Tempo&, const framepos_t& where, TempoSection::Type type);
|
Metrics imagine_new_order (MeterSection* section, const Meter& mt, const framepos_t& frame, const double& beat);
|
||||||
|
|
||||||
|
void replace_tempo (const TempoSection&, const Tempo&, const double& where, TempoSection::Type type);
|
||||||
|
void replace_tempo (const TempoSection&, const Tempo&, const framepos_t& frame, TempoSection::Type type);
|
||||||
|
|
||||||
|
void gui_move_tempo (TempoSection*, const Tempo& bpm, const framepos_t& where, const double& beat);
|
||||||
|
void gui_move_meter (MeterSection*, const Meter& mt, const framepos_t& where, const double& beat);
|
||||||
|
|
||||||
void gui_set_tempo_frame (TempoSection&, framepos_t where, double beat);
|
|
||||||
void replace_meter (const MeterSection&, const Meter&, const Timecode::BBT_Time& where);
|
void replace_meter (const MeterSection&, const Meter&, const Timecode::BBT_Time& where);
|
||||||
void replace_meter (const MeterSection&, const Meter&, const framepos_t& frame);
|
void replace_meter (const MeterSection&, const Meter&, const framepos_t& frame);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -216,7 +216,7 @@ TempoSection::tempo_at_frame (framepos_t f, framecnt_t frame_rate) const
|
||||||
}
|
}
|
||||||
|
|
||||||
/** returns the zero-based frame (relative to session)
|
/** returns the zero-based frame (relative to session)
|
||||||
where the tempo occurs.
|
where the tempo occurs in this section. note that the tempo map may have multiple such values.
|
||||||
*/
|
*/
|
||||||
framepos_t
|
framepos_t
|
||||||
TempoSection::frame_at_tempo (double bpm, framecnt_t frame_rate) const
|
TempoSection::frame_at_tempo (double bpm, framecnt_t frame_rate) const
|
||||||
|
|
@ -227,6 +227,31 @@ TempoSection::frame_at_tempo (double bpm, framecnt_t frame_rate) const
|
||||||
|
|
||||||
return minute_to_frame (time_at_tick_tempo (bpm * BBT_Time::ticks_per_beat), frame_rate) + frame();
|
return minute_to_frame (time_at_tick_tempo (bpm * BBT_Time::ticks_per_beat), frame_rate) + frame();
|
||||||
}
|
}
|
||||||
|
/** returns the tempo at the zero-based (relative to session) frame.
|
||||||
|
*/
|
||||||
|
double
|
||||||
|
TempoSection::tempo_at_beat (double b) const
|
||||||
|
{
|
||||||
|
|
||||||
|
if (_type == Constant) {
|
||||||
|
return beats_per_minute();
|
||||||
|
}
|
||||||
|
|
||||||
|
return tick_tempo_at_tick ((b - beat()) * BBT_Time::ticks_per_beat) / BBT_Time::ticks_per_beat;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** returns the zero-based frame (relative to session)
|
||||||
|
where the tempo occurs in this section. note that the tempo map may have multiple such values.
|
||||||
|
*/
|
||||||
|
double
|
||||||
|
TempoSection::beat_at_tempo (double bpm) const
|
||||||
|
{
|
||||||
|
if (_type == Constant) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (tick_at_tick_tempo (bpm * BBT_Time::ticks_per_beat) / BBT_Time::ticks_per_beat) + beat();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/** returns the zero-based tick (relative to session origin)
|
/** returns the zero-based tick (relative to session origin)
|
||||||
|
|
@ -396,6 +421,20 @@ TempoSection::time_at_tick_tempo (double tick_tempo) const
|
||||||
return log (tick_tempo / ticks_per_minute()) / _c_func;
|
return log (tick_tempo / ticks_per_minute()) / _c_func;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* tick at tempo in tpm */
|
||||||
|
double
|
||||||
|
TempoSection::tick_at_tick_tempo (double tick_tempo) const
|
||||||
|
{
|
||||||
|
return (tick_tempo - ticks_per_minute()) / _c_func;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* tempo in tpm at tick */
|
||||||
|
double
|
||||||
|
TempoSection::tick_tempo_at_tick (double tick) const
|
||||||
|
{
|
||||||
|
return (tick * _c_func) + ticks_per_minute();
|
||||||
|
}
|
||||||
|
|
||||||
/* tick at time in minutes */
|
/* tick at time in minutes */
|
||||||
double
|
double
|
||||||
TempoSection::tick_at_time (double time) const
|
TempoSection::tick_at_time (double time) const
|
||||||
|
|
@ -947,89 +986,142 @@ TempoMap::replace_tempo (const TempoSection& ts, const Tempo& tempo, const frame
|
||||||
PropertyChanged (PropertyChange ());
|
PropertyChanged (PropertyChange ());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Metrics
|
||||||
|
TempoMap::imagine_new_order (TempoSection* section, const Tempo& bpm, const framepos_t& frame, const double& beat)
|
||||||
|
{
|
||||||
|
Metrics imaginary (metrics);
|
||||||
|
|
||||||
|
TempoSection* prev_ts = 0;
|
||||||
|
TempoSection* t;
|
||||||
|
|
||||||
|
/*set frame and sort */
|
||||||
|
section->set_frame (frame);
|
||||||
|
MetricSectionFrameSorter fcmp;
|
||||||
|
imaginary.sort (fcmp);
|
||||||
|
|
||||||
|
/* recompute */
|
||||||
|
for (Metrics::iterator i = imaginary.begin(); i != imaginary.end(); ++i) {
|
||||||
|
if ((t = dynamic_cast<TempoSection*> (*i)) != 0) {
|
||||||
|
if (prev_ts) {
|
||||||
|
if (t == section) {
|
||||||
|
/* we have already set the frame - set the beat */
|
||||||
|
prev_ts->set_c_func (prev_ts->compute_c_func (bpm.beats_per_minute(), frame, _frame_rate));
|
||||||
|
section->set_beat (prev_ts->beat_at_frame (frame, _frame_rate));
|
||||||
|
prev_ts = t;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (t->position_lock_style() == MusicTime) {
|
||||||
|
prev_ts->set_c_func_from_tempo_and_beat (t->beats_per_minute(), t->beat(), _frame_rate);
|
||||||
|
t->set_frame (prev_ts->frame_at_beat (t->beat(), _frame_rate));
|
||||||
|
} else {
|
||||||
|
prev_ts->set_c_func (prev_ts->compute_c_func (t->beats_per_minute(), t->frame(), _frame_rate));
|
||||||
|
t->set_beat (prev_ts->beat_at_frame (t->frame(), _frame_rate));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
prev_ts = t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* to do - check precision using _at_tempo() methods */
|
||||||
|
/*
|
||||||
|
prev_ts = 0;
|
||||||
|
std::cerr << "dumping imaginary order ------" << std::endl;;
|
||||||
|
for (Metrics::iterator i = imaginary.begin(); i != imaginary.end(); ++i) {
|
||||||
|
if ((t = dynamic_cast<TempoSection*> (*i)) != 0) {
|
||||||
|
if (prev_ts) {
|
||||||
|
|
||||||
|
std::cerr << t->beats_per_minute() << " | " << t->beat() << " | " << t->frame() << std::endl;
|
||||||
|
std::cerr << prev_ts->beats_per_minute() << " | " << prev_ts->beat() << " | " << prev_ts->frame() << std::endl;
|
||||||
|
std::cerr << t->beats_per_minute() << " | " << prev_ts->beat_at_tempo (t->beats_per_minute()) << " | " << prev_ts->tempo_at_beat(t->beat()) << " | " << prev_ts->frame_at_tempo(t->beats_per_minute(), _frame_rate) << std::endl;
|
||||||
|
std::cerr << " ------" << std::endl;;
|
||||||
|
|
||||||
|
}
|
||||||
|
prev_ts = t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::cerr << "end dump ------";
|
||||||
|
*/
|
||||||
|
return imaginary;
|
||||||
|
}
|
||||||
|
|
||||||
|
Metrics
|
||||||
|
TempoMap::imagine_new_order(MeterSection* section, const Meter& mt, const framepos_t& frame, const double& beat)
|
||||||
|
{
|
||||||
|
/* incomplete */
|
||||||
|
Metrics imaginary (metrics);
|
||||||
|
|
||||||
|
MeterSection* prev_ms = 0;
|
||||||
|
MeterSection* m;
|
||||||
|
MeterSection* our_section = 0;
|
||||||
|
framepos_t ret = 0;
|
||||||
|
MetricSectionSorter cmp;
|
||||||
|
|
||||||
|
for (Metrics::iterator i = imaginary.begin(); i != imaginary.end(); ++i) {
|
||||||
|
if ((m = dynamic_cast<MeterSection*> (*i)) != 0) {
|
||||||
|
if (prev_ms) {
|
||||||
|
if (section->beat() == m->beat()) {
|
||||||
|
our_section = m;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (beat < m->beat()){
|
||||||
|
pair<double, BBT_Time> b_bbt = make_pair (beat, BBT_Time (1, 1, 0));
|
||||||
|
our_section->set_beat (b_bbt);
|
||||||
|
our_section->set_frame (frame_at_beat_locked (beat));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m->position_lock_style() == MusicTime) {
|
||||||
|
m->set_frame (frame_at_beat_locked (m->beat()));
|
||||||
|
} else {
|
||||||
|
pair<double, BBT_Time> b_bbt = make_pair (beat_at_frame_locked (m->frame()), BBT_Time (1, 1, 0));
|
||||||
|
m->set_beat (b_bbt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
prev_ms = m;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* now we do the whole thing again because audio-locked sections will have caused a re-order */
|
||||||
|
prev_ms = 0;
|
||||||
|
metrics.sort (cmp);
|
||||||
|
|
||||||
|
for (Metrics::iterator i = imaginary.begin(); i != imaginary.end(); ++i) {
|
||||||
|
if ((m = dynamic_cast<MeterSection*> (*i)) != 0) {
|
||||||
|
if (prev_ms) {
|
||||||
|
if (section->beat() == m->beat()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (beat < m->beat()){
|
||||||
|
ret = frame_at_beat (beat);
|
||||||
|
section->set_frame (ret);
|
||||||
|
prev_ms = section;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (m->position_lock_style() == MusicTime) {
|
||||||
|
m->set_frame (frame_at_beat (m->beat()));
|
||||||
|
} else {
|
||||||
|
pair<double, BBT_Time> b_bbt = make_pair (beat_at_frame_locked (m->frame()), BBT_Time (1, 1, 0));
|
||||||
|
m->set_beat (b_bbt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
prev_ms = m;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ret) {
|
||||||
|
pair<double, BBT_Time> b_bbt = make_pair (beat, BBT_Time (1, 1, 0));
|
||||||
|
section->set_beat (b_bbt);
|
||||||
|
section->set_frame (frame_at_beat_locked (beat));
|
||||||
|
}
|
||||||
|
return imaginary;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TempoMap::gui_set_tempo_frame (TempoSection& ts, framepos_t frame, double beat_where)
|
TempoMap::gui_move_tempo (TempoSection* ts, const Tempo& bpm, const framepos_t& frame, const double& beat_where)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
Glib::Threads::RWLock::WriterLock lm (lock);
|
Glib::Threads::RWLock::WriterLock lm (lock);
|
||||||
|
Metrics new_order = imagine_new_order (ts, bpm, frame, beat_where);
|
||||||
if (ts.position_lock_style() == MusicTime) {
|
metrics.clear();
|
||||||
std::cerr << "Music " << " beat where : " << beat_where << " frame : " << frame <<std::endl;
|
metrics = new_order;
|
||||||
/* MusicTime */
|
|
||||||
ts.set_beat (beat_where);
|
|
||||||
Metrics::const_iterator i;
|
|
||||||
|
|
||||||
TempoSection* prev_ts = 0;
|
|
||||||
MetricSectionSorter cmp;
|
|
||||||
metrics.sort (cmp);
|
|
||||||
for (i = metrics.begin(); i != metrics.end(); ++i) {
|
|
||||||
TempoSection* t;
|
|
||||||
if ((t = dynamic_cast<TempoSection*> (*i)) != 0) {
|
|
||||||
|
|
||||||
if (t->beat() >= beat_where) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
prev_ts = t;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
prev_ts->set_c_func_from_tempo_and_beat (ts.beats_per_minute(), ts.beat(), _frame_rate);
|
|
||||||
ts.set_frame (prev_ts->frame_at_beat (ts.beat(), _frame_rate));
|
|
||||||
} else {
|
|
||||||
std::cerr << "Audio " << " beat where : " << beat_where << " frame : " << frame <<std::endl;
|
|
||||||
|
|
||||||
/*AudioTime*/
|
|
||||||
ts.set_frame (frame);
|
|
||||||
MetricSectionFrameSorter fcmp;
|
|
||||||
metrics.sort (fcmp);
|
|
||||||
|
|
||||||
Metrics::const_iterator i;
|
|
||||||
TempoSection* prev_ts = 0;
|
|
||||||
TempoSection* next_ts = 0;
|
|
||||||
|
|
||||||
for (i = metrics.begin(); i != metrics.end(); ++i) {
|
|
||||||
TempoSection* t;
|
|
||||||
if ((t = dynamic_cast<TempoSection*> (*i)) != 0) {
|
|
||||||
if (t->frame() == frame) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (frame < t->frame()) {
|
|
||||||
next_ts = t;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
prev_ts = t;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (prev_ts) {
|
|
||||||
/* set the start beat - we need to reset the function constant before beat calculations make sense*/
|
|
||||||
prev_ts->set_c_func (prev_ts->compute_c_func (ts.beats_per_minute(), frame, _frame_rate));
|
|
||||||
double beats = prev_ts->beat_at_frame (frame, _frame_rate);
|
|
||||||
|
|
||||||
if (next_ts) {
|
|
||||||
if (next_ts->beat() < beats) {
|
|
||||||
/* with frame-based editing, it is possible to get in a
|
|
||||||
situation where if the tempo was placed at the mouse pointer frame,
|
|
||||||
the following music-based tempo would jump to an earlier frame,
|
|
||||||
changing the odering.
|
|
||||||
in this case, we need some kind of tempo map speculator.
|
|
||||||
*/
|
|
||||||
} else if (prev_ts->beat() > beats) {
|
|
||||||
ts.set_beat (prev_ts->beat());
|
|
||||||
} else {
|
|
||||||
ts.set_beat (beats);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ts.set_beat (beats);
|
|
||||||
ts.set_c_func (0.0);
|
|
||||||
|
|
||||||
}
|
|
||||||
MetricSectionSorter cmp;
|
|
||||||
metrics.sort (cmp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
recompute_map (false);
|
recompute_map (false);
|
||||||
}
|
}
|
||||||
|
|
@ -1037,6 +1129,13 @@ TempoMap::gui_set_tempo_frame (TempoSection& ts, framepos_t frame, double beat_
|
||||||
MetricPositionChanged (); // Emit Signal
|
MetricPositionChanged (); // Emit Signal
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TempoMap::gui_move_meter (MeterSection* ms, const Meter& mt, const framepos_t& frame, const double& beat_where)
|
||||||
|
{
|
||||||
|
Glib::Threads::RWLock::WriterLock lm (lock);
|
||||||
|
Metrics imaginary = imagine_new_order (ms, mt, frame, beat_where);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TempoMap::add_tempo (const Tempo& tempo, double where, ARDOUR::TempoSection::Type type)
|
TempoMap::add_tempo (const Tempo& tempo, double where, ARDOUR::TempoSection::Type type)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue