Tempo ramps - fix changing from const to ramp in the gui.
- also fixes some midi mouse over problems - start using replacements for frames_per_bar() frames_per_beat() etc.
This commit is contained in:
parent
0d0e458dde
commit
dbfe991cd8
|
@ -519,7 +519,7 @@ Drag::add_midi_region (MidiTimeAxisView* view, bool commit)
|
||||||
/* not that the frame rate used here can be affected by pull up/down which
|
/* not that the frame rate used here can be affected by pull up/down which
|
||||||
might be wrong.
|
might be wrong.
|
||||||
*/
|
*/
|
||||||
framecnt_t len = m.frames_per_bar (map.tempo_at (pos), _editor->session()->frame_rate());
|
framecnt_t len = map.frame_at_beat (map.beat_at_frame (pos) + 1.0) - pos;
|
||||||
return view->add_region (grab_frame(), len, commit);
|
return view->add_region (grab_frame(), len, commit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4123,7 +4123,7 @@ MidiRegionView::get_grid_beats(framepos_t pos) const
|
||||||
{
|
{
|
||||||
PublicEditor& editor = trackview.editor();
|
PublicEditor& editor = trackview.editor();
|
||||||
bool success = false;
|
bool success = false;
|
||||||
Evoral::Beats beats = editor.get_grid_type_as_beats(success, pos);
|
Evoral::Beats beats = editor.get_grid_type_as_beats (success, pos);
|
||||||
if (!success) {
|
if (!success) {
|
||||||
beats = Evoral::Beats(1);
|
beats = Evoral::Beats(1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -118,7 +118,12 @@ StepEditor::prepare_step_edit_region ()
|
||||||
const Meter& m = _mtv.session()->tempo_map().meter_at (step_edit_insert_position);
|
const Meter& m = _mtv.session()->tempo_map().meter_at (step_edit_insert_position);
|
||||||
const Tempo& t = _mtv.session()->tempo_map().tempo_at (step_edit_insert_position);
|
const Tempo& t = _mtv.session()->tempo_map().tempo_at (step_edit_insert_position);
|
||||||
|
|
||||||
step_edit_region = _mtv.add_region (step_edit_insert_position, floor (m.frames_per_bar (t, _mtv.session()->frame_rate())), true);
|
double baf = _mtv.session()->tempo_map().beat_at_frame (step_edit_insert_position);
|
||||||
|
double next_bar_in_beats = baf + m.divisions_per_bar();
|
||||||
|
framecnt_t next_bar_pos = _mtv.session()->tempo_map().frame_at_beat (next_bar_in_beats);
|
||||||
|
framecnt_t len = next_bar_pos - step_edit_insert_position;
|
||||||
|
|
||||||
|
step_edit_region = _mtv.add_region (step_edit_insert_position, len, true);
|
||||||
|
|
||||||
RegionView* rv = _mtv.midi_view()->find_view (step_edit_region);
|
RegionView* rv = _mtv.midi_view()->find_view (step_edit_region);
|
||||||
step_edit_region_view = dynamic_cast<MidiRegionView*>(rv);
|
step_edit_region_view = dynamic_cast<MidiRegionView*>(rv);
|
||||||
|
|
|
@ -194,6 +194,7 @@ TempoDialog::init (const Timecode::BBT_Time& when, double bpm, double note_type,
|
||||||
when_beat_entry.signal_activate().connect (sigc::bind (sigc::mem_fun (*this, &TempoDialog::response), RESPONSE_ACCEPT));
|
when_beat_entry.signal_activate().connect (sigc::bind (sigc::mem_fun (*this, &TempoDialog::response), RESPONSE_ACCEPT));
|
||||||
when_beat_entry.signal_key_release_event().connect (sigc::mem_fun (*this, &TempoDialog::entry_key_release), false);
|
when_beat_entry.signal_key_release_event().connect (sigc::mem_fun (*this, &TempoDialog::entry_key_release), false);
|
||||||
pulse_selector.signal_changed().connect (sigc::mem_fun (*this, &TempoDialog::pulse_change));
|
pulse_selector.signal_changed().connect (sigc::mem_fun (*this, &TempoDialog::pulse_change));
|
||||||
|
tempo_type.signal_changed().connect (sigc::mem_fun (*this, &TempoDialog::tempo_type_change));
|
||||||
tap_tempo_button.signal_button_press_event().connect (sigc::mem_fun (*this, &TempoDialog::tap_tempo_button_press), false);
|
tap_tempo_button.signal_button_press_event().connect (sigc::mem_fun (*this, &TempoDialog::tap_tempo_button_press), false);
|
||||||
tap_tempo_button.signal_focus_out_event().connect (sigc::mem_fun (*this, &TempoDialog::tap_tempo_focus_out));
|
tap_tempo_button.signal_focus_out_event().connect (sigc::mem_fun (*this, &TempoDialog::tap_tempo_focus_out));
|
||||||
|
|
||||||
|
@ -290,6 +291,12 @@ TempoDialog::pulse_change ()
|
||||||
set_response_sensitive (RESPONSE_ACCEPT, is_user_input_valid());
|
set_response_sensitive (RESPONSE_ACCEPT, is_user_input_valid());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TempoDialog::tempo_type_change ()
|
||||||
|
{
|
||||||
|
set_response_sensitive (RESPONSE_ACCEPT, is_user_input_valid());
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
TempoDialog::tap_tempo_button_press (GdkEventButton *ev)
|
TempoDialog::tap_tempo_button_press (GdkEventButton *ev)
|
||||||
{
|
{
|
||||||
|
|
|
@ -54,6 +54,7 @@ private:
|
||||||
bool bpm_button_release (GdkEventButton* );
|
bool bpm_button_release (GdkEventButton* );
|
||||||
bool entry_key_release (GdkEventKey* );
|
bool entry_key_release (GdkEventKey* );
|
||||||
void pulse_change ();
|
void pulse_change ();
|
||||||
|
void tempo_type_change ();
|
||||||
bool tap_tempo_button_press (GdkEventButton* );
|
bool tap_tempo_button_press (GdkEventButton* );
|
||||||
bool tap_tempo_focus_out (GdkEventFocus* );
|
bool tap_tempo_focus_out (GdkEventFocus* );
|
||||||
|
|
||||||
|
|
|
@ -335,9 +335,12 @@ class LIBARDOUR_API TempoMap : public PBD::StatefulDestructible
|
||||||
static const Meter& default_meter() { return _default_meter; }
|
static const Meter& default_meter() { return _default_meter; }
|
||||||
|
|
||||||
const Tempo tempo_at (framepos_t) const;
|
const Tempo tempo_at (framepos_t) const;
|
||||||
|
double frames_per_beat_at (framepos_t, framecnt_t sr) const;
|
||||||
|
|
||||||
const Meter& meter_at (framepos_t) const;
|
const Meter& meter_at (framepos_t) const;
|
||||||
|
|
||||||
const TempoSection& tempo_section_at (framepos_t) const;
|
const TempoSection& tempo_section_at (framepos_t) const;
|
||||||
|
TempoSection* tempo_section_after (framepos_t) const;
|
||||||
const MeterSection& meter_section_at (framepos_t) const;
|
const MeterSection& meter_section_at (framepos_t) const;
|
||||||
|
|
||||||
void add_tempo (const Tempo&, Timecode::BBT_Time where, TempoSection::TempoSectionType type);
|
void add_tempo (const Tempo&, Timecode::BBT_Time where, TempoSection::TempoSectionType type);
|
||||||
|
|
|
@ -206,7 +206,7 @@ double
|
||||||
TempoSection::tick_at_frame (framepos_t frame, double end_bpm, framepos_t end_frame, framecnt_t frame_rate) const
|
TempoSection::tick_at_frame (framepos_t frame, double end_bpm, framepos_t end_frame, framecnt_t frame_rate) const
|
||||||
{
|
{
|
||||||
if (_type == Constant) {
|
if (_type == Constant) {
|
||||||
return frame / frames_per_beat (frame_rate);
|
return (frame / frames_per_beat (frame_rate)) * BBT_Time::ticks_per_beat;
|
||||||
}
|
}
|
||||||
|
|
||||||
return tick_at_time (frame_to_minute (frame, frame_rate), end_bpm * BBT_Time::ticks_per_beat, frame_to_minute (end_frame, frame_rate));
|
return tick_at_time (frame_to_minute (frame, frame_rate), end_bpm * BBT_Time::ticks_per_beat, frame_to_minute (end_frame, frame_rate));
|
||||||
|
@ -216,7 +216,7 @@ framepos_t
|
||||||
TempoSection::frame_at_tick (double tick, double end_bpm, framepos_t end_frame, framecnt_t frame_rate) const
|
TempoSection::frame_at_tick (double tick, double end_bpm, framepos_t end_frame, framecnt_t frame_rate) const
|
||||||
{
|
{
|
||||||
if (_type == Constant) {
|
if (_type == Constant) {
|
||||||
return (framepos_t) floor (tick * frames_per_beat(frame_rate));
|
return (framepos_t) floor ((tick / BBT_Time::ticks_per_beat) * frames_per_beat (frame_rate));
|
||||||
}
|
}
|
||||||
|
|
||||||
return minute_to_frame (time_at_tick (tick, end_bpm * BBT_Time::ticks_per_beat, frame_to_minute (end_frame, frame_rate)), frame_rate);
|
return minute_to_frame (time_at_tick (tick, end_bpm * BBT_Time::ticks_per_beat, frame_to_minute (end_frame, frame_rate)), frame_rate);
|
||||||
|
@ -642,11 +642,10 @@ TempoMap::replace_tempo (const TempoSection& ts, const Tempo& tempo, const BBT_T
|
||||||
{
|
{
|
||||||
Glib::Threads::RWLock::WriterLock lm (lock);
|
Glib::Threads::RWLock::WriterLock lm (lock);
|
||||||
TempoSection& first (first_tempo());
|
TempoSection& first (first_tempo());
|
||||||
TempoSection::TempoSectionType tt = first.type();
|
|
||||||
|
|
||||||
if (ts.start() != first.start()) {
|
if (ts.start() != first.start()) {
|
||||||
remove_tempo_locked (ts);
|
remove_tempo_locked (ts);
|
||||||
add_tempo_locked (tempo, where, true, tt);
|
add_tempo_locked (tempo, where, true, type);
|
||||||
} else {
|
} else {
|
||||||
{
|
{
|
||||||
/* cannot move the first tempo section */
|
/* cannot move the first tempo section */
|
||||||
|
@ -1058,6 +1057,11 @@ TempoMap::_extend_map (TempoSection* tempo, MeterSection* meter,
|
||||||
double ticks_relative_to_prev_ts = ticks_at_ts - ticks_at_prev_ts;
|
double ticks_relative_to_prev_ts = ticks_at_ts - ticks_at_prev_ts;
|
||||||
/* assume (falsely) that the target tempo is constant */
|
/* assume (falsely) that the target tempo is constant */
|
||||||
double length_estimate = (ticks_relative_to_prev_ts / BBT_Time::ticks_per_beat) * meter->frames_per_grid (*t, _frame_rate);
|
double length_estimate = (ticks_relative_to_prev_ts / BBT_Time::ticks_per_beat) * meter->frames_per_grid (*t, _frame_rate);
|
||||||
|
if (prev_ts->type() == TempoSection::TempoSectionType::Constant) {
|
||||||
|
cerr << "constant type " << endl;
|
||||||
|
length_estimate = (ticks_relative_to_prev_ts / BBT_Time::ticks_per_beat) * prev_ts->frames_per_beat (_frame_rate);
|
||||||
|
}
|
||||||
|
cerr<< "initial length extimate = " << length_estimate << " ticks_relative_to_prev_ts " << ticks_relative_to_prev_ts << endl;
|
||||||
double system_precision_at_target_tempo = (_frame_rate / t->ticks_per_minute());
|
double system_precision_at_target_tempo = (_frame_rate / t->ticks_per_minute());
|
||||||
cerr << " system_precision_at_target_tempo = " << system_precision_at_target_tempo << endl;
|
cerr << " system_precision_at_target_tempo = " << system_precision_at_target_tempo << endl;
|
||||||
double tick_error = system_precision_at_target_tempo + 1.0; // sorry for the wtf
|
double tick_error = system_precision_at_target_tempo + 1.0; // sorry for the wtf
|
||||||
|
@ -1067,15 +1071,18 @@ TempoMap::_extend_map (TempoSection* tempo, MeterSection* meter,
|
||||||
double actual_ticks = prev_ts->tick_at_frame (length_estimate, t->beats_per_minute(), (framepos_t) length_estimate, _frame_rate);
|
double actual_ticks = prev_ts->tick_at_frame (length_estimate, t->beats_per_minute(), (framepos_t) length_estimate, _frame_rate);
|
||||||
tick_error = ticks_relative_to_prev_ts - actual_ticks;
|
tick_error = ticks_relative_to_prev_ts - actual_ticks;
|
||||||
length_estimate += (tick_error / BBT_Time::ticks_per_beat) * meter->frames_per_grid (*t, _frame_rate);
|
length_estimate += (tick_error / BBT_Time::ticks_per_beat) * meter->frames_per_grid (*t, _frame_rate);
|
||||||
cerr << "actual ticks = " << actual_ticks << endl;
|
//cerr << "actual ticks = " << actual_ticks << endl;
|
||||||
|
|
||||||
cerr << "tick error = " << tick_error << endl;
|
//cerr << "tick error = " << tick_error << endl;
|
||||||
}
|
}
|
||||||
|
cerr << "setting t frame to " << length_estimate + prev_ts->frame() << "tick error = " << tick_error << endl;
|
||||||
t->set_frame (length_estimate + prev_ts->frame());
|
t->set_frame (length_estimate + prev_ts->frame());
|
||||||
|
|
||||||
if (m->start() < t->start() && m->start() == prev_ts->start()) {
|
if (m->start() < t->start() && m->start() == prev_ts->start()) {
|
||||||
m->set_frame (prev_ts->frame());
|
m->set_frame (prev_ts->frame());
|
||||||
} else if (m->start() < t->start() && m->start() > prev_ts->start()) {
|
} else if (m->start() < t->start() && m->start() > prev_ts->start()) {
|
||||||
|
cerr << "setting m frame to " << prev_ts->frame_at_tick ((first_tick_in_new_meter - ticks_at_prev_ts), t->beats_per_minute(), (framepos_t) length_estimate, _frame_rate) << " ticks = " << first_tick_in_new_meter - ticks_at_prev_ts << endl;
|
||||||
|
|
||||||
m->set_frame (prev_ts->frame_at_tick ((first_tick_in_new_meter - ticks_at_prev_ts), t->beats_per_minute(), (framepos_t) length_estimate, _frame_rate));
|
m->set_frame (prev_ts->frame_at_tick ((first_tick_in_new_meter - ticks_at_prev_ts), t->beats_per_minute(), (framepos_t) length_estimate, _frame_rate));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1670,7 +1677,6 @@ TempoMap::round_to_type (framepos_t frame, RoundMode dir, BBTPointType type)
|
||||||
return frame_time (bbt);
|
return frame_time (bbt);
|
||||||
} else {
|
} else {
|
||||||
/* true rounding: find nearest bar */
|
/* true rounding: find nearest bar */
|
||||||
|
|
||||||
framepos_t raw_ft = frame_time (bbt);
|
framepos_t raw_ft = frame_time (bbt);
|
||||||
bbt.beats = 1;
|
bbt.beats = 1;
|
||||||
bbt.ticks = 0;
|
bbt.ticks = 0;
|
||||||
|
@ -1720,6 +1726,30 @@ TempoMap::get_grid (vector<TempoMap::BBTPoint>& points,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TempoSection*
|
||||||
|
TempoMap::tempo_section_after (framepos_t frame) const
|
||||||
|
{
|
||||||
|
Glib::Threads::RWLock::ReaderLock lm (lock);
|
||||||
|
|
||||||
|
Metrics::const_iterator i;
|
||||||
|
TempoSection* next = 0;
|
||||||
|
|
||||||
|
for (i = metrics.begin(); i != metrics.end(); ++i) {
|
||||||
|
TempoSection* t;
|
||||||
|
|
||||||
|
if ((t = dynamic_cast<TempoSection*> (*i)) != 0) {
|
||||||
|
|
||||||
|
if ((*i)->frame() > frame) {
|
||||||
|
next = t;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const TempoSection&
|
const TempoSection&
|
||||||
TempoMap::tempo_section_at (framepos_t frame) const
|
TempoMap::tempo_section_at (framepos_t frame) const
|
||||||
{
|
{
|
||||||
|
@ -1749,6 +1779,24 @@ TempoMap::tempo_section_at (framepos_t frame) const
|
||||||
return *prev;
|
return *prev;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* don't use this to calculate length (the tempo is only correct for this frame).
|
||||||
|
do that stuff based on the beat_at_frame and frame_at_beat api
|
||||||
|
*/
|
||||||
|
double
|
||||||
|
TempoMap::frames_per_beat_at (framepos_t frame, framecnt_t sr) const
|
||||||
|
{
|
||||||
|
Glib::Threads::RWLock::ReaderLock lm (lock);
|
||||||
|
|
||||||
|
const TempoSection* ts_at = &tempo_section_at (frame);
|
||||||
|
const TempoSection* ts_after = tempo_section_after (frame);
|
||||||
|
|
||||||
|
if (ts_after) {
|
||||||
|
return (60.0 * _frame_rate) / (ts_at->tempo_at_frame (frame - ts_at->frame(), ts_after->beats_per_minute(), ts_after->frame(), _frame_rate));
|
||||||
|
}
|
||||||
|
/* must be treated as constant tempo */
|
||||||
|
return ts_at->frames_per_beat (_frame_rate);
|
||||||
|
}
|
||||||
|
|
||||||
const Tempo
|
const Tempo
|
||||||
TempoMap::tempo_at (framepos_t frame) const
|
TempoMap::tempo_at (framepos_t frame) const
|
||||||
{
|
{
|
||||||
|
@ -2141,11 +2189,14 @@ TempoMap::framepos_minus_beats (framepos_t pos, Evoral::Beats beats) const
|
||||||
framepos_t
|
framepos_t
|
||||||
TempoMap::framepos_plus_bbt (framepos_t pos, BBT_Time op) const
|
TempoMap::framepos_plus_bbt (framepos_t pos, BBT_Time op) const
|
||||||
{
|
{
|
||||||
|
cerr << "framepos_plus_bbt - untested" << endl;
|
||||||
Glib::Threads::RWLock::ReaderLock lm (lock);
|
Glib::Threads::RWLock::ReaderLock lm (lock);
|
||||||
|
|
||||||
Metrics::const_iterator i;
|
Metrics::const_iterator i;
|
||||||
const MeterSection* meter;
|
const MeterSection* meter;
|
||||||
const MeterSection* m;
|
const MeterSection* m;
|
||||||
const TempoSection* tempo;
|
const TempoSection* tempo;
|
||||||
|
const TempoSection* next_tempo = 0;
|
||||||
const TempoSection* t;
|
const TempoSection* t;
|
||||||
double frames_per_beat;
|
double frames_per_beat;
|
||||||
framepos_t effective_pos = max (pos, (framepos_t) 0);
|
framepos_t effective_pos = max (pos, (framepos_t) 0);
|
||||||
|
@ -2171,10 +2222,20 @@ TempoMap::framepos_plus_bbt (framepos_t pos, BBT_Time op) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (i = metrics.begin(); i != metrics.end(); ++i) {
|
||||||
|
if ((*i)->frame() > effective_pos) {
|
||||||
|
if ((t = dynamic_cast<const TempoSection*>(*i)) != 0) {
|
||||||
|
next_tempo = t;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* We now have:
|
/* We now have:
|
||||||
|
|
||||||
meter -> the Meter for "pos"
|
meter -> the Meter for "pos"
|
||||||
tempo -> the Tempo for "pos"
|
tempo -> the Tempo for "pos"
|
||||||
|
next_tempo -> the Tempo after "pos" or 0
|
||||||
i -> for first new metric after "pos", possibly metrics.end()
|
i -> for first new metric after "pos", possibly metrics.end()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -2182,9 +2243,9 @@ TempoMap::framepos_plus_bbt (framepos_t pos, BBT_Time op) const
|
||||||
checking for a new metric on every beat.
|
checking for a new metric on every beat.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
frames_per_beat = tempo->frames_per_beat (_frame_rate);
|
|
||||||
|
|
||||||
uint64_t bars = 0;
|
uint64_t bars = 0;
|
||||||
|
/* fpb is used for constant tempo */
|
||||||
|
frames_per_beat = tempo->frames_per_beat (_frame_rate);
|
||||||
|
|
||||||
while (op.bars) {
|
while (op.bars) {
|
||||||
|
|
||||||
|
@ -2204,7 +2265,16 @@ TempoMap::framepos_plus_bbt (framepos_t pos, BBT_Time op) const
|
||||||
* frames_per_beat value.
|
* frames_per_beat value.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
pos += llrint (frames_per_beat * (bars * meter->divisions_per_bar()));
|
if ((t = dynamic_cast<const TempoSection*>(*i)) != 0) {
|
||||||
|
next_tempo = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (next_tempo) {
|
||||||
|
pos += tempo->frame_at_beat (bars * meter->divisions_per_bar(), next_tempo->beats_per_minute(), next_tempo->frame(), _frame_rate);
|
||||||
|
} else {
|
||||||
|
pos += llrint (frames_per_beat * (bars * meter->divisions_per_bar()));
|
||||||
|
}
|
||||||
|
|
||||||
bars = 0;
|
bars = 0;
|
||||||
|
|
||||||
if ((t = dynamic_cast<const TempoSection*>(*i)) != 0) {
|
if ((t = dynamic_cast<const TempoSection*>(*i)) != 0) {
|
||||||
|
@ -2214,13 +2284,16 @@ TempoMap::framepos_plus_bbt (framepos_t pos, BBT_Time op) const
|
||||||
}
|
}
|
||||||
++i;
|
++i;
|
||||||
frames_per_beat = tempo->frames_per_beat (_frame_rate);
|
frames_per_beat = tempo->frames_per_beat (_frame_rate);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pos += llrint (frames_per_beat * (bars * meter->divisions_per_bar()));
|
if (next_tempo) {
|
||||||
|
pos += tempo->frame_at_beat (bars * meter->divisions_per_bar(), next_tempo->beats_per_minute(), next_tempo->frame(), _frame_rate);
|
||||||
|
} else {
|
||||||
|
pos += llrint (frames_per_beat * (bars * meter->divisions_per_bar()));
|
||||||
|
}
|
||||||
|
|
||||||
uint64_t beats = 0;
|
uint64_t beats = 0;
|
||||||
|
|
||||||
|
@ -2244,7 +2317,16 @@ TempoMap::framepos_plus_bbt (framepos_t pos, BBT_Time op) const
|
||||||
* frames_per_beat value.
|
* frames_per_beat value.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
pos += llrint (beats * frames_per_beat);
|
if ((t = dynamic_cast<const TempoSection*>(*i)) != 0) {
|
||||||
|
next_tempo = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (next_tempo) {
|
||||||
|
pos += tempo->frame_at_beat (beats, next_tempo->beats_per_minute(), next_tempo->frame(), _frame_rate);
|
||||||
|
} else {
|
||||||
|
pos += llrint (beats * frames_per_beat);
|
||||||
|
}
|
||||||
|
|
||||||
beats = 0;
|
beats = 0;
|
||||||
|
|
||||||
if ((t = dynamic_cast<const TempoSection*>(*i)) != 0) {
|
if ((t = dynamic_cast<const TempoSection*>(*i)) != 0) {
|
||||||
|
@ -2258,16 +2340,14 @@ TempoMap::framepos_plus_bbt (framepos_t pos, BBT_Time op) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pos += llrint (beats * frames_per_beat);
|
if (next_tempo) {
|
||||||
|
pos += tempo->frame_at_beat (beats, next_tempo->beats_per_minute(), next_tempo->frame(), _frame_rate);
|
||||||
|
} else {
|
||||||
|
pos += llrint (beats * frames_per_beat);
|
||||||
|
}
|
||||||
|
|
||||||
if (op.ticks) {
|
if (op.ticks) {
|
||||||
if (op.ticks >= BBT_Time::ticks_per_beat) {
|
pos += tempo->frame_at_tick (op.ticks, next_tempo->beats_per_minute(), next_tempo->frame(), _frame_rate);
|
||||||
pos += llrint (frames_per_beat + /* extra beat */
|
|
||||||
(frames_per_beat * ((op.ticks % (uint32_t) BBT_Time::ticks_per_beat) /
|
|
||||||
(double) BBT_Time::ticks_per_beat)));
|
|
||||||
} else {
|
|
||||||
pos += llrint (frames_per_beat * (op.ticks / (double) BBT_Time::ticks_per_beat));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return pos;
|
return pos;
|
||||||
|
|
|
@ -308,7 +308,7 @@ double
|
||||||
MidiClockTicker::one_ppqn_in_frames (framepos_t transport_position)
|
MidiClockTicker::one_ppqn_in_frames (framepos_t transport_position)
|
||||||
{
|
{
|
||||||
const Tempo& current_tempo = _session->tempo_map().tempo_at (transport_position);
|
const Tempo& current_tempo = _session->tempo_map().tempo_at (transport_position);
|
||||||
double frames_per_beat = current_tempo.frames_per_beat (_session->nominal_frame_rate());
|
double frames_per_beat = _session->tempo_map().frames_per_beat_at (transport_position, _session->nominal_frame_rate());
|
||||||
|
|
||||||
double quarter_notes_per_beat = 4.0 / current_tempo.note_type();
|
double quarter_notes_per_beat = 4.0 / current_tempo.note_type();
|
||||||
double frames_per_quarter_note = frames_per_beat / quarter_notes_per_beat;
|
double frames_per_quarter_note = frames_per_beat / quarter_notes_per_beat;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user