Compare commits
29 Commits
master
...
tempo_roun
Author | SHA1 | Date |
---|---|---|
nick_m | 499a380cb2 | |
nick_m | 17a1949cf0 | |
nick_m | 970555dc65 | |
nick_m | a942ae7afb | |
nick_m | 824f62983d | |
nick_m | 8f5b84359e | |
nick_m | 4e38e69e63 | |
nick_m | a8c3928ed2 | |
nick_m | 3861ad8d6e | |
nick_m | 41054c2ba4 | |
nick_m | 9666144828 | |
nick_m | cc9994af10 | |
nick_m | 8719e139e8 | |
nick_m | 337706a599 | |
nick_m | b7be457c3c | |
nick_m | 43d5ed8b9d | |
nick_m | 56e1e5c9bb | |
nick_m | c83a53abd8 | |
nick_m | 808979c2e5 | |
nick_m | 8909fe07d3 | |
nick_m | eabecd08d2 | |
nick_m | 147af5ee41 | |
nick_m | f268eb4c18 | |
nick_m | 473874a03b | |
nick_m | 29293439e5 | |
nick_m | 6e17164b00 | |
nick_m | 11d6dc51d0 | |
nick_m | cbd353b578 | |
nick_m | 7d4ab1b9ae |
|
@ -1316,7 +1316,8 @@ AudioClock::set_bbt (framepos_t when, framecnt_t offset, bool /*force*/)
|
|||
|
||||
TempoMetric m (_session->tempo_map().metric_at (pos));
|
||||
|
||||
sprintf (buf, "%-5.3f", _session->tempo_map().tempo_at_frame (pos).beats_per_minute());
|
||||
sprintf (buf, "%-5.3f/%f", _session->tempo_map().tempo_at_frame (pos).note_types_per_minute(), m.tempo().note_type());
|
||||
/* XXX this doesn't fit inside the container. */
|
||||
_left_layout->set_markup (string_compose ("<span size=\"%1\">" TXTSPAN "%3</span> <span foreground=\"green\">%2</span></span>",
|
||||
INFO_FONT_SIZE, buf, _("Tempo")));
|
||||
|
||||
|
|
|
@ -274,7 +274,7 @@ AutomationController::set_freq_beats(double beats)
|
|||
const ARDOUR::Session& session = _controllable->session();
|
||||
const framepos_t pos = session.transport_frame();
|
||||
const ARDOUR::Tempo& tempo = session.tempo_map().tempo_at_frame (pos);
|
||||
const double bpm = tempo.beats_per_minute();
|
||||
const double bpm = tempo.note_types_per_minute();
|
||||
const double bps = bpm / 60.0;
|
||||
const double freq = bps / beats;
|
||||
_controllable->set_value(clamp(freq, desc.lower, desc.upper), Controllable::NoGroup);
|
||||
|
|
|
@ -3198,7 +3198,7 @@ MeterMarkerDrag::motion (GdkEvent* event, bool first_move)
|
|||
}
|
||||
const double beat = map.beat_at_bbt (bbt);
|
||||
_real_section = map.add_meter (Meter (_marker->meter().divisions_per_bar(), _marker->meter().note_divisor())
|
||||
, beat, bbt, map.frame_at_bbt (bbt), _real_section->position_lock_style());
|
||||
, beat, bbt, _real_section->position_lock_style());
|
||||
if (!_real_section) {
|
||||
aborted (true);
|
||||
return;
|
||||
|
@ -3271,6 +3271,7 @@ MeterMarkerDrag::aborted (bool moved)
|
|||
TempoMarkerDrag::TempoMarkerDrag (Editor* e, ArdourCanvas::Item* i, bool c)
|
||||
: Drag (e, i)
|
||||
, _copy (c)
|
||||
, _grab_bpm (0.0)
|
||||
, before_state (0)
|
||||
{
|
||||
DEBUG_TRACE (DEBUG::Drags, "New TempoMarkerDrag\n");
|
||||
|
@ -3278,6 +3279,7 @@ TempoMarkerDrag::TempoMarkerDrag (Editor* e, ArdourCanvas::Item* i, bool c)
|
|||
_marker = reinterpret_cast<TempoMarker*> (_item->get_data ("marker"));
|
||||
_real_section = &_marker->tempo();
|
||||
_movable = _real_section->movable();
|
||||
_grab_bpm = _real_section->note_types_per_minute();
|
||||
assert (_marker);
|
||||
}
|
||||
|
||||
|
@ -3310,7 +3312,7 @@ TempoMarkerDrag::motion (GdkEvent* event, bool first_move)
|
|||
// mvc drag - create a dummy marker to catch events, hide it.
|
||||
|
||||
char name[64];
|
||||
snprintf (name, sizeof (name), "%.2f", _marker->tempo().beats_per_minute());
|
||||
snprintf (name, sizeof (name), "%.2f", _marker->tempo().note_types_per_minute());
|
||||
|
||||
TempoSection section (_marker->tempo());
|
||||
|
||||
|
@ -3341,7 +3343,8 @@ TempoMarkerDrag::motion (GdkEvent* event, bool first_move)
|
|||
_editor->begin_reversible_command (_("copy tempo mark"));
|
||||
|
||||
if (_real_section->position_lock_style() == MusicTime) {
|
||||
_real_section = map.add_tempo (tempo, map.pulse_at_frame (frame), 0, type, MusicTime);
|
||||
const int32_t divisions = _editor->get_grid_music_divisions (event->button.state);
|
||||
_real_section = map.add_tempo (tempo, map.exact_qn_at_frame (frame, divisions), 0, type, MusicTime);
|
||||
} else {
|
||||
_real_section = map.add_tempo (tempo, 0.0, frame, type, AudioTime);
|
||||
}
|
||||
|
@ -3356,9 +3359,8 @@ TempoMarkerDrag::motion (GdkEvent* event, bool first_move)
|
|||
|
||||
if (ArdourKeyboard::indicates_constraint (event->button.state)) {
|
||||
/* use vertical movement to alter tempo .. should be log */
|
||||
double new_bpm = _real_section->beats_per_minute() + ((last_pointer_y() - current_pointer_y()) / 5.0);
|
||||
double new_bpm = max (1.5, _grab_bpm + ((grab_y() - min (-1.0, current_pointer_y())) / 5.0));
|
||||
stringstream strs;
|
||||
|
||||
_editor->session()->tempo_map().gui_change_tempo (_real_section, Tempo (new_bpm, _real_section->note_type()));
|
||||
strs << new_bpm;
|
||||
show_verbose_cursor_text (strs.str());
|
||||
|
@ -3425,7 +3427,7 @@ TempoMarkerDrag::aborted (bool moved)
|
|||
|
||||
BBTRulerDrag::BBTRulerDrag (Editor* e, ArdourCanvas::Item* i)
|
||||
: Drag (e, i)
|
||||
, _pulse (0.0)
|
||||
, _grab_qn (0.0)
|
||||
, _tempo (0)
|
||||
, before_state (0)
|
||||
{
|
||||
|
@ -3441,8 +3443,8 @@ BBTRulerDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
|
|||
_tempo = const_cast<TempoSection*> (&map.tempo_section_at_frame (raw_grab_frame()));
|
||||
ostringstream sstr;
|
||||
|
||||
sstr << "^" << fixed << setprecision(3) << map.tempo_at_frame (adjusted_current_frame (event)).beats_per_minute() << "\n";
|
||||
sstr << "<" << fixed << setprecision(3) << _tempo->beats_per_minute();
|
||||
sstr << "^" << fixed << setprecision(3) << map.tempo_at_frame (adjusted_current_frame (event)).note_types_per_minute() << "\n";
|
||||
sstr << "<" << fixed << setprecision(3) << _tempo->note_types_per_minute();
|
||||
show_verbose_cursor_text (sstr.str());
|
||||
finished (event, false);
|
||||
}
|
||||
|
@ -3465,9 +3467,9 @@ BBTRulerDrag::setup_pointer_frame_offset ()
|
|||
beat = floor (beat_at_frame) + (floor (((beat_at_frame - floor (beat_at_frame)) * 4)) / 4);
|
||||
}
|
||||
|
||||
_pulse = map.pulse_at_beat (beat);
|
||||
_grab_qn = map.quarter_note_at_beat (beat);
|
||||
|
||||
_pointer_frame_offset = raw_grab_frame() - map.frame_at_pulse (_pulse);
|
||||
_pointer_frame_offset = raw_grab_frame() - map.frame_at_quarter_note (_grab_qn);
|
||||
|
||||
}
|
||||
|
||||
|
@ -3492,11 +3494,11 @@ BBTRulerDrag::motion (GdkEvent* event, bool first_move)
|
|||
|
||||
if (ArdourKeyboard::indicates_constraint (event->button.state)) {
|
||||
/* adjust previous tempo to match pointer frame */
|
||||
_editor->session()->tempo_map().gui_dilate_tempo (_tempo, map.frame_at_pulse (_pulse), pf, _pulse);
|
||||
_editor->session()->tempo_map().gui_dilate_tempo (_tempo, map.frame_at_quarter_note (_grab_qn), pf);
|
||||
}
|
||||
ostringstream sstr;
|
||||
sstr << "^" << fixed << setprecision(3) << map.tempo_at_frame (pf).beats_per_minute() << "\n";
|
||||
sstr << "<" << fixed << setprecision(3) << _tempo->beats_per_minute();
|
||||
sstr << "^" << fixed << setprecision(3) << map.tempo_at_frame (pf).note_types_per_minute() << "\n";
|
||||
sstr << "<" << fixed << setprecision(3) << _tempo->note_types_per_minute();
|
||||
show_verbose_cursor_text (sstr.str());
|
||||
}
|
||||
|
||||
|
@ -5591,7 +5593,7 @@ NoteDrag::total_dx (const guint state) const
|
|||
frameoffset_t const dx = _editor->pixel_to_sample (_drags->current_pointer_x() - grab_x());
|
||||
|
||||
/* primary note time */
|
||||
double const quarter_note_start = (_region->region()->pulse() * 4.0) - _region->midi_region()->start_beats();
|
||||
double const quarter_note_start = _region->region()->quarter_note() - _region->midi_region()->start_beats();
|
||||
frameoffset_t const n = map.frame_at_quarter_note (quarter_note_start + _primary->note()->time().to_double());
|
||||
|
||||
/* new time of the primary note in session frames */
|
||||
|
|
|
@ -745,6 +745,7 @@ private:
|
|||
|
||||
bool _copy;
|
||||
bool _movable;
|
||||
double _grab_bpm;
|
||||
XMLNode* before_state;
|
||||
};
|
||||
|
||||
|
@ -770,7 +771,7 @@ public:
|
|||
void setup_pointer_frame_offset ();
|
||||
|
||||
private:
|
||||
double _pulse;
|
||||
double _grab_qn;
|
||||
ARDOUR::TempoSection* _tempo;
|
||||
XMLNode* before_state;
|
||||
};
|
||||
|
|
|
@ -1394,10 +1394,9 @@ Editor::toggle_marker_lock_style ()
|
|||
|
||||
const Meter meter (msp->divisions_per_bar(), msp->note_divisor());
|
||||
const Timecode::BBT_Time bbt (msp->bbt());
|
||||
const framepos_t frame = msp->frame();
|
||||
const PositionLockStyle pls = (msp->position_lock_style() == AudioTime) ? MusicTime : AudioTime;
|
||||
|
||||
_session->tempo_map().replace_meter (*msp, meter, bbt, frame, pls);
|
||||
_session->tempo_map().replace_meter (*msp, meter, bbt, pls);
|
||||
|
||||
XMLNode &after = _session->tempo_map().get_state();
|
||||
_session->add_command(new MementoCommand<TempoMap>(_session->tempo_map(), &before, &after));
|
||||
|
@ -1405,7 +1404,7 @@ Editor::toggle_marker_lock_style ()
|
|||
} else if (tm) {
|
||||
TempoSection* tsp = &tm->tempo();
|
||||
|
||||
const Tempo tempo (tsp->beats_per_minute());
|
||||
const Tempo tempo (tsp->note_types_per_minute(), tsp->note_type());
|
||||
const double pulse = tsp->pulse();
|
||||
const framepos_t frame = tsp->frame();
|
||||
const TempoSection::Type type = tsp->type();
|
||||
|
@ -1432,7 +1431,7 @@ Editor::toggle_tempo_type ()
|
|||
if (tm) {
|
||||
TempoSection* tsp = &tm->tempo();
|
||||
|
||||
const Tempo tempo (tsp->beats_per_minute(), tsp->note_type());
|
||||
const Tempo tempo (tsp->note_types_per_minute(), tsp->note_type());
|
||||
const double pulse = tsp->pulse();
|
||||
const framepos_t frame = tsp->frame();
|
||||
const TempoSection::Type type = (tsp->type() == TempoSection::Ramp) ? TempoSection::Constant : TempoSection::Ramp;
|
||||
|
|
|
@ -100,13 +100,13 @@ Editor::draw_metric_marks (const Metrics& metrics)
|
|||
}
|
||||
} else if ((ts = dynamic_cast<const TempoSection*>(*i)) != 0) {
|
||||
if (UIConfiguration::instance().get_allow_non_quarter_pulse()) {
|
||||
snprintf (buf, sizeof (buf), "%.3f/%.0f", ts->beats_per_minute(), ts->note_type());
|
||||
snprintf (buf, sizeof (buf), "%.3f/%.0f", ts->note_types_per_minute(), ts->note_type());
|
||||
} else {
|
||||
snprintf (buf, sizeof (buf), "%.3f", ts->beats_per_minute());
|
||||
snprintf (buf, sizeof (buf), "%.3f", ts->note_types_per_minute());
|
||||
}
|
||||
|
||||
max_tempo = max (max_tempo, ts->beats_per_minute());
|
||||
min_tempo = min (min_tempo, ts->beats_per_minute());
|
||||
max_tempo = max (max_tempo, ts->note_types_per_minute());
|
||||
min_tempo = min (min_tempo, ts->note_types_per_minute());
|
||||
|
||||
tempo_curves.push_back (new TempoCurve (*this, *tempo_group, UIConfiguration::instance().color ("tempo curve"),
|
||||
*(const_cast<TempoSection*>(ts)), ts->frame(), false));
|
||||
|
@ -147,7 +147,7 @@ Editor::draw_metric_marks (const Metrics& metrics)
|
|||
TempoMarker* tempo_marker;
|
||||
|
||||
if ((tempo_marker = dynamic_cast<TempoMarker*> (*x)) != 0) {
|
||||
tempo_marker->update_height_mark ((tempo_marker->tempo().beats_per_minute() - min_tempo) / max (10.0, max_tempo - min_tempo));
|
||||
tempo_marker->update_height_mark ((tempo_marker->tempo().note_types_per_minute() - min_tempo) / max (10.0, max_tempo - min_tempo));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -208,11 +208,17 @@ Editor::marker_position_changed ()
|
|||
if ((ts = &tempo_marker->tempo()) != 0) {
|
||||
tempo_marker->set_position (ts->frame ());
|
||||
char buf[64];
|
||||
snprintf (buf, sizeof (buf), "%.3f", ts->beats_per_minute());
|
||||
|
||||
if (UIConfiguration::instance().get_allow_non_quarter_pulse()) {
|
||||
snprintf (buf, sizeof (buf), "%.3f/%.0f", ts->note_types_per_minute(), ts->note_type());
|
||||
} else {
|
||||
snprintf (buf, sizeof (buf), "%.3f", ts->note_types_per_minute());
|
||||
}
|
||||
|
||||
tempo_marker->set_name (buf);
|
||||
|
||||
max_tempo = max (max_tempo, ts->beats_per_minute());
|
||||
min_tempo = min (min_tempo, ts->beats_per_minute());
|
||||
max_tempo = max (max_tempo, ts->note_types_per_minute());
|
||||
min_tempo = min (min_tempo, ts->note_types_per_minute());
|
||||
}
|
||||
}
|
||||
if ((meter_marker = dynamic_cast<MeterMarker*> (*x)) != 0) {
|
||||
|
@ -248,7 +254,7 @@ Editor::marker_position_changed ()
|
|||
for (Marks::iterator x = metric_marks.begin(); x != metric_marks.end(); ++x) {
|
||||
TempoMarker* tempo_marker;
|
||||
if ((tempo_marker = dynamic_cast<TempoMarker*> (*x)) != 0) {
|
||||
tempo_marker->update_height_mark ((tempo_marker->tempo().beats_per_minute() - min_tempo) / max (max_tempo - min_tempo, 10.0));
|
||||
tempo_marker->update_height_mark ((tempo_marker->tempo().note_types_per_minute() - min_tempo) / max (max_tempo - min_tempo, 10.0));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -362,7 +368,7 @@ Editor::mouse_add_new_tempo_event (framepos_t frame)
|
|||
TempoMap& map(_session->tempo_map());
|
||||
|
||||
begin_reversible_command (_("add tempo mark"));
|
||||
const double pulse = map.pulse_at_frame (frame);
|
||||
const double pulse = map.exact_qn_at_frame (frame, get_grid_music_divisions (0)) / 4.0;
|
||||
|
||||
if (pulse > 0.0) {
|
||||
XMLNode &before = map.get_state();
|
||||
|
@ -409,9 +415,9 @@ Editor::mouse_add_new_meter_event (framepos_t frame)
|
|||
XMLNode &before = map.get_state();
|
||||
|
||||
if (meter_dialog.get_lock_style() == MusicTime) {
|
||||
map.add_meter (Meter (bpb, note_type), beat, requested, map.frame_at_beat (beat), MusicTime);
|
||||
map.add_meter (Meter (bpb, note_type), beat, requested, MusicTime);
|
||||
} else {
|
||||
map.add_meter (Meter (bpb, note_type), beat, requested, map.frame_at_beat (beat), AudioTime);
|
||||
map.add_meter (Meter (bpb, note_type), beat, requested, AudioTime);
|
||||
}
|
||||
|
||||
_session->add_command(new MementoCommand<TempoMap>(map, &before, &map.get_state()));
|
||||
|
@ -462,13 +468,12 @@ Editor::edit_meter_section (MeterSection* section)
|
|||
Timecode::BBT_Time when;
|
||||
meter_dialog.get_bbt_time (when);
|
||||
|
||||
framepos_t const frame = _session->tempo_map().frame_at_bbt (when);
|
||||
const PositionLockStyle pls = (meter_dialog.get_lock_style() == AudioTime) ? AudioTime : MusicTime;
|
||||
|
||||
begin_reversible_command (_("replace meter mark"));
|
||||
XMLNode &before = _session->tempo_map().get_state();
|
||||
|
||||
_session->tempo_map().replace_meter (*section, meter, when, frame, pls);
|
||||
_session->tempo_map().replace_meter (*section, meter, when, pls);
|
||||
|
||||
XMLNode &after = _session->tempo_map().get_state();
|
||||
_session->add_command(new MementoCommand<TempoMap>(_session->tempo_map(), &before, &after));
|
||||
|
|
|
@ -1711,7 +1711,7 @@ MidiRegionView::update_sustained (Note* ev, bool update_ghost_regions)
|
|||
const boost::shared_ptr<ARDOUR::MidiRegion> mr = midi_region();
|
||||
boost::shared_ptr<NoteType> note = ev->note();
|
||||
|
||||
const double session_source_start = (_region->pulse() * 4.0) - mr->start_beats();
|
||||
const double session_source_start = _region->quarter_note() - mr->start_beats();
|
||||
const framepos_t note_start_frames = map.frame_at_quarter_note (note->time().to_double() + session_source_start) - _region->position();
|
||||
|
||||
const double x0 = trackview.editor().sample_to_pixel (note_start_frames);
|
||||
|
@ -1779,7 +1779,7 @@ MidiRegionView::update_hit (Hit* ev, bool update_ghost_regions)
|
|||
{
|
||||
boost::shared_ptr<NoteType> note = ev->note();
|
||||
|
||||
const double note_time_qn = note->time().to_double() + ((_region->pulse() * 4.0) - midi_region()->start_beats());
|
||||
const double note_time_qn = note->time().to_double() + (_region->quarter_note() - midi_region()->start_beats());
|
||||
const framepos_t note_start_frames = trackview.session()->tempo_map().frame_at_quarter_note (note_time_qn) - _region->position();
|
||||
|
||||
const double x = trackview.editor().sample_to_pixel(note_start_frames);
|
||||
|
@ -2595,7 +2595,7 @@ MidiRegionView::note_dropped(NoteBase *, frameoffset_t dt, int8_t dnote)
|
|||
|
||||
for (Selection::iterator i = _selection.begin(); i != _selection.end() ; ++i) {
|
||||
|
||||
double const start_qn = (_region->pulse() * 4.0) - midi_region()->start_beats();
|
||||
double const start_qn = _region->quarter_note() - midi_region()->start_beats();
|
||||
framepos_t new_frames = map.frame_at_quarter_note (start_qn + (*i)->note()->time().to_double()) + dt;
|
||||
Evoral::Beats new_time = Evoral::Beats (map.quarter_note_at_frame (new_frames) - start_qn);
|
||||
if (new_time < 0) {
|
||||
|
@ -2922,7 +2922,7 @@ MidiRegionView::commit_resizing (NoteBase* primary, bool at_front, double delta_
|
|||
|
||||
/* and then to beats */
|
||||
const double e_qaf = tmap.exact_qn_at_frame (current_fr + midi_region()->position(), divisions);
|
||||
const double quarter_note_start = (_region->pulse() * 4.0) - midi_region()->start_beats();
|
||||
const double quarter_note_start = _region->quarter_note() - midi_region()->start_beats();
|
||||
const Evoral::Beats x_beats = Evoral::Beats (e_qaf - quarter_note_start);
|
||||
|
||||
if (at_front && x_beats < canvas_note->note()->end_time()) {
|
||||
|
@ -3577,14 +3577,14 @@ MidiRegionView::paste_internal (framepos_t pos, unsigned paste_count, float time
|
|||
const Evoral::Beats duration = last_time - first_time;
|
||||
const Evoral::Beats snap_duration = duration.snap_to(snap_beats);
|
||||
const Evoral::Beats paste_offset = snap_duration * paste_count;
|
||||
const Evoral::Beats pos_beats = absolute_frames_to_source_beats(pos) + paste_offset;
|
||||
const Evoral::Beats quarter_note = absolute_frames_to_source_beats(pos) + paste_offset;
|
||||
Evoral::Beats end_point = Evoral::Beats();
|
||||
|
||||
DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("Paste data spans from %1 to %2 (%3) ; paste pos beats = %4 (based on %5 - %6)\n",
|
||||
first_time,
|
||||
last_time,
|
||||
duration, pos, _region->position(),
|
||||
pos_beats));
|
||||
quarter_note));
|
||||
|
||||
clear_editor_note_selection ();
|
||||
|
||||
|
@ -3593,7 +3593,7 @@ MidiRegionView::paste_internal (framepos_t pos, unsigned paste_count, float time
|
|||
for (Notes::const_iterator i = mcb.notes().begin(); i != mcb.notes().end(); ++i) {
|
||||
|
||||
boost::shared_ptr<NoteType> copied_note (new NoteType (*((*i).get())));
|
||||
copied_note->set_time (pos_beats + copied_note->time() - first_time);
|
||||
copied_note->set_time (quarter_note + copied_note->time() - first_time);
|
||||
copied_note->set_id (Evoral::next_event_id());
|
||||
|
||||
/* make all newly added notes selected */
|
||||
|
@ -4149,7 +4149,7 @@ MidiRegionView::snap_frame_to_grid_underneath (framepos_t p, int32_t divisions,
|
|||
eqaf -= grid_beats.to_double();
|
||||
}
|
||||
}
|
||||
const double session_start_off = (_region->pulse() * 4.0) - midi_region()->start_beats();
|
||||
const double session_start_off = _region->quarter_note() - midi_region()->start_beats();
|
||||
|
||||
return Evoral::Beats (eqaf - session_start_off);
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ void TempoCurve::setup_sizes(const double timebar_height)
|
|||
{
|
||||
curve_height = floor (timebar_height) - 2.5;
|
||||
}
|
||||
|
||||
/* ignores Tempo note type - only note_types_per_minute is potentially curved */
|
||||
TempoCurve::TempoCurve (PublicEditor& ed, ArdourCanvas::Container& parent, guint32 rgba, ARDOUR::TempoSection& temp, framepos_t frame, bool handle_events)
|
||||
|
||||
: editor (ed)
|
||||
|
@ -34,8 +34,8 @@ TempoCurve::TempoCurve (PublicEditor& ed, ArdourCanvas::Container& parent, guint
|
|||
, _curve (0)
|
||||
, _shown (false)
|
||||
, _color (rgba)
|
||||
, _min_tempo (temp.beats_per_minute())
|
||||
, _max_tempo (temp.beats_per_minute())
|
||||
, _min_tempo (temp.note_types_per_minute())
|
||||
, _max_tempo (temp.note_types_per_minute())
|
||||
, _tempo (temp)
|
||||
|
||||
{
|
||||
|
@ -44,12 +44,12 @@ TempoCurve::TempoCurve (PublicEditor& ed, ArdourCanvas::Container& parent, guint
|
|||
|
||||
group = new ArdourCanvas::Container (&parent, ArdourCanvas::Duple (unit_position, 1));
|
||||
#ifdef CANVAS_DEBUG
|
||||
group->name = string_compose ("TempoCurve::group for %1", _tempo.beats_per_minute());
|
||||
group->name = string_compose ("TempoCurve::group for %1", _tempo.note_types_per_minute());
|
||||
#endif
|
||||
|
||||
_curve = new ArdourCanvas::FramedCurve (group);
|
||||
#ifdef CANVAS_DEBUG
|
||||
_curve->name = string_compose ("TempoCurve::curve for %1", _tempo.beats_per_minute());
|
||||
_curve->name = string_compose ("TempoCurve::curve for %1", _tempo.note_types_per_minute());
|
||||
#endif
|
||||
_curve->set_points_per_segment (3);
|
||||
points = new ArdourCanvas::Points ();
|
||||
|
@ -113,14 +113,14 @@ TempoCurve::set_position (framepos_t frame, framepos_t end_frame)
|
|||
points->push_back (ArdourCanvas::Duple (0.0, curve_height));
|
||||
|
||||
if (end_frame == (framepos_t) UINT32_MAX) {
|
||||
const double tempo_at = _tempo.beats_per_minute();
|
||||
const double tempo_at = _tempo.note_types_per_minute();
|
||||
const double y_pos = (curve_height) - (((tempo_at - _min_tempo) / (_max_tempo - _min_tempo)) * curve_height);
|
||||
|
||||
points->push_back (ArdourCanvas::Duple (0.0, y_pos));
|
||||
points->push_back (ArdourCanvas::Duple (ArdourCanvas::COORD_MAX - 5.0, y_pos));
|
||||
|
||||
} else if (_tempo.type() == ARDOUR::TempoSection::Constant) {
|
||||
const double tempo_at = _tempo.beats_per_minute();
|
||||
const double tempo_at = _tempo.note_types_per_minute();
|
||||
const double y_pos = (curve_height) - (((tempo_at - _min_tempo) / (_max_tempo - _min_tempo)) * curve_height);
|
||||
|
||||
points->push_back (ArdourCanvas::Duple (0.0, y_pos));
|
||||
|
@ -131,7 +131,7 @@ TempoCurve::set_position (framepos_t frame, framepos_t end_frame)
|
|||
framepos_t current_frame = frame;
|
||||
|
||||
while (current_frame < (end_frame - frame_step)) {
|
||||
const double tempo_at = _tempo.tempo_at_frame (current_frame, editor.session()->frame_rate());
|
||||
const double tempo_at = _tempo.tempo_at_minute (_tempo.minute_at_frame (current_frame)).note_types_per_minute();
|
||||
const double y_pos = max ((curve_height) - (((tempo_at - _min_tempo) / (_max_tempo - _min_tempo)) * curve_height), 0.0);
|
||||
|
||||
points->push_back (ArdourCanvas::Duple (editor.sample_to_pixel (current_frame - frame), min (y_pos, curve_height)));
|
||||
|
@ -139,7 +139,7 @@ TempoCurve::set_position (framepos_t frame, framepos_t end_frame)
|
|||
current_frame += frame_step;
|
||||
}
|
||||
|
||||
const double tempo_at = _tempo.tempo_at_frame (end_frame, editor.session()->frame_rate());
|
||||
const double tempo_at = _tempo.tempo_at_minute (_tempo.minute_at_frame (end_frame)).note_types_per_minute();
|
||||
const double y_pos = max ((curve_height) - (((tempo_at - _min_tempo) / (_max_tempo - _min_tempo)) * curve_height), 0.0);
|
||||
|
||||
points->push_back (ArdourCanvas::Duple (editor.sample_to_pixel ((end_frame - 1) - frame), min (y_pos, curve_height)));
|
||||
|
|
|
@ -48,7 +48,7 @@ TempoDialog::TempoDialog (TempoMap& map, framepos_t frame, const string&)
|
|||
Tempo tempo (map.tempo_at_frame (frame));
|
||||
Timecode::BBT_Time when (map.bbt_at_frame (frame));
|
||||
|
||||
init (when, tempo.beats_per_minute(), tempo.note_type(), TempoSection::Constant, true, MusicTime);
|
||||
init (when, tempo.note_types_per_minute(), tempo.note_type(), TempoSection::Constant, true, MusicTime);
|
||||
}
|
||||
|
||||
TempoDialog::TempoDialog (TempoMap& map, TempoSection& section, const string&)
|
||||
|
@ -63,7 +63,7 @@ TempoDialog::TempoDialog (TempoMap& map, TempoSection& section, const string&)
|
|||
, tap_tempo_button (_("Tap tempo"))
|
||||
{
|
||||
Timecode::BBT_Time when (map.bbt_at_frame (section.frame()));
|
||||
init (when, section.beats_per_minute(), section.note_type(), section.type(), section.movable(), section.position_lock_style());
|
||||
init (when, section.note_types_per_minute(), section.note_type(), section.type(), section.movable(), section.position_lock_style());
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -77,11 +77,11 @@ TempoLines::draw_ticks (std::vector<ARDOUR::TempoMap::BBTPoint>& grid,
|
|||
if (grid.begin()->c != 0.0) {
|
||||
const double beat_divisions = (l / ((double) divisions)) * (grid.begin()->tempo.note_type() / grid.begin()->meter.note_divisor());
|
||||
const double time_at_division = log (((grid.begin()->c * (beat_divisions)) /
|
||||
grid.begin()->tempo.beats_per_minute()) + 1) / grid.begin()->c;
|
||||
grid.begin()->tempo.note_types_per_minute()) + 1) / grid.begin()->c;
|
||||
|
||||
f = grid.begin()->frame + (framecnt_t) floor ((time_at_division * 60.0 * frame_rate) + 0.5);
|
||||
} else {
|
||||
const double fpb = grid.begin()->tempo.frames_per_beat (frame_rate)
|
||||
const double fpb = grid.begin()->tempo.frames_per_note_type (frame_rate)
|
||||
* (grid.begin()->tempo.note_type() / grid.begin()->meter.note_divisor());
|
||||
|
||||
f = grid.begin()->frame + (l * (fpb / (double) divisions));
|
||||
|
|
|
@ -161,8 +161,6 @@ class LIBARDOUR_API MidiRegion : public Region
|
|||
PBD::ScopedConnection _model_connection;
|
||||
PBD::ScopedConnection _source_connection;
|
||||
PBD::ScopedConnection _model_contents_connection;
|
||||
|
||||
double _last_length_beats;
|
||||
};
|
||||
|
||||
} /* namespace ARDOUR */
|
||||
|
|
|
@ -175,10 +175,12 @@ class LIBARDOUR_API Region
|
|||
void set_position_lock_style (PositionLockStyle ps);
|
||||
void recompute_position_from_lock_style (const int32_t sub_num);
|
||||
|
||||
/* meter-based beat at the region position */
|
||||
double beat () const { return _beat; }
|
||||
void set_beat (double beat) { _beat = beat; }
|
||||
double pulse () const { return _pulse; }
|
||||
void set_pulse (double pulse) { _pulse = pulse; }
|
||||
/* quarter-note at the region position */
|
||||
double quarter_note () const { return _quarter_note; }
|
||||
void set_quarter_note (double qn) { _quarter_note = qn; }
|
||||
|
||||
void suspend_property_changes ();
|
||||
|
||||
|
@ -380,7 +382,7 @@ class LIBARDOUR_API Region
|
|||
/** Sync position relative to the start of our file */
|
||||
PBD::Property<framepos_t> _sync_position;
|
||||
|
||||
double _pulse;
|
||||
double _quarter_note;
|
||||
|
||||
SourceList _sources;
|
||||
/** Used when timefx are applied, so we can always use the original source */
|
||||
|
|
|
@ -50,30 +50,36 @@ class TempoMap;
|
|||
class LIBARDOUR_API Tempo {
|
||||
public:
|
||||
/**
|
||||
* @param bpm Beats Per Minute
|
||||
* @param npm Note Types per minute
|
||||
* @param type Note Type (default `4': quarter note)
|
||||
*/
|
||||
Tempo (double bpm, double type=4.0) // defaulting to quarter note
|
||||
: _beats_per_minute (bpm), _note_type(type) {}
|
||||
Tempo (double npm, double type=4.0) // defaulting to quarter note
|
||||
: _note_types_per_minute (npm), _note_type(type) {}
|
||||
|
||||
/*
|
||||
quarter note beats as distinct from a beat derived from meter and pulse.
|
||||
*/
|
||||
double beats_per_minute () const { return _beats_per_minute; }
|
||||
void set_beats_per_minute (double bpm) { _beats_per_minute = bpm; }
|
||||
double note_types_per_minute () const { return _note_types_per_minute; }
|
||||
double note_types_per_minute (double note_type) const { return (_note_types_per_minute / _note_type) * note_type; }
|
||||
void set_note_types_per_minute (double npm) { _note_types_per_minute = npm; }
|
||||
double note_type () const { return _note_type; }
|
||||
/** audio samples per beat
|
||||
|
||||
double quarter_notes_per_minute () const { return note_types_per_minute (4.0); }
|
||||
double pulses_per_minute () const { return note_types_per_minute (1.0); }
|
||||
/** audio samples per note type.
|
||||
* if you want an instantaneous value for this, use TempoMap::frames_per_quarter_note_at() instead.
|
||||
* @param sr samplerate
|
||||
*/
|
||||
double frames_per_beat (framecnt_t sr) const {
|
||||
return (60.0 * sr) / _beats_per_minute;
|
||||
double frames_per_note_type (framecnt_t sr) const {
|
||||
return (60.0 * sr) / _note_types_per_minute;
|
||||
}
|
||||
double frames_per_pulse (framecnt_t sr) const {
|
||||
return (_note_type * 60.0 * sr) / _beats_per_minute;
|
||||
/** audio samples per quarter note.
|
||||
* if you want an instantaneous value for this, use TempoMap::frames_per_quarter_note_at() instead.
|
||||
* @param sr samplerate
|
||||
*/
|
||||
double frames_per_quarter_note (framecnt_t sr) const {
|
||||
return (60.0 * sr) / quarter_notes_per_minute ();
|
||||
}
|
||||
|
||||
protected:
|
||||
double _beats_per_minute;
|
||||
double _note_types_per_minute;
|
||||
double _note_type;
|
||||
};
|
||||
|
||||
|
@ -105,19 +111,21 @@ class LIBARDOUR_API Meter {
|
|||
/** A section of timeline with a certain Tempo or Meter. */
|
||||
class LIBARDOUR_API MetricSection {
|
||||
public:
|
||||
MetricSection (double pulse, framepos_t frame, PositionLockStyle pls, bool is_tempo)
|
||||
: _pulse (pulse), _frame (frame), _movable (true), _position_lock_style (pls), _is_tempo (is_tempo) {}
|
||||
MetricSection (double pulse, double minute, PositionLockStyle pls, bool is_tempo, framecnt_t sample_rate)
|
||||
: _pulse (pulse), _minute (minute), _movable (true), _position_lock_style (pls), _is_tempo (is_tempo), _sample_rate (sample_rate) {}
|
||||
|
||||
virtual ~MetricSection() {}
|
||||
|
||||
const double& pulse () const { return _pulse; }
|
||||
void set_pulse (double pulse) { _pulse = pulse; }
|
||||
|
||||
framepos_t frame() const { return _frame; }
|
||||
virtual void set_frame (framepos_t f) {
|
||||
_frame = f;
|
||||
double minute() const { return _minute; }
|
||||
virtual void set_minute (double m) {
|
||||
_minute = m;
|
||||
}
|
||||
|
||||
framepos_t frame () const { return frame_at_minute (_minute); }
|
||||
|
||||
void set_movable (bool yn) { _movable = yn; }
|
||||
bool movable() const { return _movable; }
|
||||
|
||||
|
@ -131,21 +139,26 @@ class LIBARDOUR_API MetricSection {
|
|||
void set_position_lock_style (PositionLockStyle ps) { _position_lock_style = ps; }
|
||||
bool is_tempo () const { return _is_tempo; }
|
||||
|
||||
framepos_t frame_at_minute (const double& time) const;
|
||||
double minute_at_frame (const framepos_t& frame) const;
|
||||
|
||||
private:
|
||||
|
||||
double _pulse;
|
||||
framepos_t _frame;
|
||||
double _minute;
|
||||
bool _movable;
|
||||
PositionLockStyle _position_lock_style;
|
||||
const bool _is_tempo;
|
||||
framecnt_t _sample_rate;
|
||||
};
|
||||
|
||||
/** A section of timeline with a certain Meter. */
|
||||
class LIBARDOUR_API MeterSection : public MetricSection, public Meter {
|
||||
public:
|
||||
MeterSection (double pulse, framepos_t frame, double beat, const Timecode::BBT_Time& bbt, double bpb, double note_type, PositionLockStyle pls)
|
||||
: MetricSection (pulse, frame, pls, false), Meter (bpb, note_type), _bbt (bbt), _beat (beat) {}
|
||||
MeterSection (double pulse, double minute, double beat, const Timecode::BBT_Time& bbt, double bpb, double note_type, PositionLockStyle pls, framecnt_t sr)
|
||||
: MetricSection (pulse, minute, pls, false, sr), Meter (bpb, note_type), _bbt (bbt), _beat (beat) {}
|
||||
|
||||
MeterSection (const XMLNode&);
|
||||
MeterSection (const XMLNode&, const framecnt_t sample_rate);
|
||||
|
||||
static const std::string xml_state_node_name;
|
||||
|
||||
|
@ -173,10 +186,10 @@ class LIBARDOUR_API TempoSection : public MetricSection, public Tempo {
|
|||
Constant,
|
||||
};
|
||||
|
||||
TempoSection (const double& pulse, const framepos_t& frame, double qpm, double note_type, Type tempo_type, PositionLockStyle pls)
|
||||
: MetricSection (pulse, frame, pls, true), Tempo (qpm, note_type), _type (tempo_type), _c_func (0.0), _active (true), _locked_to_meter (false) {}
|
||||
TempoSection (const double& pulse, const double& minute, double qpm, double note_type, Type tempo_type, PositionLockStyle pls, framecnt_t sr)
|
||||
: MetricSection (pulse, minute, pls, true, sr), Tempo (qpm, note_type), _type (tempo_type), _c_func (0.0), _active (true), _locked_to_meter (false) {}
|
||||
|
||||
TempoSection (const XMLNode&);
|
||||
TempoSection (const XMLNode&, const framecnt_t sample_rate);
|
||||
|
||||
static const std::string xml_state_node_name;
|
||||
|
||||
|
@ -194,25 +207,25 @@ class LIBARDOUR_API TempoSection : public MetricSection, public Tempo {
|
|||
bool locked_to_meter () const { return _locked_to_meter; }
|
||||
void set_locked_to_meter (bool yn) { _locked_to_meter = yn; }
|
||||
|
||||
double tempo_at_frame (const framepos_t& frame, const framecnt_t& frame_rate) const;
|
||||
framepos_t frame_at_tempo (const double& ppm, const double& beat, const framecnt_t& frame_rate) const;
|
||||
Tempo tempo_at_minute (const double& minute) const;
|
||||
double minute_at_ntpm (const double& ntpm, const double& pulse) const;
|
||||
|
||||
double tempo_at_pulse (const double& pulse) const;
|
||||
double pulse_at_tempo (const double& ppm, const framepos_t& frame, const framecnt_t& frame_rate) const;
|
||||
Tempo tempo_at_pulse (const double& pulse) const;
|
||||
double pulse_at_ntpm (const double& ntpm, const double& minute) const;
|
||||
|
||||
double pulse_at_frame (const framepos_t& frame, const framepos_t& frame_rate) const;
|
||||
framepos_t frame_at_pulse (const double& pulse, const framecnt_t& frame_rate) const;
|
||||
double pulse_at_minute (const double& minute) const;
|
||||
double minute_at_pulse (const double& pulse) const;
|
||||
|
||||
double compute_c_func_pulse (const double& end_bpm, const double& end_pulse, const framecnt_t& frame_rate);
|
||||
double compute_c_func_frame (const double& end_bpm, const framepos_t& end_frame, const framecnt_t& frame_rate) const;
|
||||
double compute_c_func_pulse (const double& end_ntpm, const double& end_pulse) const;
|
||||
double compute_c_func_minute (const double& end_ntpm, const double& end_minute) const;
|
||||
|
||||
double pulse_at_frame (const framepos_t& frame) const;
|
||||
framepos_t frame_at_pulse (const double& pulse) const;
|
||||
|
||||
Timecode::BBT_Time legacy_bbt () { return _legacy_bbt; }
|
||||
|
||||
private:
|
||||
|
||||
framepos_t minute_to_frame (const double& time, const framecnt_t& frame_rate) const;
|
||||
double frame_to_minute (const framepos_t& frame, const framecnt_t& frame_rate) const;
|
||||
|
||||
/* tempo ramp functions. zero-based with time in minutes,
|
||||
* 'tick tempo' in ticks per minute and tempo in bpm.
|
||||
* time relative to section start.
|
||||
|
@ -252,11 +265,11 @@ typedef std::list<MetricSection*> Metrics;
|
|||
class LIBARDOUR_API TempoMetric {
|
||||
public:
|
||||
TempoMetric (const Meter& m, const Tempo& t)
|
||||
: _meter (&m), _tempo (&t), _frame (0), _pulse (0.0) {}
|
||||
: _meter (&m), _tempo (&t), _minute (0.0), _pulse (0.0) {}
|
||||
|
||||
void set_tempo (const Tempo& t) { _tempo = &t; }
|
||||
void set_meter (const Meter& m) { _meter = &m; }
|
||||
void set_frame (framepos_t f) { _frame = f; }
|
||||
void set_minute (double m) { _minute = m; }
|
||||
void set_pulse (const double& p) { _pulse = p; }
|
||||
|
||||
void set_metric (const MetricSection* section) {
|
||||
|
@ -268,19 +281,19 @@ class LIBARDOUR_API TempoMetric {
|
|||
set_tempo(*tempo);
|
||||
}
|
||||
|
||||
set_frame (section->frame());
|
||||
set_minute (section->minute());
|
||||
set_pulse (section->pulse());
|
||||
}
|
||||
|
||||
const Meter& meter() const { return *_meter; }
|
||||
const Tempo& tempo() const { return *_tempo; }
|
||||
framepos_t frame() const { return _frame; }
|
||||
double minute() const { return _minute; }
|
||||
const double& pulse() const { return _pulse; }
|
||||
|
||||
private:
|
||||
const Meter* _meter;
|
||||
const Tempo* _tempo;
|
||||
framepos_t _frame;
|
||||
double _minute;
|
||||
double _pulse;
|
||||
};
|
||||
|
||||
|
@ -310,7 +323,7 @@ class LIBARDOUR_API TempoMap : public PBD::StatefulDestructible
|
|||
|
||||
BBTPoint (const MeterSection& m, const Tempo& t, framepos_t f,
|
||||
uint32_t b, uint32_t e, double func_c)
|
||||
: frame (f), meter (m.divisions_per_bar(), m.note_divisor()), tempo (t.beats_per_minute(), t.note_type()), c (func_c), bar (b), beat (e) {}
|
||||
: frame (f), meter (m.divisions_per_bar(), m.note_divisor()), tempo (t.note_types_per_minute(), t.note_type()), c (func_c), bar (b), beat (e) {}
|
||||
|
||||
Timecode::BBT_Time bbt() const { return Timecode::BBT_Time (bar, beat, 0); }
|
||||
operator Timecode::BBT_Time() const { return bbt(); }
|
||||
|
@ -329,8 +342,8 @@ class LIBARDOUR_API TempoMap : public PBD::StatefulDestructible
|
|||
static const Tempo& default_tempo() { return _default_tempo; }
|
||||
static const Meter& default_meter() { return _default_meter; }
|
||||
|
||||
/* because tempos may be ramped, this is only valid for the instant requested.*/
|
||||
double frames_per_beat_at (const framepos_t&, const framecnt_t& sr) const;
|
||||
/* because tempi may be ramped, this is only valid for the instant requested.*/
|
||||
double frames_per_quarter_note_at (const framepos_t&, const framecnt_t& sr) const;
|
||||
|
||||
const TempoSection& tempo_section_at_frame (framepos_t frame) const;
|
||||
const MeterSection& meter_section_at_frame (framepos_t frame) const;
|
||||
|
@ -348,7 +361,7 @@ class LIBARDOUR_API TempoMap : public PBD::StatefulDestructible
|
|||
* @param where bbt position of new section
|
||||
* @param frame frame position of new section. ignored if pls == MusicTime
|
||||
*/
|
||||
MeterSection* add_meter (const Meter&, const double& beat, const Timecode::BBT_Time& where, const framepos_t& frame, PositionLockStyle pls);
|
||||
MeterSection* add_meter (const Meter&, const double& beat, const Timecode::BBT_Time& where, PositionLockStyle pls);
|
||||
|
||||
void remove_tempo (const TempoSection&, bool send_signal);
|
||||
void remove_meter (const MeterSection&, bool send_signal);
|
||||
|
@ -356,8 +369,7 @@ class LIBARDOUR_API TempoMap : public PBD::StatefulDestructible
|
|||
void replace_tempo (const TempoSection&, const Tempo&, const double& pulse, const framepos_t& frame
|
||||
, TempoSection::Type type, PositionLockStyle pls);
|
||||
|
||||
void replace_meter (const MeterSection&, const Meter&, const Timecode::BBT_Time& where, const framepos_t& frame
|
||||
, PositionLockStyle pls);
|
||||
void replace_meter (const MeterSection&, const Meter&, const Timecode::BBT_Time& where, PositionLockStyle pls);
|
||||
|
||||
framepos_t round_to_bar (framepos_t frame, RoundMode dir);
|
||||
framepos_t round_to_beat (framepos_t frame, RoundMode dir);
|
||||
|
@ -394,7 +406,7 @@ class LIBARDOUR_API TempoMap : public PBD::StatefulDestructible
|
|||
|
||||
/* TEMPO- AND METER-SENSITIVE FUNCTIONS
|
||||
|
||||
bbt_at_frame(), frame_at_bbt(), beat_at_frame(), frame_at_beat(), tempo_at_beat()
|
||||
bbt_at_frame(), frame_at_bbt(), beat_at_frame(), frame_at_beat()
|
||||
and bbt_duration_at()
|
||||
are all sensitive to tempo and meter, and will give answers
|
||||
that align with the grid formed by tempo and meter sections.
|
||||
|
@ -406,20 +418,11 @@ class LIBARDOUR_API TempoMap : public PBD::StatefulDestructible
|
|||
double beat_at_frame (const framecnt_t& frame) const;
|
||||
framepos_t frame_at_beat (const double& beat) const;
|
||||
|
||||
Tempo tempo_at_frame (const framepos_t& frame) const;
|
||||
framepos_t frame_at_tempo (const Tempo& tempo) const;
|
||||
|
||||
Tempo tempo_at_beat (const double& beat) const;
|
||||
|
||||
const Meter& meter_at_frame (framepos_t) const;
|
||||
|
||||
double pulse_at_beat (const double& beat) const;
|
||||
double beat_at_pulse (const double& pulse) const;
|
||||
|
||||
double pulse_at_frame (const framecnt_t& frame) const;
|
||||
framepos_t frame_at_pulse (const double& pulse) const;
|
||||
|
||||
/* bbt - it's nearly always better to use beats.*/
|
||||
/* bbt - it's nearly always better to use meter-based beat (above)
|
||||
unless tick resolution is desirable.
|
||||
*/
|
||||
Timecode::BBT_Time bbt_at_frame (framepos_t when);
|
||||
Timecode::BBT_Time bbt_at_frame_rt (framepos_t when);
|
||||
framepos_t frame_at_bbt (const Timecode::BBT_Time&);
|
||||
|
@ -427,11 +430,12 @@ class LIBARDOUR_API TempoMap : public PBD::StatefulDestructible
|
|||
double beat_at_bbt (const Timecode::BBT_Time& bbt);
|
||||
Timecode::BBT_Time bbt_at_beat (const double& beats);
|
||||
|
||||
double pulse_at_bbt (const Timecode::BBT_Time& bbt);
|
||||
double pulse_at_bbt_rt (const Timecode::BBT_Time& bbt);
|
||||
Timecode::BBT_Time bbt_at_pulse (const double& pulse);
|
||||
double quarter_note_at_bbt (const Timecode::BBT_Time& bbt);
|
||||
double quarter_note_at_bbt_rt (const Timecode::BBT_Time& bbt);
|
||||
Timecode::BBT_Time bbt_at_quarter_note (const double& quarter_note);
|
||||
|
||||
framecnt_t bbt_duration_at (framepos_t, const Timecode::BBT_Time&, int dir);
|
||||
framepos_t framepos_plus_bbt (framepos_t pos, Timecode::BBT_Time b) const;
|
||||
|
||||
/* TEMPO-SENSITIVE FUNCTIONS
|
||||
|
||||
|
@ -446,21 +450,32 @@ class LIBARDOUR_API TempoMap : public PBD::StatefulDestructible
|
|||
framepos_t framepos_plus_qn (framepos_t, Evoral::Beats) const;
|
||||
Evoral::Beats framewalk_to_qn (framepos_t pos, framecnt_t distance) const;
|
||||
|
||||
framepos_t framepos_plus_bbt (framepos_t pos, Timecode::BBT_Time b) const;
|
||||
/* quarter note related functions are also tempo-sensitive and ignore meter.
|
||||
quarter notes may be compared with and assigned to Evoral::Beats.
|
||||
*/
|
||||
double quarter_note_at_frame (const framepos_t frame) const;
|
||||
double quarter_note_at_frame_rt (const framepos_t frame) const;
|
||||
framepos_t frame_at_quarter_note (const double quarter_note) const;
|
||||
|
||||
framecnt_t frames_between_quarter_notes (const double start, const double end) const;
|
||||
double quarter_notes_between_frames (const framecnt_t start, const framecnt_t end) const;
|
||||
|
||||
double quarter_note_at_frame (const framepos_t frame);
|
||||
double quarter_note_at_frame_rt (const framepos_t frame);
|
||||
framepos_t frame_at_quarter_note (const double quarter_note);
|
||||
double quarter_note_at_beat (const double beat);
|
||||
double beat_at_quarter_note (const double beat);
|
||||
|
||||
/* obtain a musical subdivision via a frame position and magic note divisor.*/
|
||||
double exact_qn_at_frame (const framepos_t& frame, const int32_t sub_num);
|
||||
double exact_beat_at_frame (const framepos_t& frame, const int32_t sub_num);
|
||||
|
||||
Tempo tempo_at_frame (const framepos_t& frame) const;
|
||||
framepos_t frame_at_tempo (const Tempo& tempo) const;
|
||||
Tempo tempo_at_quarter_note (const double& beat) const;
|
||||
double quarter_note_at_tempo (const Tempo& tempo) const;
|
||||
|
||||
void gui_move_tempo (TempoSection*, const framepos_t& frame, const int& sub_num);
|
||||
void gui_move_meter (MeterSection*, const framepos_t& frame);
|
||||
bool gui_change_tempo (TempoSection*, const Tempo& bpm);
|
||||
void gui_dilate_tempo (TempoSection* tempo, const framepos_t& frame, const framepos_t& end_frame, const double& pulse);
|
||||
|
||||
double exact_beat_at_frame (const framepos_t& frame, const int32_t sub_num);
|
||||
double exact_qn_at_frame (const framepos_t& frame, const int32_t sub_num);
|
||||
void gui_dilate_tempo (TempoSection* tempo, const framepos_t& frame, const framepos_t& end_frame);
|
||||
|
||||
std::pair<double, framepos_t> predict_tempo_position (TempoSection* section, const Timecode::BBT_Time& bbt);
|
||||
bool can_solve_bbt (TempoSection* section, const Timecode::BBT_Time& bbt);
|
||||
|
@ -470,20 +485,23 @@ class LIBARDOUR_API TempoMap : public PBD::StatefulDestructible
|
|||
|
||||
private:
|
||||
|
||||
double beat_at_frame_locked (const Metrics& metrics, const framecnt_t& frame) const;
|
||||
framepos_t frame_at_beat_locked (const Metrics& metrics, const double& beat) const;
|
||||
double beat_at_minute_locked (const Metrics& metrics, const double& minute) const;
|
||||
double minute_at_beat_locked (const Metrics& metrics, const double& beat) const;
|
||||
|
||||
double pulse_at_beat_locked (const Metrics& metrics, const double& beat) const;
|
||||
double beat_at_pulse_locked (const Metrics& metrics, const double& pulse) const;
|
||||
|
||||
double pulse_at_frame_locked (const Metrics& metrics, const framepos_t& frame) const;
|
||||
framepos_t frame_at_pulse_locked (const Metrics& metrics, const double& pulse) const;
|
||||
double pulse_at_minute_locked (const Metrics& metrics, const double& minute) const;
|
||||
double minute_at_pulse_locked (const Metrics& metrics, const double& pulse) const;
|
||||
|
||||
Tempo tempo_at_frame_locked (const Metrics& metrics, const framepos_t& frame) const;
|
||||
framepos_t frame_at_tempo_locked (const Metrics& metrics, const Tempo& tempo) const;
|
||||
Tempo tempo_at_minute_locked (const Metrics& metrics, const double& minute) const;
|
||||
double minute_at_tempo_locked (const Metrics& metrics, const Tempo& tempo) const;
|
||||
|
||||
Timecode::BBT_Time bbt_at_frame_locked (const Metrics& metrics, const framepos_t& frame) const;
|
||||
framepos_t frame_at_bbt_locked (const Metrics& metrics, const Timecode::BBT_Time&) const;
|
||||
Tempo tempo_at_pulse_locked (const Metrics& metrics, const double& pulse) const;
|
||||
double pulse_at_tempo_locked (const Metrics& metrics, const Tempo& tempo) const;
|
||||
|
||||
Timecode::BBT_Time bbt_at_minute_locked (const Metrics& metrics, const double& minute) const;
|
||||
double minute_at_bbt_locked (const Metrics& metrics, const Timecode::BBT_Time&) const;
|
||||
|
||||
double beat_at_bbt_locked (const Metrics& metrics, const Timecode::BBT_Time& bbt) const ;
|
||||
Timecode::BBT_Time bbt_at_beat_locked (const Metrics& metrics, const double& beats) const;
|
||||
|
@ -491,28 +509,35 @@ private:
|
|||
double pulse_at_bbt_locked (const Metrics& metrics, const Timecode::BBT_Time& bbt) const;
|
||||
Timecode::BBT_Time bbt_at_pulse_locked (const Metrics& metrics, const double& pulse) const;
|
||||
|
||||
framepos_t frame_at_quarter_note_locked (const Metrics& metrics, const double quarter_note) const;
|
||||
double quarter_note_at_frame_locked (const Metrics& metrics, const framepos_t frame) const;
|
||||
double minute_at_quarter_note_locked (const Metrics& metrics, const double quarter_note) const;
|
||||
double quarter_note_at_minute_locked (const Metrics& metrics, const double minute) const;
|
||||
|
||||
double quarter_note_at_beat_locked (const Metrics& metrics, const double beat) const;
|
||||
double beat_at_quarter_note_locked (const Metrics& metrics, const double beat) const;
|
||||
|
||||
const TempoSection& tempo_section_at_frame_locked (const Metrics& metrics, framepos_t frame) const;
|
||||
double minutes_between_quarter_notes_locked (const Metrics& metrics, const double start_qn, const double end_qn) const;
|
||||
double quarter_notes_between_frames_locked (const Metrics& metrics, const framecnt_t start, const framecnt_t end) const;
|
||||
|
||||
const TempoSection& tempo_section_at_minute_locked (const Metrics& metrics, double minute) const;
|
||||
const TempoSection& tempo_section_at_beat_locked (const Metrics& metrics, const double& beat) const;
|
||||
|
||||
const MeterSection& meter_section_at_frame_locked (const Metrics& metrics, framepos_t frame) const;
|
||||
const MeterSection& meter_section_at_minute_locked (const Metrics& metrics, double minute) const;
|
||||
const MeterSection& meter_section_at_beat_locked (const Metrics& metrics, const double& beat) const;
|
||||
|
||||
bool check_solved (const Metrics& metrics) const;
|
||||
bool set_active_tempos (const Metrics& metrics, const framepos_t& frame);
|
||||
|
||||
bool solve_map_frame (Metrics& metrics, TempoSection* section, const framepos_t& frame);
|
||||
bool solve_map_minute (Metrics& metrics, TempoSection* section, const double& minute);
|
||||
bool solve_map_pulse (Metrics& metrics, TempoSection* section, const double& pulse);
|
||||
bool solve_map_frame (Metrics& metrics, MeterSection* section, const framepos_t& frame);
|
||||
bool solve_map_minute (Metrics& metrics, MeterSection* section, const double& minute);
|
||||
bool solve_map_bbt (Metrics& metrics, MeterSection* section, const Timecode::BBT_Time& bbt);
|
||||
|
||||
double exact_beat_at_frame_locked (const Metrics& metrics, const framepos_t& frame, const int32_t sub_num);
|
||||
double exact_qn_at_frame_locked (const Metrics& metrics, const framepos_t& frame, const int32_t sub_num);
|
||||
|
||||
double minute_at_frame (const framepos_t frame) const;
|
||||
framepos_t frame_at_minute (const double minute) const;
|
||||
|
||||
friend class ::BBTTest;
|
||||
friend class ::FrameposPlusBeatsTest;
|
||||
friend class ::FrameposMinusBeatsTest;
|
||||
|
@ -538,11 +563,10 @@ private:
|
|||
|
||||
void do_insert (MetricSection* section);
|
||||
|
||||
TempoSection* add_tempo_locked (const Tempo&, double pulse, framepos_t frame
|
||||
TempoSection* add_tempo_locked (const Tempo&, double pulse, double minute
|
||||
, TempoSection::Type type, PositionLockStyle pls, bool recompute, bool locked_to_meter = false);
|
||||
|
||||
MeterSection* add_meter_locked (const Meter&, double beat, const Timecode::BBT_Time& where, framepos_t frame
|
||||
, PositionLockStyle pls, bool recompute);
|
||||
MeterSection* add_meter_locked (const Meter&, double beat, const Timecode::BBT_Time& where, PositionLockStyle pls, bool recompute);
|
||||
|
||||
bool remove_tempo_locked (const TempoSection&);
|
||||
bool remove_meter_locked (const MeterSection&);
|
||||
|
|
|
@ -1808,7 +1808,7 @@ AUPlugin::get_beat_and_tempo_callback (Float64* outCurrentBeat,
|
|||
}
|
||||
|
||||
if (outCurrentTempo) {
|
||||
*outCurrentTempo = tmap.tempo_at_frame (transport_frame + input_offset).beats_per_minute();
|
||||
*outCurrentTempo = tmap.tempo_at_frame (transport_frame + input_offset).quarter_notes_per_minute();
|
||||
}
|
||||
|
||||
return noErr;
|
||||
|
|
|
@ -1020,7 +1020,7 @@ LuaBindings::common (lua_State* L)
|
|||
.addFunction ("lower_to_bottom", &Region::lower_to_bottom)
|
||||
.addFunction ("set_sync_position", &Region::set_sync_position)
|
||||
.addFunction ("clear_sync_position", &Region::clear_sync_position)
|
||||
.addFunction ("pulse", &Region::pulse)
|
||||
.addFunction ("quarter_note", &Region::quarter_note)
|
||||
.addFunction ("set_hidden", &Region::set_hidden)
|
||||
.addFunction ("set_muted", &Region::set_muted)
|
||||
.addFunction ("set_opaque", &Region::set_opaque)
|
||||
|
@ -1347,8 +1347,10 @@ LuaBindings::common (lua_State* L)
|
|||
.beginClass <Tempo> ("Tempo")
|
||||
.addConstructor <void (*) (double, double)> ()
|
||||
.addFunction ("note_type", &Tempo::note_type)
|
||||
.addFunction ("beats_per_minute", &Tempo::beats_per_minute)
|
||||
.addFunction ("frames_per_beat", &Tempo::frames_per_beat)
|
||||
.addFunction ("note_types_per_minute", (double (Tempo::*)() const)&Tempo::note_types_per_minute)
|
||||
.addFunction ("quarter_notes_per_minute", &Tempo::quarter_notes_per_minute)
|
||||
.addFunction ("frames_per_quarter_note", &Tempo::frames_per_quarter_note)
|
||||
.addFunction ("frames_per_note_type", &Tempo::frames_per_note_type)
|
||||
.endClass ()
|
||||
|
||||
.beginClass <Meter> ("Meter")
|
||||
|
|
|
@ -2447,7 +2447,7 @@ LV2Plugin::connect_and_run(BufferSet& bufs,
|
|||
}
|
||||
|
||||
if (_bpm_control_port) {
|
||||
*_bpm_control_port = tmap.tempo_at_frame (start).beats_per_minute();
|
||||
*_bpm_control_port = tmap.tempo_at_frame (start).note_types_per_minute();
|
||||
}
|
||||
|
||||
#ifdef LV2_EXTENDED
|
||||
|
@ -2519,7 +2519,7 @@ LV2Plugin::connect_and_run(BufferSet& bufs,
|
|||
if (valid && (flags & PORT_INPUT)) {
|
||||
if ((flags & PORT_POSITION)) {
|
||||
Timecode::BBT_Time bbt (tmap.bbt_at_frame (start));
|
||||
double bpm = tmap.tempo_at_frame (start).beats_per_minute();
|
||||
double bpm = tmap.tempo_at_frame (start).note_types_per_minute();
|
||||
double beatpos = (bbt.bars - 1) * tmetric.meter().divisions_per_bar()
|
||||
+ (bbt.beats - 1)
|
||||
+ (bbt.ticks / Timecode::BBT_Time::ticks_per_beat);
|
||||
|
@ -2560,8 +2560,8 @@ LV2Plugin::connect_and_run(BufferSet& bufs,
|
|||
} else {
|
||||
tmetric.set_metric(metric);
|
||||
Timecode::BBT_Time bbt;
|
||||
bbt = tmap.bbt_at_pulse (metric->pulse());
|
||||
double bpm = tmap.tempo_at_frame (start/*XXX*/).beats_per_minute();
|
||||
bbt = tmap.bbt_at_frame (metric->frame());
|
||||
double bpm = tmap.tempo_at_frame (start/*XXX*/).note_types_per_minute();
|
||||
write_position(&_impl->forge, _ev_buffers[port_index],
|
||||
tmetric, bbt, speed, bpm,
|
||||
metric->frame(),
|
||||
|
@ -2834,7 +2834,7 @@ LV2Plugin::connect_and_run(BufferSet& bufs,
|
|||
* so it needs to be realative to that.
|
||||
*/
|
||||
TempoMetric t = tmap.metric_at(start);
|
||||
_current_bpm = tmap.tempo_at_frame (start).beats_per_minute();
|
||||
_current_bpm = tmap.tempo_at_frame (start).note_types_per_minute();
|
||||
Timecode::BBT_Time bbt (tmap.bbt_at_frame (start));
|
||||
double beatpos = (bbt.bars - 1) * t.meter().divisions_per_bar()
|
||||
+ (bbt.beats - 1)
|
||||
|
|
|
@ -82,11 +82,7 @@ MIDIClock_Slave::rebind (MidiPort& port)
|
|||
void
|
||||
MIDIClock_Slave::calculate_one_ppqn_in_frames_at(framepos_t time)
|
||||
{
|
||||
const Tempo& current_tempo = session->tempo_map().tempo_at_frame (time);
|
||||
double const frames_per_beat = session->tempo_map().frames_per_beat_at (time, session->frame_rate());
|
||||
|
||||
double quarter_notes_per_beat = 4.0 / current_tempo.note_type();
|
||||
double frames_per_quarter_note = frames_per_beat / quarter_notes_per_beat;
|
||||
const double frames_per_quarter_note = session->tempo_map().frames_per_quarter_note_at (time, session->frame_rate());
|
||||
|
||||
one_ppqn_in_frames = frames_per_quarter_note / double (ppqn);
|
||||
// DEBUG_TRACE (DEBUG::MidiClock, string_compose ("at %1, one ppqn = %2\n", time, one_ppqn_in_frames));
|
||||
|
|
|
@ -106,7 +106,7 @@ MidiRegion::MidiRegion (boost::shared_ptr<const MidiRegion> other, frameoffset_t
|
|||
, _start_beats (Properties::start_beats, 0.0)
|
||||
, _length_beats (Properties::length_beats, other->_length_beats)
|
||||
{
|
||||
_start_beats = (_session.tempo_map().exact_qn_at_frame (other->_position + offset, sub_num) - (other->pulse() * 4.0)) + other->_start_beats;
|
||||
_start_beats = (_session.tempo_map().exact_qn_at_frame (other->_position + offset, sub_num) - other->_quarter_note) + other->_start_beats;
|
||||
|
||||
update_length_beats (sub_num);
|
||||
register_properties ();
|
||||
|
@ -195,7 +195,7 @@ MidiRegion::clone (boost::shared_ptr<MidiSource> newsrc) const
|
|||
plist.add (Properties::layer, 0);
|
||||
|
||||
boost::shared_ptr<MidiRegion> ret (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (newsrc, plist, true)));
|
||||
ret->set_pulse (pulse());
|
||||
ret->set_quarter_note (quarter_note());
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -212,8 +212,10 @@ MidiRegion::post_set (const PropertyChange& pc)
|
|||
so disallow (this has been set from XML state anyway).
|
||||
*/
|
||||
if (!_session.loading()) {
|
||||
/* update non-musically */
|
||||
update_length_beats (0);
|
||||
/* ensure this only updates non-musical regions */
|
||||
if (position_lock_style() == AudioTime) {
|
||||
update_length_beats (0);
|
||||
}
|
||||
}
|
||||
} else if (pc.contains (Properties::start) && !pc.contains (Properties::start_beats)) {
|
||||
set_start_beats_from_start_frames ();
|
||||
|
@ -223,7 +225,9 @@ MidiRegion::post_set (const PropertyChange& pc)
|
|||
void
|
||||
MidiRegion::set_start_beats_from_start_frames ()
|
||||
{
|
||||
_start_beats = (pulse() * 4.0) - _session.tempo_map().quarter_note_at_frame (_position - _start);
|
||||
if (position_lock_style() == AudioTime) {
|
||||
_start_beats = quarter_note() - _session.tempo_map().quarter_note_at_frame (_position - _start);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -265,11 +269,10 @@ MidiRegion::update_after_tempo_map_change (bool /* send */)
|
|||
For now, the musical position at the region start is retained, but subsequent events
|
||||
will maintain their beat distance according to the map.
|
||||
*/
|
||||
_start = _session.tempo_map().frame_at_quarter_note (pulse() * 4.0)
|
||||
- _session.tempo_map().frame_at_quarter_note ((pulse() * 4.0) - start_beats());
|
||||
_start = _session.tempo_map().frames_between_quarter_notes (quarter_note() - start_beats(), quarter_note());
|
||||
|
||||
/* _length doesn't change for audio-locked regions. update length_beats to match. */
|
||||
_length_beats = _session.tempo_map().quarter_note_at_frame (_position + _length) - _session.tempo_map().quarter_note_at_frame (_position);
|
||||
_length_beats = _session.tempo_map().quarter_note_at_frame (_position + _length) - quarter_note();
|
||||
|
||||
s_and_l.add (Properties::start);
|
||||
s_and_l.add (Properties::length_beats);
|
||||
|
@ -281,7 +284,7 @@ MidiRegion::update_after_tempo_map_change (bool /* send */)
|
|||
Region::update_after_tempo_map_change (false);
|
||||
|
||||
/* _start has now been updated. */
|
||||
_length = _session.tempo_map().frame_at_pulse (pulse() + (_length_beats / 4.0)) - _position;
|
||||
_length = max ((framecnt_t) 1, _session.tempo_map().frames_between_quarter_notes (quarter_note(), quarter_note() + _length_beats));
|
||||
|
||||
if (old_start != _start) {
|
||||
s_and_l.add (Properties::start);
|
||||
|
@ -299,7 +302,7 @@ MidiRegion::update_after_tempo_map_change (bool /* send */)
|
|||
void
|
||||
MidiRegion::update_length_beats (const int32_t sub_num)
|
||||
{
|
||||
_length_beats = _session.tempo_map().exact_qn_at_frame (_position + _length, sub_num) - (pulse() * 4.0);
|
||||
_length_beats = _session.tempo_map().exact_qn_at_frame (_position + _length, sub_num) - quarter_note();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -313,8 +316,7 @@ MidiRegion::set_position_internal (framepos_t pos, bool allow_bbt_recompute, con
|
|||
}
|
||||
|
||||
/* set _start to new position in tempo map */
|
||||
_start = _session.tempo_map().frame_at_quarter_note (pulse() * 4.0)
|
||||
- _session.tempo_map().frame_at_quarter_note ((pulse() * 4.0) - start_beats());
|
||||
_start = _session.tempo_map().frames_between_quarter_notes (quarter_note() - start_beats(), quarter_note());
|
||||
|
||||
/* in construction from src */
|
||||
if (_length_beats == 0.0) {
|
||||
|
@ -322,12 +324,12 @@ MidiRegion::set_position_internal (framepos_t pos, bool allow_bbt_recompute, con
|
|||
}
|
||||
|
||||
if (position_lock_style() == AudioTime) {
|
||||
_length_beats = _session.tempo_map().quarter_note_at_frame (_position + _length) - _session.tempo_map().quarter_note_at_frame (_position);
|
||||
_length_beats = _session.tempo_map().quarter_note_at_frame (_position + _length) - quarter_note();
|
||||
} else {
|
||||
/* leave _length_beats alone, and change _length to reflect the state of things
|
||||
at the new position (tempo map may dictate a different number of frames).
|
||||
*/
|
||||
Region::set_length_internal (_session.tempo_map().frame_at_quarter_note ((pulse() * 4.0) + length_beats()) - _position, sub_num);
|
||||
Region::set_length_internal (_session.tempo_map().frames_between_quarter_notes (quarter_note(), quarter_note() + length_beats()), sub_num);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -411,8 +413,7 @@ MidiRegion::_read_at (const SourceList& /*srcs*/,
|
|||
<< " _position = " << _position
|
||||
<< " _start = " << _start
|
||||
<< " intoffset = " << internal_offset
|
||||
<< " pulse = " << pulse()
|
||||
<< " start_pulse = " << start_pulse()
|
||||
<< " quarter_note = " << quarter_note()
|
||||
<< " start_beat = " << _start_beats
|
||||
<< endl;
|
||||
#endif
|
||||
|
@ -430,7 +431,7 @@ MidiRegion::_read_at (const SourceList& /*srcs*/,
|
|||
tracker,
|
||||
filter,
|
||||
_filtered_parameters,
|
||||
pulse(),
|
||||
quarter_note(),
|
||||
_start_beats
|
||||
) != to_read) {
|
||||
return 0; /* "read nothing" */
|
||||
|
@ -450,13 +451,6 @@ MidiRegion::set_state (const XMLNode& node, int version)
|
|||
{
|
||||
int ret = Region::set_state (node, version);
|
||||
|
||||
if (ret == 0) {
|
||||
/* set length beats to the frame (non-musical) */
|
||||
if (position_lock_style() == AudioTime) {
|
||||
update_length_beats (0);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -604,9 +598,7 @@ void
|
|||
MidiRegion::set_start_internal (framecnt_t s, const int32_t sub_num)
|
||||
{
|
||||
Region::set_start_internal (s, sub_num);
|
||||
if (position_lock_style() == AudioTime) {
|
||||
set_start_beats_from_start_frames ();
|
||||
}
|
||||
set_start_beats_from_start_frames ();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -630,15 +622,14 @@ MidiRegion::trim_to_internal (framepos_t position, framecnt_t length, const int3
|
|||
if (_position != position) {
|
||||
|
||||
const double pos_qn = _session.tempo_map().exact_qn_at_frame (position, sub_num);
|
||||
const double old_pos_qn = pulse() * 4.0;
|
||||
const double old_pos_qn = quarter_note();
|
||||
|
||||
/* sets _pulse to new position.*/
|
||||
set_position_internal (position, true, sub_num);
|
||||
what_changed.add (Properties::position);
|
||||
|
||||
double new_start_qn = start_beats() + (pos_qn - old_pos_qn);
|
||||
const framepos_t new_start = _session.tempo_map().frame_at_quarter_note (pos_qn)
|
||||
- _session.tempo_map().frame_at_quarter_note (pos_qn - new_start_qn);
|
||||
framepos_t new_start = _session.tempo_map().frames_between_quarter_notes (pos_qn - new_start_qn, pos_qn);
|
||||
|
||||
if (!verify_start_and_length (new_start, length)) {
|
||||
return;
|
||||
|
|
|
@ -190,12 +190,12 @@ MidiSource::midi_read (const Lock& lm,
|
|||
MidiStateTracker* tracker,
|
||||
MidiChannelFilter* filter,
|
||||
const std::set<Evoral::Parameter>& filtered,
|
||||
const double pulse,
|
||||
const double start_beats) const
|
||||
const double pos_beats,
|
||||
const double start_beats) const
|
||||
{
|
||||
BeatsFramesConverter converter(_session.tempo_map(), source_start);
|
||||
|
||||
const double start_qn = (pulse * 4.0) - start_beats;
|
||||
const double start_qn = pos_beats - start_beats;
|
||||
|
||||
DEBUG_TRACE (DEBUG::MidiSourceIO,
|
||||
string_compose ("MidiSource::midi_read() %5 sstart %1 start %2 cnt %3 tracker %4\n",
|
||||
|
|
|
@ -177,7 +177,7 @@ Region::register_properties ()
|
|||
, _position (Properties::position, 0) \
|
||||
, _beat (Properties::beat, 0.0) \
|
||||
, _sync_position (Properties::sync_position, (s)) \
|
||||
, _pulse (0.0) \
|
||||
, _quarter_note (0.0) \
|
||||
, _transient_user_start (0) \
|
||||
, _transient_analysis_start (0) \
|
||||
, _transient_analysis_end (0) \
|
||||
|
@ -208,7 +208,7 @@ Region::register_properties ()
|
|||
, _position(Properties::position, other->_position) \
|
||||
, _beat (Properties::beat, other->_beat) \
|
||||
, _sync_position(Properties::sync_position, other->_sync_position) \
|
||||
, _pulse (other->_pulse) \
|
||||
, _quarter_note (other->_quarter_note) \
|
||||
, _user_transients (other->_user_transients) \
|
||||
, _transient_user_start (other->_transient_user_start) \
|
||||
, _transients (other->_transients) \
|
||||
|
@ -294,7 +294,7 @@ Region::Region (boost::shared_ptr<const Region> other)
|
|||
|
||||
_start = other->_start;
|
||||
_beat = other->_beat;
|
||||
_pulse = other->_pulse;
|
||||
_quarter_note = other->_quarter_note;
|
||||
|
||||
/* sync pos is relative to start of file. our start-in-file is now zero,
|
||||
so set our sync position to whatever the the difference between
|
||||
|
@ -353,7 +353,7 @@ Region::Region (boost::shared_ptr<const Region> other, frameoffset_t offset, con
|
|||
|
||||
_start = other->_start + offset;
|
||||
_beat = _session.tempo_map().exact_beat_at_frame (_position, sub_num);
|
||||
_pulse = _session.tempo_map().exact_qn_at_frame (_position, sub_num) / 4.0;
|
||||
_quarter_note = _session.tempo_map().exact_qn_at_frame (_position, sub_num);
|
||||
|
||||
/* if the other region had a distinct sync point
|
||||
set, then continue to use it as best we can.
|
||||
|
@ -549,11 +549,6 @@ Region::set_position_lock_style (PositionLockStyle ps)
|
|||
|
||||
_position_lock_style = ps;
|
||||
|
||||
if (_position_lock_style == MusicTime) {
|
||||
_beat = _session.tempo_map().beat_at_frame (_position);
|
||||
_pulse = _session.tempo_map().pulse_at_frame (_position);
|
||||
}
|
||||
|
||||
send_change (Properties::position_lock_style);
|
||||
}
|
||||
}
|
||||
|
@ -600,6 +595,7 @@ Region::set_position (framepos_t pos, int32_t sub_num)
|
|||
if (!_session.loading()) {
|
||||
_beat = _session.tempo_map().exact_beat_at_frame (pos, sub_num);
|
||||
}
|
||||
|
||||
/* will set pulse accordingly */
|
||||
set_position_internal (pos, false, sub_num);
|
||||
}
|
||||
|
@ -675,7 +671,7 @@ Region::set_position_internal (framepos_t pos, bool allow_bbt_recompute, const i
|
|||
recompute_position_from_lock_style (sub_num);
|
||||
} else {
|
||||
/* MusicTime dictates that we glue to ardour beats. the pulse may have changed.*/
|
||||
_pulse = _session.tempo_map().pulse_at_beat (_beat);
|
||||
_quarter_note = _session.tempo_map().quarter_note_at_beat (_beat);
|
||||
}
|
||||
|
||||
/* check that the new _position wouldn't make the current
|
||||
|
@ -694,7 +690,7 @@ void
|
|||
Region::recompute_position_from_lock_style (const int32_t sub_num)
|
||||
{
|
||||
_beat = _session.tempo_map().exact_beat_at_frame (_position, sub_num);
|
||||
_pulse = _session.tempo_map().exact_qn_at_frame (_position, sub_num) / 4.0;
|
||||
_quarter_note = _session.tempo_map().exact_qn_at_frame (_position, sub_num);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1853,7 +1849,7 @@ void
|
|||
Region::post_set (const PropertyChange& pc)
|
||||
{
|
||||
if (pc.contains (Properties::position)) {
|
||||
_pulse = _session.tempo_map().pulse_at_beat (_beat);
|
||||
_quarter_note = _session.tempo_map().quarter_note_at_beat (_beat);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -208,7 +208,7 @@ intptr_t Session::vst_callback (
|
|||
|
||||
if (value & (kVstTempoValid)) {
|
||||
const Tempo& t (session->tempo_map().tempo_at_frame (now));
|
||||
timeinfo->tempo = t.beats_per_minute ();
|
||||
timeinfo->tempo = t.quarter_notes_per_minute ();
|
||||
newflags |= (kVstTempoValid);
|
||||
}
|
||||
if (value & (kVstTimeSigValid)) {
|
||||
|
@ -225,7 +225,7 @@ intptr_t Session::vst_callback (
|
|||
bbt.beats = 1;
|
||||
bbt.ticks = 0;
|
||||
/* exact quarter note */
|
||||
double ppqBar = session->tempo_map().pulse_at_bbt_rt (bbt) * 4.0;
|
||||
double ppqBar = session->tempo_map().quarter_note_at_bbt_rt (bbt);
|
||||
/* quarter note at frame position (not rounded to note subdivision) */
|
||||
double ppqPos = session->tempo_map().quarter_note_at_frame_rt (now);
|
||||
if (value & (kVstPpqPosValid)) {
|
||||
|
@ -333,7 +333,7 @@ intptr_t Session::vst_callback (
|
|||
// returns tempo (in bpm * 10000) at sample frame location passed in <value>
|
||||
if (session) {
|
||||
const Tempo& t (session->tempo_map().tempo_at_frame (value));
|
||||
return t.beats_per_minute() * 1000;
|
||||
return t.quarter_notes_per_minute() * 1000;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
|
1198
libs/ardour/tempo.cc
1198
libs/ardour/tempo.cc
File diff suppressed because it is too large
Load Diff
|
@ -13,11 +13,11 @@ void
|
|||
BBTTest::addTest ()
|
||||
{
|
||||
TempoMap map(48000);
|
||||
Tempo tempo(120);
|
||||
Tempo tempo(120, 4.0);
|
||||
Meter meter(4.0, 4.0);
|
||||
|
||||
/* no need to supply the frame for a new music-locked meter */
|
||||
map.add_meter (meter, 4.0, BBT_Time(2, 1, 0), 0, MusicTime);
|
||||
map.add_meter (meter, 4.0, BBT_Time(2, 1, 0), MusicTime);
|
||||
|
||||
/* add some good stuff here */
|
||||
}
|
||||
|
|
|
@ -18,10 +18,10 @@ FrameposPlusBeatsTest::singleTempoTest ()
|
|||
double const frames_per_beat = (60 / double (bpm)) * double (sampling_rate);
|
||||
|
||||
TempoMap map (sampling_rate);
|
||||
Tempo tempo (bpm);
|
||||
Tempo tempo (bpm, 4.0);
|
||||
Meter meter (4, 4);
|
||||
|
||||
map.replace_meter (map.first_meter(), meter, BBT_Time (1, 1, 0), (framepos_t) 0, AudioTime);
|
||||
map.replace_meter (map.first_meter(), meter, BBT_Time (1, 1, 0), AudioTime);
|
||||
map.replace_tempo (map.first_tempo(), tempo, 0.0, 0, TempoSection::Constant, AudioTime);
|
||||
|
||||
/* Add 1 beat to beat 3 of the first bar */
|
||||
|
@ -41,7 +41,7 @@ FrameposPlusBeatsTest::doubleTempoTest ()
|
|||
|
||||
TempoMap map (sampling_rate);
|
||||
Meter meter (4, 4);
|
||||
map.replace_meter (map.first_meter(), meter, BBT_Time (1, 1, 0), (framepos_t) 0, AudioTime);
|
||||
map.replace_meter (map.first_meter(), meter, BBT_Time (1, 1, 0), AudioTime);
|
||||
|
||||
/*
|
||||
120bpm at bar 1, 240bpm at bar 4
|
||||
|
@ -62,9 +62,9 @@ FrameposPlusBeatsTest::doubleTempoTest ()
|
|||
|
||||
*/
|
||||
|
||||
Tempo tempoA (120);
|
||||
Tempo tempoA (120, 4.0);
|
||||
map.replace_tempo (map.first_tempo(), tempoA, 0.0, 0, TempoSection::Constant, AudioTime);
|
||||
Tempo tempoB (240);
|
||||
Tempo tempoB (240, 4.0);
|
||||
map.add_tempo (tempoB, 12.0 / tempoA.note_type(), 0, TempoSection::Constant, MusicTime);
|
||||
|
||||
/* Now some tests */
|
||||
|
@ -94,7 +94,7 @@ FrameposPlusBeatsTest::doubleTempoWithMeterTest ()
|
|||
|
||||
TempoMap map (sampling_rate);
|
||||
Meter meterA (4, 4);
|
||||
map.replace_meter (map.first_meter(), meterA, BBT_Time (1, 1, 0), (framepos_t) 0, AudioTime);
|
||||
map.replace_meter (map.first_meter(), meterA, BBT_Time (1, 1, 0), AudioTime);
|
||||
|
||||
/*
|
||||
120bpm at bar 1, 240bpm at bar 4
|
||||
|
@ -115,12 +115,12 @@ FrameposPlusBeatsTest::doubleTempoWithMeterTest ()
|
|||
|
||||
*/
|
||||
|
||||
Tempo tempoA (120);
|
||||
Tempo tempoA (120, 4.0);
|
||||
map.replace_tempo (map.first_tempo(), tempoA, 0.0, 0, TempoSection::Constant, AudioTime);
|
||||
Tempo tempoB (240);
|
||||
Tempo tempoB (240, 4.0);
|
||||
map.add_tempo (tempoB, 12.0 / tempoA.note_type(), 0, TempoSection::Constant, MusicTime);
|
||||
Meter meterB (3, 8);
|
||||
map.add_meter (meterB, 12.0, BBT_Time (4, 1, 0), 0, MusicTime);
|
||||
map.add_meter (meterB, 12.0, BBT_Time (4, 1, 0), MusicTime);
|
||||
|
||||
/* Now some tests */
|
||||
|
||||
|
@ -149,7 +149,7 @@ FrameposPlusBeatsTest::doubleTempoWithComplexMeterTest ()
|
|||
|
||||
TempoMap map (sampling_rate);
|
||||
Meter meterA (3, 4);
|
||||
map.replace_meter (map.first_meter(), meterA, BBT_Time (1, 1, 0), (framepos_t) 0, AudioTime);
|
||||
map.replace_meter (map.first_meter(), meterA, BBT_Time (1, 1, 0), AudioTime);
|
||||
|
||||
/*
|
||||
120bpm at bar 1, 240bpm at bar 4
|
||||
|
@ -172,12 +172,12 @@ FrameposPlusBeatsTest::doubleTempoWithComplexMeterTest ()
|
|||
4|1|0
|
||||
*/
|
||||
|
||||
Tempo tempoA (120);
|
||||
Tempo tempoA (120, 4.0);
|
||||
map.replace_tempo (map.first_tempo(), tempoA, 0.0, 0, TempoSection::Constant, AudioTime);
|
||||
Tempo tempoB (240, 4.0);
|
||||
map.add_tempo (tempoB, 12.0 / 4.0, 0, TempoSection::Constant, MusicTime);
|
||||
Meter meterB (5, 8);
|
||||
map.add_meter (meterB, 9.0, BBT_Time (4, 1, 0), 0, MusicTime);
|
||||
map.add_meter (meterB, 9.0, BBT_Time (4, 1, 0), MusicTime);
|
||||
/* Now some tests */
|
||||
|
||||
/* Add 1 beat to 1|2 */
|
||||
|
|
|
@ -17,10 +17,10 @@ FramewalkToBeatsTest::singleTempoTest ()
|
|||
double const frames_per_beat = (60 / double (bpm)) * double (sampling_rate);
|
||||
|
||||
TempoMap map (sampling_rate);
|
||||
Tempo tempo (bpm);
|
||||
Tempo tempo (bpm, 4.0);
|
||||
Meter meter (4, 4);
|
||||
|
||||
map.replace_meter (map.meter_section_at_frame (0), meter, BBT_Time (1, 1, 0), (framepos_t) 0, AudioTime);
|
||||
map.replace_meter (map.meter_section_at_frame (0), meter, BBT_Time (1, 1, 0), AudioTime);
|
||||
map.replace_tempo (map.tempo_section_at_frame (0), tempo, 0.0, 0, TempoSection::Constant, AudioTime);
|
||||
|
||||
/* Walk 1 beats-worth of frames from beat 3 */
|
||||
|
@ -47,7 +47,7 @@ FramewalkToBeatsTest::doubleTempoTest ()
|
|||
|
||||
TempoMap map (sampling_rate);
|
||||
Meter meter (4, 4);
|
||||
map.replace_meter (map.meter_section_at_frame (0), meter, BBT_Time (1, 1, 0), (framepos_t) 0, AudioTime);
|
||||
map.replace_meter (map.meter_section_at_frame (0), meter, BBT_Time (1, 1, 0), AudioTime);
|
||||
|
||||
/*
|
||||
120bpm at bar 1, 240bpm at bar 4
|
||||
|
@ -104,7 +104,7 @@ FramewalkToBeatsTest::tripleTempoTest ()
|
|||
|
||||
TempoMap map (sampling_rate);
|
||||
Meter meter (4, 4);
|
||||
map.replace_meter (map.meter_section_at_frame (0), meter, BBT_Time (1, 1, 0), (framepos_t) 0, AudioTime);
|
||||
map.replace_meter (map.meter_section_at_frame (0), meter, BBT_Time (1, 1, 0), AudioTime);
|
||||
|
||||
/*
|
||||
120bpm at bar 1, 240bpm at bar 2, 160bpm at bar 3
|
||||
|
@ -126,11 +126,11 @@ FramewalkToBeatsTest::tripleTempoTest ()
|
|||
|
||||
*/
|
||||
|
||||
Tempo tempoA (120);
|
||||
Tempo tempoA (120, 4.0);
|
||||
map.replace_tempo (map.tempo_section_at_frame (0), tempoA, 0.0, 0, TempoSection::Constant, AudioTime);
|
||||
Tempo tempoB (240);
|
||||
Tempo tempoB (240, 4.0);
|
||||
map.add_tempo (tempoB, 4.0 / tempoB.note_type(), 0, TempoSection::Constant, MusicTime);
|
||||
Tempo tempoC (160);
|
||||
Tempo tempoC (160, 4.0);
|
||||
map.add_tempo (tempoC, 8.0 / tempoB.note_type(), 0, TempoSection::Constant, MusicTime);
|
||||
|
||||
/* Walk from 1|3 to 4|1 */
|
||||
|
@ -147,10 +147,10 @@ FramewalkToBeatsTest::singleTempoMeterTest ()
|
|||
double const frames_per_beat = (60 / double (bpm)) * double (sampling_rate);
|
||||
|
||||
TempoMap map (sampling_rate);
|
||||
Tempo tempo (bpm);
|
||||
Tempo tempo (bpm, 4.0);
|
||||
Meter meter (7, 8);
|
||||
|
||||
map.replace_meter (map.meter_section_at_frame (0), meter, BBT_Time (1, 1, 0), (framepos_t) 0, AudioTime);
|
||||
map.replace_meter (map.meter_section_at_frame (0), meter, BBT_Time (1, 1, 0), AudioTime);
|
||||
map.replace_tempo (map.tempo_section_at_frame (0), tempo, 0.0, 0, TempoSection::Constant, AudioTime);
|
||||
|
||||
/* Walk 1 qn beats-worth of frames from beat 3 */
|
||||
|
|
|
@ -44,12 +44,12 @@ class TestSlaveSessionProxy : public ISlaveSessionProxy {
|
|||
_transport_frame (0),
|
||||
_frame_time (1000000),
|
||||
_tempo_map (0),
|
||||
tempo (120),
|
||||
tempo (120, 4.0),
|
||||
meter (4.0, 4.0)
|
||||
{
|
||||
_tempo_map = new TempoMap (FRAME_RATE);
|
||||
_tempo_map->add_tempo (tempo, 0.0, 0, TempoSection::Constant, AudioTime);
|
||||
_tempo_map->add_meter (meter, 0.0, Timecode::BBT_Time(1, 1, 0), 0, AudioTime);
|
||||
_tempo_map->add_meter (meter, 0.0, Timecode::BBT_Time(1, 1, 0), AudioTime);
|
||||
}
|
||||
|
||||
// Controlling the mock object
|
||||
|
|
|
@ -8,13 +8,13 @@ using namespace ARDOUR;
|
|||
using namespace Timecode;
|
||||
|
||||
void
|
||||
TempoTest::recomputeMapTest ()
|
||||
TempoTest::recomputeMapTest48 ()
|
||||
{
|
||||
int const sampling_rate = 48000;
|
||||
|
||||
TempoMap map (sampling_rate);
|
||||
Meter meterA (4, 4);
|
||||
map.replace_meter (map.first_meter(), meterA, BBT_Time (1, 1, 0), (framepos_t) 0, AudioTime);
|
||||
map.replace_meter (map.first_meter(), meterA, BBT_Time (1, 1, 0), AudioTime);
|
||||
|
||||
/*
|
||||
120bpm at bar 1, 240bpm at bar 4
|
||||
|
@ -35,43 +35,329 @@ TempoTest::recomputeMapTest ()
|
|||
|
||||
*/
|
||||
|
||||
Tempo tempoA (120);
|
||||
Tempo tempoA (120.0, 4.0);
|
||||
map.replace_tempo (map.first_tempo(), tempoA, 0.0, 0, TempoSection::Constant, AudioTime);
|
||||
Tempo tempoB (240);
|
||||
Tempo tempoB (240.0, 4.0);
|
||||
map.add_tempo (tempoB, 3.0, 0, TempoSection::Constant, MusicTime);
|
||||
Meter meterB (3, 4);
|
||||
map.add_meter (meterB, 12.0, BBT_Time (4, 1, 0), 0, MusicTime);
|
||||
|
||||
map.add_meter (meterB, 12.0, BBT_Time (4, 1, 0), MusicTime);
|
||||
//map.dump (map._metrics, std::cout);
|
||||
list<MetricSection*>::iterator i = map._metrics.begin();
|
||||
CPPUNIT_ASSERT_EQUAL (framepos_t (0), (*i)->frame ());
|
||||
|
||||
/* check the tempo section for ecpected result (no map) */
|
||||
const TempoSection& tsa (map.tempo_section_at_frame (0));
|
||||
CPPUNIT_ASSERT_EQUAL (framepos_t (288e3), tsa.frame_at_pulse (3.0, sampling_rate));
|
||||
CPPUNIT_ASSERT_EQUAL (framepos_t (144e3), tsa.frame_at_pulse (1.5, sampling_rate));
|
||||
CPPUNIT_ASSERT_EQUAL (framepos_t (96e3), tsa.frame_at_pulse (1.0, sampling_rate));
|
||||
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (3.0, tsa.pulse_at_frame (288e3, sampling_rate), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (1.5, tsa.pulse_at_frame (144e3, sampling_rate), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (1.0, tsa.pulse_at_frame (96e3, sampling_rate), 1e-17);
|
||||
|
||||
/* do the same via the map */
|
||||
CPPUNIT_ASSERT_EQUAL (framepos_t (288e3), map.frame_at_pulse (3.0));
|
||||
CPPUNIT_ASSERT_EQUAL (framepos_t (144e3), map.frame_at_pulse (1.5));
|
||||
CPPUNIT_ASSERT_EQUAL (framepos_t (96e3), map.frame_at_pulse (1.0));
|
||||
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (3.0, map.pulse_at_frame (288e3), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (1.5, map.pulse_at_frame (144e3), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (1.0, map.pulse_at_frame (96e3), 1e-17);
|
||||
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (240.0, map.tempo_at_beat (24.0).beats_per_minute(), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (240.0, map.tempo_at_beat (12.0).beats_per_minute(), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (120.0, map.tempo_at_beat (6.0).beats_per_minute(), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (120.0, map.tempo_at_beat (0.0).beats_per_minute(), 1e-17);
|
||||
|
||||
i = map._metrics.end();
|
||||
--i;
|
||||
CPPUNIT_ASSERT_EQUAL (framepos_t (288e3), (*i)->frame ());
|
||||
|
||||
/* check the tempo section for expected result (no map) */
|
||||
const TempoSection& tsa (map.tempo_section_at_frame (0));
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (0.1, tsa.minute_at_pulse (3.0), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (0.1 / 2.0, tsa.minute_at_pulse (1.5), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (0.1 / 3.0, tsa.minute_at_pulse (1.0), 1e-17);
|
||||
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (3.0, tsa.pulse_at_minute (0.1), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (1.5, tsa.pulse_at_minute (0.1 / 2.0), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (1.0, tsa.pulse_at_minute (0.1 / 3.0), 1e-17);
|
||||
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (1.0, tsa.minute_at_frame (60.0 * sampling_rate), 1e-17);
|
||||
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (0.1, tsa.minute_at_ntpm (240.0, 3.0), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (0.1, tsa.minute_at_ntpm (240.0, 3.0), 1e-17);
|
||||
|
||||
/* do the same via the map */
|
||||
|
||||
/* quarter note */
|
||||
|
||||
/* quarter note - frame*/
|
||||
CPPUNIT_ASSERT_EQUAL (framepos_t (288e3), map.frame_at_quarter_note (12.0));
|
||||
CPPUNIT_ASSERT_EQUAL (framepos_t (144e3), map.frame_at_quarter_note (6.0));
|
||||
CPPUNIT_ASSERT_EQUAL (framepos_t (96e3), map.frame_at_quarter_note (4.0));
|
||||
|
||||
/* frame - quarter note*/
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (12.0, map.quarter_note_at_frame (288e3), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (6.0, map.quarter_note_at_frame (144e3), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (4.0, map.quarter_note_at_frame (96e3), 1e-17);
|
||||
|
||||
/* pulse - internal minute based interface */
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (0.1, map.minute_at_pulse_locked (map._metrics, 3.0), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (3.0, map.pulse_at_minute_locked (map._metrics, 0.1), 1e-17);
|
||||
|
||||
/* tempo */
|
||||
|
||||
/* tempo - frame */
|
||||
CPPUNIT_ASSERT_EQUAL (framepos_t (288e3), map.frame_at_tempo (tempoB));
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (240.0, map.tempo_at_frame (288e3).note_types_per_minute(), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (120.0, map.tempo_at_frame (288e3 - 1).note_types_per_minute(), 1e-17);
|
||||
|
||||
/* tempo - quarter note */
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (240.0, map.tempo_at_quarter_note (24.0).note_types_per_minute(), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (240.0, map.tempo_at_quarter_note (12.0).note_types_per_minute(), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (120.0, map.tempo_at_quarter_note (6.0).note_types_per_minute(), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (120.0, map.tempo_at_quarter_note (0.0).note_types_per_minute(), 1e-17);
|
||||
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (12.0, map.quarter_note_at_tempo (tempoB), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (0.0, map.quarter_note_at_tempo (tempoA), 1e-17);
|
||||
|
||||
/* tempo - internal minute interface */
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (240.0, map.tempo_at_minute_locked (map._metrics, 0.1).note_types_per_minute(), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (0.1, map.minute_at_tempo_locked (map._metrics, tempoB), 1e-17);
|
||||
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (240.0, map.tempo_at_pulse_locked (map._metrics, 3.0).note_types_per_minute(), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (3.0, map.pulse_at_tempo_locked (map._metrics, tempoB), 1e-17);
|
||||
}
|
||||
|
||||
void
|
||||
TempoTest::recomputeMapTest44 ()
|
||||
{
|
||||
int const sampling_rate = 44100;
|
||||
|
||||
TempoMap map (sampling_rate);
|
||||
Meter meterA (4, 4);
|
||||
map.replace_meter (map.first_meter(), meterA, BBT_Time (1, 1, 0), AudioTime);
|
||||
|
||||
/*
|
||||
120bpm at bar 1, 240bpm at bar 4
|
||||
|
||||
120bpm = 24e3 samples per beat
|
||||
240bpm = 12e3 samples per beat
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
|
||||
120bpm 240bpm
|
||||
0 beats 12 beats
|
||||
0 frames 288e3 frames
|
||||
0 pulses 3 pulses
|
||||
| | | | |
|
||||
| 1.1 1.2 1.3 1.4 | 2.1 2.2 2.3.2.4 | 3.1 3.2 3.3 3.4 | 4.1 4.2 4.3 |
|
||||
|
||||
*/
|
||||
|
||||
Tempo tempoA (120.0, 4.0);
|
||||
map.replace_tempo (map.first_tempo(), tempoA, 0.0, 0, TempoSection::Constant, AudioTime);
|
||||
Tempo tempoB (240.0, 4.0);
|
||||
map.add_tempo (tempoB, 3.0, 0, TempoSection::Constant, MusicTime);
|
||||
Meter meterB (3, 4);
|
||||
map.add_meter (meterB, 12.0, BBT_Time (4, 1, 0), MusicTime);
|
||||
|
||||
list<MetricSection*>::iterator i = map._metrics.begin();
|
||||
CPPUNIT_ASSERT_EQUAL (framepos_t (0), (*i)->frame ());
|
||||
i = map._metrics.end();
|
||||
--i;
|
||||
CPPUNIT_ASSERT_EQUAL (framepos_t (264600), (*i)->frame ());
|
||||
|
||||
/* check the tempo section for expected result (no map) */
|
||||
const TempoSection& tsa (map.tempo_section_at_frame (0));
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (0.1, tsa.minute_at_pulse (3.0), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (0.1 / 2.0, tsa.minute_at_pulse (1.5), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (0.1 / 3.0, tsa.minute_at_pulse (1.0), 1e-17);
|
||||
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (3.0, tsa.pulse_at_minute (0.1), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (1.5, tsa.pulse_at_minute (0.1 / 2.0), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (1.0, tsa.pulse_at_minute (0.1 / 3.0), 1e-17);
|
||||
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (1.0, tsa.minute_at_frame (60.0 * sampling_rate), 1e-17);
|
||||
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (0.1, tsa.minute_at_ntpm (240.0, 3.0), 1e-17);
|
||||
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (0.1, tsa.minute_at_pulse (3.0), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (3.0, tsa.pulse_at_minute (0.1), 1e-17);
|
||||
|
||||
/* do the same via the map */
|
||||
|
||||
/* quarter note */
|
||||
|
||||
/* quarter note - frame */
|
||||
CPPUNIT_ASSERT_EQUAL (framepos_t (264600), map.frame_at_quarter_note (12.0));
|
||||
CPPUNIT_ASSERT_EQUAL (framepos_t (132300), map.frame_at_quarter_note (6.0));
|
||||
CPPUNIT_ASSERT_EQUAL (framepos_t (88200), map.frame_at_quarter_note (4.0));
|
||||
|
||||
/* frame - quarter note */
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (3.0 * 4.0, map.quarter_note_at_frame (264600), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (1.5 * 4.0, map.quarter_note_at_frame (132300), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (1.0 * 4.0, map.quarter_note_at_frame (88200), 1e-17);
|
||||
|
||||
/* pulse - internal minute based interface */
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (0.1, map.minute_at_pulse_locked (map._metrics, 3.0), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (3.0, map.pulse_at_minute_locked (map._metrics, 0.1), 1e-17);
|
||||
|
||||
/* tempo */
|
||||
|
||||
/* tempo - frame */
|
||||
CPPUNIT_ASSERT_EQUAL (framepos_t (264600), map.frame_at_tempo (tempoB));
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (240.0, map.tempo_at_frame (264600).note_types_per_minute(), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (120.0, map.tempo_at_frame (264600 - 1).note_types_per_minute(), 1e-17);
|
||||
|
||||
/* tempo - quarter note */
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (240.0, map.tempo_at_quarter_note (24.0).note_types_per_minute(), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (240.0, map.tempo_at_quarter_note (12.0).note_types_per_minute(), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (120.0, map.tempo_at_quarter_note (6.0).note_types_per_minute(), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (120.0, map.tempo_at_quarter_note (0.0).note_types_per_minute(), 1e-17);
|
||||
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (12.0, map.quarter_note_at_tempo (tempoB), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (0.0, map.quarter_note_at_tempo (tempoA), 1e-17);
|
||||
|
||||
/* tempo - internal minute interface */
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (240.0, map.tempo_at_minute_locked (map._metrics, 0.1).note_types_per_minute(), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (0.1, map.minute_at_tempo_locked (map._metrics, tempoB), 1e-17);
|
||||
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (240.0, map.tempo_at_pulse_locked (map._metrics, 3.0).note_types_per_minute(), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (3.0, map.pulse_at_tempo_locked (map._metrics, tempoB), 1e-17);
|
||||
}
|
||||
|
||||
void
|
||||
TempoTest::qnDistanceTestConstant ()
|
||||
{
|
||||
int const sampling_rate = 44100;
|
||||
|
||||
TempoMap map (sampling_rate);
|
||||
Meter meterA (4, 4);
|
||||
map.replace_meter (map.first_meter(), meterA, BBT_Time (1, 1, 0), AudioTime);
|
||||
|
||||
/*
|
||||
120bpm at bar 1, 240bpm at bar 4
|
||||
|
||||
120bpm = 24e3 samples per beat
|
||||
240bpm = 12e3 samples per beat
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
|
||||
120bpm 240bpm
|
||||
0 beats 12 beats
|
||||
0 frames 288e3 frames
|
||||
0 pulses 3 pulses
|
||||
| | | | |
|
||||
| 1.1 1.2 1.3 1.4 | 2.1 2.2 2.3.2.4 | 3.1 3.2 3.3 3.4 | 4.1 4.2 4.3 |
|
||||
|
||||
*/
|
||||
|
||||
Tempo tempoA (120.0, 4.0);
|
||||
map.replace_tempo (map.first_tempo(), tempoA, 0.0, 0, TempoSection::Constant, AudioTime);
|
||||
/* should have no effect on pulse */
|
||||
Tempo tempoB (120.0, 4.0);
|
||||
map.add_tempo (tempoB, 2.0, 0, TempoSection::Constant, MusicTime);
|
||||
/* equivalent to pulse 3.0 @ 120 bpm*/
|
||||
Tempo tempoC (240.0, 4.0);
|
||||
map.add_tempo (tempoC, 0.0, 6 * sampling_rate, TempoSection::Constant, AudioTime);
|
||||
Tempo tempoD (90.4, 4.0);
|
||||
map.add_tempo (tempoD, 9.0, 0, TempoSection::Constant, MusicTime);
|
||||
Tempo tempoE (110.6, 4.0);
|
||||
map.add_tempo (tempoE, 12.0, 0, TempoSection::Constant, MusicTime);
|
||||
Tempo tempoF (123.7, 4.0);
|
||||
map.add_tempo (tempoF, 15.0, 0, TempoSection::Constant, MusicTime);
|
||||
Tempo tempoG (111.8, 4.0);
|
||||
map.add_tempo (tempoG, 0.0, (framepos_t) 2 * 60 * sampling_rate, TempoSection::Constant, AudioTime);
|
||||
|
||||
Meter meterB (3, 4);
|
||||
map.add_meter (meterB, 12.0, BBT_Time (4, 1, 0), MusicTime);
|
||||
|
||||
list<MetricSection*>::iterator i = map._metrics.begin();
|
||||
CPPUNIT_ASSERT_EQUAL (framepos_t (0), (*i)->frame ());
|
||||
i = map._metrics.end();
|
||||
--i;
|
||||
CPPUNIT_ASSERT_EQUAL ((*i)->frame(), map.frames_between_quarter_notes (0.0, (*i)->pulse() * 4.0));
|
||||
|
||||
--i;
|
||||
/* tempoF */
|
||||
CPPUNIT_ASSERT_EQUAL ((*i)->frame(), map.frames_between_quarter_notes (0.0, 15.0 * 4.0));
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL ((*i)->minute(), map.minutes_between_quarter_notes_locked (map._metrics, 0.0, 15.0 * 4.0), 1e-17);
|
||||
|
||||
--i;
|
||||
/* tempoE */
|
||||
CPPUNIT_ASSERT_EQUAL ((*i)->frame(), map.frames_between_quarter_notes (0.0, 12.0 * 4.0));
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL ((*i)->minute(), map.minutes_between_quarter_notes_locked (map._metrics, 0.0, 12.0 * 4.0), 1e-17);
|
||||
|
||||
--i;
|
||||
CPPUNIT_ASSERT_EQUAL ((*i)->frame(), map.frames_between_quarter_notes (0.0, 9.0 * 4.0));
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL ((*i)->minute(), map.minutes_between_quarter_notes_locked (map._metrics, 0.0, 9.0 * 4.0), 1e-17);
|
||||
|
||||
--i;
|
||||
/* tempoC */
|
||||
CPPUNIT_ASSERT_EQUAL (framecnt_t (6 * sampling_rate), map.frames_between_quarter_notes (0.0, (*i)->pulse() * 4.0));
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (0.1, map.minutes_between_quarter_notes_locked (map._metrics, 0.0, (*i)->pulse() * 4.0), 1e-17);
|
||||
|
||||
/* distance from beat 12.0 to 0.0 should be 6.0 seconds */
|
||||
CPPUNIT_ASSERT_EQUAL (framecnt_t (264600), map.frames_between_quarter_notes (0.0, 3.0 * 4.0));
|
||||
CPPUNIT_ASSERT_EQUAL (framecnt_t (-264600), map.frames_between_quarter_notes (3.0 * 4.0, 0.0));
|
||||
CPPUNIT_ASSERT_EQUAL (framecnt_t (396900), map.frames_between_quarter_notes (0.0, 24.0));
|
||||
CPPUNIT_ASSERT_EQUAL (framecnt_t (-396900), map.frames_between_quarter_notes (24.0, 0.0));
|
||||
CPPUNIT_ASSERT_EQUAL (framecnt_t (88200), map.frames_between_quarter_notes (2.0 * 4.0, 3.0 * 4.0));
|
||||
}
|
||||
void
|
||||
TempoTest::qnDistanceTestRamp ()
|
||||
{
|
||||
int const sampling_rate = 44100;
|
||||
|
||||
TempoMap map (sampling_rate);
|
||||
Meter meterA (4, 4);
|
||||
map.replace_meter (map.first_meter(), meterA, BBT_Time (1, 1, 0), AudioTime);
|
||||
|
||||
/*
|
||||
120bpm at bar 1, 240bpm at bar 4
|
||||
|
||||
120bpm = 24e3 samples per beat
|
||||
240bpm = 12e3 samples per beat
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
|
||||
120bpm 240bpm
|
||||
0 beats 12 beats
|
||||
0 frames 288e3 frames
|
||||
0 pulses 3 pulses
|
||||
| | | | |
|
||||
| 1.1 1.2 1.3 1.4 | 2.1 2.2 2.3.2.4 | 3.1 3.2 3.3 3.4 | 4.1 4.2 4.3 |
|
||||
|
||||
*/
|
||||
|
||||
Tempo tempoA (120.2, 4.0);
|
||||
map.replace_tempo (map.first_tempo(), tempoA, 0.0, 0, TempoSection::Ramp, AudioTime);
|
||||
Tempo tempoB (240.5, 4.0);
|
||||
map.add_tempo (tempoB, 3.0, 0, TempoSection::Ramp, MusicTime);
|
||||
|
||||
Tempo tempoC (130.1, 4.0);
|
||||
map.add_tempo (tempoC, 0.0, 6 * sampling_rate, TempoSection::Ramp, AudioTime);
|
||||
Tempo tempoD (90.3, 4.0);
|
||||
map.add_tempo (tempoD, 9.0, 0, TempoSection::Ramp, MusicTime);
|
||||
Tempo tempoE (110.7, 4.0);
|
||||
map.add_tempo (tempoE, 12.0, 0, TempoSection::Ramp, MusicTime);
|
||||
Tempo tempoF (123.9, 4.0);
|
||||
map.add_tempo (tempoF, 15.0, 0, TempoSection::Ramp, MusicTime);
|
||||
Tempo tempoG (111.8, 4.0);
|
||||
map.add_tempo (tempoG, 0.0, (framepos_t) 2 * 60 * sampling_rate, TempoSection::Ramp, AudioTime);
|
||||
Meter meterB (3, 4);
|
||||
map.add_meter (meterB, 4.0, BBT_Time (2, 1, 0), AudioTime);
|
||||
map.recompute_map (map._metrics, 1);
|
||||
|
||||
list<MetricSection*>::iterator i = map._metrics.begin();
|
||||
CPPUNIT_ASSERT_EQUAL (framepos_t (0), (*i)->frame ());
|
||||
i = map._metrics.end();
|
||||
--i;
|
||||
/* tempoG */
|
||||
CPPUNIT_ASSERT_EQUAL ((*i)->frame(), map.frames_between_quarter_notes (0.0, (*i)->pulse() * 4.0));
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL ((*i)->minute(), map.minutes_between_quarter_notes_locked (map._metrics, 0.0, (*i)->pulse() * 4.0), 1e-17);
|
||||
|
||||
--i;
|
||||
CPPUNIT_ASSERT_EQUAL ((*i)->frame(), map.frames_between_quarter_notes (0.0, 60.0));
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL ((*i)->minute(), map.minutes_between_quarter_notes_locked (map._metrics, 0.0, 60.0), 1e-17);
|
||||
|
||||
--i;
|
||||
/* tempoE */
|
||||
CPPUNIT_ASSERT_EQUAL ((*i)->frame(), map.frames_between_quarter_notes (0.0, 48.0));
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL ((*i)->minute(), map.minutes_between_quarter_notes_locked (map._metrics, 0.0, 48.0), 1e-17);
|
||||
|
||||
--i;
|
||||
CPPUNIT_ASSERT_EQUAL ((*i)->frame(), map.frames_between_quarter_notes (0.0, 36.0));
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL ((*i)->minute(), map.minutes_between_quarter_notes_locked (map._metrics, 0.0, 36.0), 1e-17);
|
||||
|
||||
--i;
|
||||
/* tempoC */
|
||||
CPPUNIT_ASSERT_EQUAL (framecnt_t (6 * sampling_rate), map.frames_between_quarter_notes (0.0, (*i)->pulse() * 4.0));
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (0.1, map.minutes_between_quarter_notes_locked (map._metrics, 0.0, (*i)->pulse() * 4.0), 1e-17);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -85,7 +371,7 @@ TempoTest::rampTest48 ()
|
|||
Tempo tempoB (217.0, 4.0);
|
||||
map.replace_tempo (map.first_tempo(), tempoA, 0.0, 0, TempoSection::Ramp, AudioTime);
|
||||
map.add_tempo (tempoB, 0.0, (framepos_t) 60 * sampling_rate, TempoSection::Ramp, AudioTime);
|
||||
map.replace_meter (map.first_meter(), meterA, BBT_Time (1, 1, 0), (framepos_t) 0, AudioTime);
|
||||
map.replace_meter (map.first_meter(), meterA, BBT_Time (1, 1, 0), AudioTime);
|
||||
|
||||
/*
|
||||
|
||||
|
@ -109,26 +395,31 @@ TempoTest::rampTest48 ()
|
|||
TempoSection& tA = map.first_tempo();
|
||||
const TempoSection& tB = map.tempo_section_at_frame ((framepos_t) 60 * sampling_rate);
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL ((framepos_t) 60 * sampling_rate, tA.frame_at_tempo (tB.beats_per_minute(), 300.0, sampling_rate));
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (217.0, tA.tempo_at_frame ((framepos_t) 60 * sampling_rate, sampling_rate), 1e-17);
|
||||
CPPUNIT_ASSERT_EQUAL ((framepos_t) 60 * sampling_rate, tA.frame_at_pulse (tB.pulse(), sampling_rate));
|
||||
/* note 1e-14 here. (expm1) */
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (tB.pulse(), tA.pulse_at_frame ((framepos_t) 60 * sampling_rate, sampling_rate), 1e-14);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (1.0, tA.minute_at_ntpm (217.0, 300.0), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (217.0, tA.tempo_at_minute (1.0).note_types_per_minute(), 1e-17);
|
||||
|
||||
/* note 1e-14 here. pulse is two derivatives away from time */
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (tB.pulse(), tA.pulse_at_minute (1.0), 1e-14);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (1.0, tA.minute_at_pulse (tB.pulse()), 1e-15);
|
||||
|
||||
/* note 1e-17 here. tempo is one derivative away from pulse, so we can get the same stuff with more precision */
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (tB.pulse(), tA.pulse_at_ntpm (217.0, 1.0), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (1.0, tA.minute_at_ntpm (217.0, tB.pulse()), 1e-17);
|
||||
|
||||
/* self-check tempo at pulse @ 125 bpm. */
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (125.0, tA.tempo_at_pulse (tA.pulse_at_tempo (125.0, 0, sampling_rate)), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (125.0, tA.tempo_at_pulse (tA.pulse_at_ntpm (125.0, 0)).note_types_per_minute(), 1e-17);
|
||||
|
||||
/* check that tB's pulse is what tA thinks it should be */
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (tB.pulse(), tA.pulse_at_tempo (217.0, 0, sampling_rate), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (tB.pulse(), tA.pulse_at_ntpm (217.0, 0), 1e-17);
|
||||
|
||||
/* check that the tempo at the halfway mark (in pulses) is half the tempo delta.*/
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (147.0, tA.tempo_at_pulse (tB.pulse() / 2.0), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL ((tB.pulse() - tA.pulse()) / 2.0, tA.pulse_at_tempo (147.0, 0, sampling_rate), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (147.0, tA.tempo_at_pulse (tB.pulse() / 2.0).note_types_per_minute(), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL ((tB.pulse() - tA.pulse()) / 2.0, tA.pulse_at_ntpm (147.0, 0), 1e-17);
|
||||
|
||||
/* self-check frame at pulse 20 seconds in. */
|
||||
const framepos_t target = 20 * sampling_rate;
|
||||
const framepos_t result = tA.frame_at_pulse (tA.pulse_at_frame (target, sampling_rate), sampling_rate);
|
||||
CPPUNIT_ASSERT_EQUAL (target, result);
|
||||
const double target = 20.0 / 60.0;
|
||||
const double result = tA.minute_at_pulse (tA.pulse_at_minute (target));
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (target, result, 1e-14);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -142,7 +433,7 @@ TempoTest::rampTest44 ()
|
|||
Tempo tempoB (217.0, 4.0);
|
||||
map.replace_tempo (map.first_tempo(), tempoA, 0.0, 0, TempoSection::Ramp, AudioTime);
|
||||
map.add_tempo (tempoB, 0.0, (framepos_t) 60 * sampling_rate, TempoSection::Ramp, AudioTime);
|
||||
map.replace_meter (map.first_meter(), meterA, BBT_Time (1, 1, 0), (framepos_t) 0, AudioTime);
|
||||
map.replace_meter (map.first_meter(), meterA, BBT_Time (1, 1, 0), AudioTime);
|
||||
|
||||
/*
|
||||
|
||||
|
@ -166,25 +457,31 @@ TempoTest::rampTest44 ()
|
|||
TempoSection& tA = map.first_tempo();
|
||||
const TempoSection& tB = map.tempo_section_at_frame ((framepos_t) 60 * sampling_rate);
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL ((framepos_t) 60 * sampling_rate, tA.frame_at_tempo (tB.beats_per_minute(), 300.0, sampling_rate));
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (217.0, tA.tempo_at_frame ((framepos_t) 60 * sampling_rate, sampling_rate), 1e-17);
|
||||
CPPUNIT_ASSERT_EQUAL ((framepos_t) 60 * sampling_rate, tA.frame_at_pulse (tB.pulse(), sampling_rate));
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (tB.pulse(), tA.pulse_at_frame ((framepos_t) 60 * sampling_rate, sampling_rate), 1e-14);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (1.0, tA.minute_at_ntpm (217.0, 300.0), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (217.0, tA.tempo_at_minute (1.0).note_types_per_minute(), 1e-17);
|
||||
|
||||
/* note 1e-14 here. pulse is two derivatives away from time */
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (tB.pulse(), tA.pulse_at_minute (1.0), 1e-14);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (1.0, tA.minute_at_pulse (tB.pulse()), 1e-15);
|
||||
|
||||
/* note 1e-17 here. tempo is one derivative away from pulse, so we can get the same stuff with more precision */
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (tB.pulse(), tA.pulse_at_ntpm (217.0, 1.0), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (1.0, tA.minute_at_ntpm (217.0, tB.pulse()), 1e-17);
|
||||
|
||||
/* self-check tempo at pulse @ 125 bpm. */
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (125.0, tA.tempo_at_pulse (tA.pulse_at_tempo (125.0, 0, sampling_rate)), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (125.0, tA.tempo_at_pulse (tA.pulse_at_ntpm (125.0, 0)).note_types_per_minute(), 1e-17);
|
||||
|
||||
/* check that tB's pulse is what tA thinks it should be */
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (tB.pulse(), tA.pulse_at_tempo (217.0, 0, sampling_rate), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (tB.pulse(), tA.pulse_at_ntpm (217.0, 0), 1e-17);
|
||||
|
||||
/* check that the tempo at the halfway mark (in pulses) is half the tempo delta.*/
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (147.0, tA.tempo_at_pulse (tB.pulse() / 2.0), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL ((tB.pulse() - tA.pulse()) / 2.0, tA.pulse_at_tempo (147.0, 0, sampling_rate), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (147.0, tA.tempo_at_pulse (tB.pulse() / 2.0).note_types_per_minute(), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL ((tB.pulse() - tA.pulse()) / 2.0, tA.pulse_at_ntpm (147.0, 0), 1e-17);
|
||||
|
||||
/* self-check frame at pulse 20 seconds in. */
|
||||
const framepos_t target = 20 * sampling_rate;
|
||||
const framepos_t result = tA.frame_at_pulse (tA.pulse_at_frame (target, sampling_rate), sampling_rate);
|
||||
CPPUNIT_ASSERT_EQUAL (target, result);
|
||||
const double target = 20.0 / 60.0;
|
||||
const double result = tA.minute_at_pulse (tA.pulse_at_minute (target));
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (target, result, 1e-14);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -198,7 +495,7 @@ TempoTest::tempoAtPulseTest ()
|
|||
Tempo tempoB (160.0, 3.0);
|
||||
Tempo tempoC (123.0, 4.0);
|
||||
|
||||
map.replace_meter (map.first_meter(), meterA, BBT_Time (1, 1, 0), (framepos_t) 0, AudioTime);
|
||||
map.replace_meter (map.first_meter(), meterA, BBT_Time (1, 1, 0), AudioTime);
|
||||
map.replace_tempo (map.first_tempo(), tempoA, 0.0, 0, TempoSection::Ramp, AudioTime);
|
||||
|
||||
map.add_tempo (tempoB, 20.0, 0, TempoSection::Ramp, MusicTime);
|
||||
|
@ -228,23 +525,113 @@ TempoTest::tempoAtPulseTest ()
|
|||
}
|
||||
}
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL (160.0, tA->tempo_at_pulse (20.0));
|
||||
CPPUNIT_ASSERT_EQUAL (123.0, tB->tempo_at_pulse (30.0));
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (160.0, tA->tempo_at_pulse (20.0).note_types_per_minute(), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (123.0, tB->tempo_at_pulse (30.0).note_types_per_minute(), 1e-17);
|
||||
|
||||
/* check that the tempo at the halfway mark (in pulses) is half the tempo delta.*/
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (((80.0 - 160.0) / 2.0) + 160.0, tA->tempo_at_pulse (10.0), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (20.0 / 2.0, tA->pulse_at_tempo (120, 0, sampling_rate), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (((160.0 - 123.0) / 2.0) + 123.0, tB->tempo_at_pulse (25.0), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (((20.0 - 30.0) / 2.0) + 30.0, tB->pulse_at_tempo (141.5, 0, sampling_rate), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (((80.0 - 160.0) / 2.0) + 160.0, tA->tempo_at_pulse (10.0).note_types_per_minute(), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (20.0 / 2.0, tA->pulse_at_ntpm (120.0, 0), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (((160.0 - 123.0) / 2.0) + 123.0, tB->tempo_at_pulse (25.0).note_types_per_minute(), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (((20.0 - 30.0) / 2.0) + 30.0, tB->pulse_at_ntpm (141.5, 0), 1e-17);
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL (tB->frame(), tA->frame_at_pulse (20.0, sampling_rate));
|
||||
CPPUNIT_ASSERT_EQUAL (tC->frame(), tB->frame_at_pulse (30.0, sampling_rate));
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (tB->minute(), tA->minute_at_pulse (20.0), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (tC->minute(), tB->minute_at_pulse (30.0), 1e-17);
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL (tB->frame(), tA->frame_at_tempo (160.0, 20.0, sampling_rate));
|
||||
CPPUNIT_ASSERT_EQUAL (tC->frame(), tB->frame_at_tempo (123.0, 30.0, sampling_rate));
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (tB->minute(), tA->minute_at_ntpm (160.0, 20.0), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (tC->minute(), tB->minute_at_ntpm (123.0, 30.0), 1e-17);
|
||||
|
||||
/* self-check tempo at pulse @ 125 bpm. */
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (125.0, tA->tempo_at_pulse (tA->pulse_at_tempo (125.0, 0, sampling_rate)), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (160.0, tA->tempo_at_pulse (20.0), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (123.0, tB->tempo_at_pulse (30.0), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (125.0, tA->tempo_at_pulse (tA->pulse_at_ntpm (125.0, 0)).note_types_per_minute(), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (160.0, tA->tempo_at_pulse (20.0).note_types_per_minute(), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (123.0, tB->tempo_at_pulse (30.0).note_types_per_minute(), 1e-17);
|
||||
/* test minute based measurements */
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (tB->minute(), tA->minute_at_pulse (20.0), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (tC->minute(), tB->minute_at_pulse (30.0), 1e-17);
|
||||
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (tB->minute(), tA->minute_at_ntpm (160.0, 20.0), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (tC->minute(), tB->minute_at_ntpm (123.0, 30.0), 1e-17);
|
||||
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (160.0, tA->tempo_at_minute (tB->minute()).note_types_per_minute(), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (123.0, tB->tempo_at_minute (tC->minute()).note_types_per_minute(), 1e-17);
|
||||
}
|
||||
|
||||
void
|
||||
TempoTest::tempoFundamentalsTest ()
|
||||
{
|
||||
int const sampling_rate = 48000;
|
||||
|
||||
TempoMap map (sampling_rate);
|
||||
Meter meterA (4, 8);
|
||||
Tempo tempoA (120.0, 4.0);
|
||||
Tempo tempoB (120.0, 8.0);
|
||||
Tempo tempoC (120.0, 2.0);
|
||||
Tempo tempoD (160.0, 2.0);
|
||||
Tempo tempoE (123.0, 3.0);
|
||||
|
||||
map.replace_meter (map.first_meter(), meterA, BBT_Time (1, 1, 0), AudioTime);
|
||||
map.replace_tempo (map.first_tempo(), tempoA, 0.0, 0, TempoSection::Constant, AudioTime);
|
||||
|
||||
map.add_tempo (tempoB, 20.0, 0, TempoSection::Constant, MusicTime);
|
||||
map.add_tempo (tempoC, 30.0, 0, TempoSection::Constant, MusicTime);
|
||||
|
||||
map.add_tempo (tempoD, 40.0, 0, TempoSection::Constant, MusicTime);
|
||||
map.add_tempo (tempoE, 50.0, 0, TempoSection::Constant, MusicTime);
|
||||
|
||||
TempoSection* tA = 0;
|
||||
TempoSection* tB = 0;
|
||||
TempoSection* tC = 0;
|
||||
TempoSection* tD = 0;
|
||||
TempoSection* tE = 0;
|
||||
list<MetricSection*>::iterator i;
|
||||
|
||||
for (i = map._metrics.begin(); i != map._metrics.end(); ++i) {
|
||||
TempoSection* t;
|
||||
if ((t = dynamic_cast<TempoSection*> (*i)) != 0) {
|
||||
if (!tA) {
|
||||
tA = t;
|
||||
continue;
|
||||
}
|
||||
if (!tB) {
|
||||
tB = t;
|
||||
continue;
|
||||
}
|
||||
if (!tC) {
|
||||
tC = t;
|
||||
continue;
|
||||
}
|
||||
if (!tD) {
|
||||
tD = t;
|
||||
continue;
|
||||
}
|
||||
if (!tE) {
|
||||
tE = t;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (24000.0, tA->frames_per_quarter_note (sampling_rate), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (24000.0, tA->frames_per_note_type (sampling_rate), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (120.0, tA->quarter_notes_per_minute (), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (30.0, tA->pulses_per_minute (), 1e-17);
|
||||
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (48000.0, tB->frames_per_quarter_note (sampling_rate), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (24000.0, tB->frames_per_note_type (sampling_rate), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (60.0, tB->quarter_notes_per_minute (), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (15.0, tB->pulses_per_minute (), 1e-17);
|
||||
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (12000.0, tC->frames_per_quarter_note (sampling_rate), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (24000.0, tC->frames_per_note_type (sampling_rate), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (240.0, tC->quarter_notes_per_minute (), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (60.0, tC->pulses_per_minute (), 1e-17);
|
||||
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (9000.0, tD->frames_per_quarter_note (sampling_rate), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (18000.0, tD->frames_per_note_type (sampling_rate), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (320.0, tD->quarter_notes_per_minute (), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (80.0, tD->pulses_per_minute (), 1e-17);
|
||||
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (17560.975609756097, tE->frames_per_quarter_note (sampling_rate), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (23414.634146341465, tE->frames_per_note_type (sampling_rate), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (164.0, tE->quarter_notes_per_minute (), 1e-17);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL (41.0, tE->pulses_per_minute (), 1e-17);
|
||||
}
|
||||
|
|
|
@ -5,10 +5,14 @@
|
|||
class TempoTest : public CppUnit::TestFixture
|
||||
{
|
||||
CPPUNIT_TEST_SUITE (TempoTest);
|
||||
CPPUNIT_TEST (recomputeMapTest);
|
||||
CPPUNIT_TEST (recomputeMapTest48);
|
||||
CPPUNIT_TEST (recomputeMapTest44);
|
||||
CPPUNIT_TEST (qnDistanceTestConstant);
|
||||
CPPUNIT_TEST (qnDistanceTestRamp);
|
||||
CPPUNIT_TEST (rampTest48);
|
||||
CPPUNIT_TEST (rampTest44);
|
||||
CPPUNIT_TEST (tempoAtPulseTest);
|
||||
CPPUNIT_TEST (tempoFundamentalsTest);
|
||||
CPPUNIT_TEST_SUITE_END ();
|
||||
|
||||
public:
|
||||
|
@ -16,8 +20,13 @@ public:
|
|||
void tearDown () {}
|
||||
|
||||
void recomputeMapTest ();
|
||||
void recomputeMapTest44 ();
|
||||
void recomputeMapTest48 ();
|
||||
void qnDistanceTestConstant ();
|
||||
void qnDistanceTestRamp ();
|
||||
void rampTest48 ();
|
||||
void rampTest44 ();
|
||||
void tempoAtPulseTest();
|
||||
void tempoFundamentalsTest();
|
||||
};
|
||||
|
||||
|
|
|
@ -308,11 +308,7 @@ MidiClockTicker::tick (const framepos_t& /* transport_frame */, pframes_t nframe
|
|||
double
|
||||
MidiClockTicker::one_ppqn_in_frames (framepos_t transport_position)
|
||||
{
|
||||
const Tempo& current_tempo = _session->tempo_map().tempo_at_frame (transport_position);
|
||||
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 frames_per_quarter_note = frames_per_beat / quarter_notes_per_beat;
|
||||
const double frames_per_quarter_note = _session->tempo_map().frames_per_quarter_note_at (transport_position, _session->nominal_frame_rate());
|
||||
|
||||
return frames_per_quarter_note / double (_ppqn);
|
||||
}
|
||||
|
|
|
@ -132,7 +132,7 @@ JACKSession::timebase_callback (jack_transport_state_t /*state*/,
|
|||
pos->beats_per_bar = metric.meter().divisions_per_bar();
|
||||
pos->beat_type = metric.meter().note_divisor();
|
||||
pos->ticks_per_beat = Timecode::BBT_Time::ticks_per_beat;
|
||||
pos->beats_per_minute = metric.tempo().beats_per_minute();
|
||||
pos->beats_per_minute = metric.tempo().note_types_per_minute();
|
||||
|
||||
pos->valid = jack_position_bits_t (pos->valid | JackPositionBBT);
|
||||
|
||||
|
|
|
@ -68,7 +68,7 @@ write_bbt_source_to_source (boost::shared_ptr<MidiSource> bbt_source, boost::sh
|
|||
TempoMap& map (source->session().tempo_map());
|
||||
|
||||
for (Evoral::Sequence<MidiModel::TimeType>::const_iterator i = bbt_source->model()->begin(MidiModel::TimeType(), true); i != bbt_source->model()->end(); ++i) {
|
||||
const double new_time = map.quarter_note_at_beat ((*i).time().to_double() + map.beat_at_pulse (session_offset)) - (session_offset * 4.0);
|
||||
const double new_time = map.quarter_note_at_beat ((*i).time().to_double() + map.beat_at_quarter_note (session_offset * 4.0)) - (session_offset * 4.0);
|
||||
Evoral::Event<Evoral::Beats> new_ev (*i, true);
|
||||
new_ev.set_time (Evoral::Beats (new_time));
|
||||
source->append_event_beats (source_lock, new_ev);
|
||||
|
@ -135,7 +135,7 @@ ensure_per_region_source (Session* session, boost::shared_ptr<MidiRegion> region
|
|||
|
||||
Source::Lock newsrc_lock (newsrc->mutex());
|
||||
|
||||
write_bbt_source_to_source (region->midi_source(0), newsrc, newsrc_lock, region->pulse() - (region->start_beats() / 4.0));
|
||||
write_bbt_source_to_source (region->midi_source(0), newsrc, newsrc_lock, (region->quarter_note() - region->start_beats()) / 4.0);
|
||||
|
||||
cout << UTILNAME << ":" << endl
|
||||
<< " Created new midi source file" << endl
|
||||
|
@ -189,7 +189,7 @@ ensure_per_source_source (Session* session, boost::shared_ptr<MidiRegion> region
|
|||
|
||||
Source::Lock newsrc_lock (newsrc->mutex());
|
||||
|
||||
write_bbt_source_to_source (region->midi_source(0), newsrc, newsrc_lock, region->pulse() - (region->start_beats() / 4.0));
|
||||
write_bbt_source_to_source (region->midi_source(0), newsrc, newsrc_lock, (region->quarter_note() - region->start_beats()) / 4.0);
|
||||
|
||||
cout << UTILNAME << ":" << endl
|
||||
<< " Created new midi source file" << endl
|
||||
|
@ -206,13 +206,13 @@ reset_start (Session* session, boost::shared_ptr<MidiRegion> region)
|
|||
{
|
||||
/* set start_beats to quarter note value from incorrect bbt*/
|
||||
TempoMap& tmap (session->tempo_map());
|
||||
double new_start_qn = (tmap.pulse_at_beat (region->beat()) - tmap.pulse_at_beat (region->beat() - region->start_beats())) * 4.0;
|
||||
double new_start_qn = tmap.quarter_note_at_beat (region->beat()) - tmap.quarter_note_at_beat (region->beat() - region->start_beats());
|
||||
|
||||
/* force a change to start and start_beats */
|
||||
PositionLockStyle old_pls = region->position_lock_style();
|
||||
region->set_position_lock_style (AudioTime);
|
||||
region->set_start (tmap.frame_at_quarter_note (region->pulse() * 4.0) - tmap.frame_at_quarter_note ((region->pulse() * 4.0) - new_start_qn) + 1);
|
||||
region->set_start (tmap.frame_at_quarter_note (region->pulse() * 4.0) - tmap.frame_at_quarter_note ((region->pulse() * 4.0) - new_start_qn));
|
||||
region->set_start (tmap.frame_at_quarter_note (region->quarter_note()) - tmap.frame_at_quarter_note (region->quarter_note() - new_start_qn) + 1);
|
||||
region->set_start (tmap.frame_at_quarter_note (region->quarter_note()) - tmap.frame_at_quarter_note (region->quarter_note() - new_start_qn));
|
||||
region->set_position_lock_style (old_pls);
|
||||
|
||||
}
|
||||
|
@ -222,14 +222,14 @@ reset_length (Session* session, boost::shared_ptr<MidiRegion> region)
|
|||
{
|
||||
/* set length_beats to quarter note value */
|
||||
TempoMap& tmap (session->tempo_map());
|
||||
double new_length_qn = (tmap.pulse_at_beat (region->beat() + region->length_beats())
|
||||
- tmap.pulse_at_beat (region->beat())) * 4.0;
|
||||
double new_length_qn = tmap.quarter_note_at_beat (region->beat() + region->length_beats())
|
||||
- tmap.quarter_note_at_beat (region->beat());
|
||||
|
||||
/* force a change to length and length_beats */
|
||||
PositionLockStyle old_pls = region->position_lock_style();
|
||||
region->set_position_lock_style (AudioTime);
|
||||
region->set_length (tmap.frame_at_quarter_note ((region->pulse() * 4.0) + new_length_qn) + 1 - region->position(), 0);
|
||||
region->set_length (tmap.frame_at_quarter_note ((region->pulse() * 4.0) + new_length_qn)- region->position(), 0);
|
||||
region->set_length (tmap.frame_at_quarter_note (region->quarter_note() + new_length_qn) + 1 - region->position(), 0);
|
||||
region->set_length (tmap.frame_at_quarter_note (region->quarter_note() + new_length_qn)- region->position(), 0);
|
||||
region->set_position_lock_style (old_pls);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue