Compare commits

...

29 Commits

Author SHA1 Message Date
nick_m 499a380cb2 remove debugging output 2016-11-11 03:26:21 +11:00
nick_m 17a1949cf0 remove unused variable and debugging. 2016-11-11 03:16:09 +11:00
nick_m 970555dc65 rename Region pos_beats -> quarter_note 2016-11-09 22:16:30 +11:00
nick_m a942ae7afb more tempo documentation. 2016-11-09 22:16:30 +11:00
nick_m 824f62983d ensure non-zero midi region length when tempo map changes. 2016-11-09 22:16:30 +11:00
nick_m 8f5b84359e TempoSection note-types-per-minute node name goes back to beats-per-minute for now. 2016-11-09 22:16:30 +11:00
nick_m 4e38e69e63 use note_type explicitly when constructing a Tempo in the hope that others follow.
- should be a no-op
2016-11-09 22:16:30 +11:00
nick_m a8c3928ed2 remove recently added xml nodes. 2016-11-09 22:16:30 +11:00
nick_m 3861ad8d6e use frame interval api for empoMap::framepos_plus_qn() 2016-11-09 22:16:30 +11:00
nick_m 41054c2ba4 clarify bbt_at_frame() warning. 2016-11-09 22:16:30 +11:00
nick_m 9666144828 rename note_divisions_per_minute -> ote_types_per_minute (double note_type) 2016-11-09 22:16:30 +11:00
nick_m cc9994af10 add empoMap::quarter_notes_between_frames().
- in an ideal world, this wouldn't be here at all,
	  but is required to support framewalk_to_qn().
	  if Beats are at tick resolution, the frame-induced
	  temporal rounding is acceptable.
2016-11-09 22:16:30 +11:00
nick_m 8719e139e8 TempoSection::tempo_at methods return a Tempo, document the opposite direction. 2016-11-09 22:16:30 +11:00
nick_m 337706a599 audio units uses quarter_notes_per_minute(). 2016-11-09 22:16:30 +11:00
nick_m b7be457c3c rename Tempo _beats_per_minute to _note_types_per_minute, provide pulse helpers.
- adds quarter_notes_per_minute(), note_divisions_per_minute (double)
	  pulses_per_minute() and frames_per_quarter_note()

	- this should be a no-op except for the use of tempo by
	  the vst callback which definitely uses quarter notes per minute.

	- the XML node for TempoSection named 'beats-per-minute'
	  has been renamed.
2016-11-09 22:16:30 +11:00
nick_m 43d5ed8b9d tempo doc explains that currently Tempo::beats_per_minute means something else.
- Tempo beats_per_minute() is currently implemented as note types per minute.
	  a further patch will change Tempo to reflect this and provide some helpers.
2016-11-09 22:16:30 +11:00
nick_m 56e1e5c9bb remove commented code. 2016-11-09 22:16:30 +11:00
nick_m c83a53abd8 more tempo documentation. 2016-11-09 22:16:30 +11:00
nick_m 808979c2e5 fix lock error in empoMap::quarter_note_at_bbt_rt(), expand constant tempo test. 2016-11-09 22:16:30 +11:00
nick_m 8909fe07d3 remove unused TempoMap::tempo_at_beat(). implement unused tempo_at_quarter_note(). 2016-11-09 22:16:30 +11:00
nick_m eabecd08d2 tempo.h reorganization. should be a no-op 2016-11-09 22:16:30 +11:00
nick_m 147af5ee41 more documentation in tempo.cc, fix constant bug in pulse_at_tempo_locked() 2016-11-09 22:16:30 +11:00
nick_m f268eb4c18 remove remaining frame api from TempoSection. 2016-11-09 22:16:30 +11:00
nick_m 473874a03b remove public pulse methods from TempoMap.
- the only object whose musical position is not expressed in
	  quarter notes is MetricSection.
	  there is now no need to expose this.
2016-11-09 22:16:30 +11:00
nick_m 29293439e5 add some documentation for TempoMap. 2016-11-09 22:16:30 +11:00
nick_m 6e17164b00 clamp setting tempo via vertical drag.
- a bit suboptimal. we really need the opposite of _trackview_only
	  to prevent jumping to track canvas scrolled coordinates in the first place.
2016-11-09 22:16:30 +11:00
nick_m 11d6dc51d0 rename Region pulse to pos_beats. use new beat distance api where required.
- add more debugging output detecting regions whose
	  beat and frame position do not align on a playlist.
	  this is required as a check as we have never used
	  frame rounding on constant tempi before 8884a5723dc
2016-11-09 22:16:30 +11:00
nick_m cbd353b578 MidiRegion _start/_length beats are frame based only when lock style is Audiotime 2016-11-09 22:14:08 +11:00
nick_m 7d4ab1b9ae Refactor tempo api, include quarter-note distance in frames method.
- moves frame rounding up to TempoMap, which is needed
	  in order to calculate pulse distance without frame rounding.

	- the time unit for tempo is still minute, but this now also
	  applies to meter sections. (new audio locked meter sections no
	  longer require a frame position).

	- there is no longer a discontinuity
	  in the pulse for audio-locked meter/tempi.

	- temporarily add debugging output in Region::set_position()
	  to test for region beat not matching region frame.
2016-11-09 22:14:08 +11:00
31 changed files with 1482 additions and 773 deletions

View File

@ -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")));

View File

@ -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);

View File

@ -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 */

View File

@ -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;
};

View File

@ -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;

View File

@ -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));

View File

@ -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);
}

View File

@ -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)));

View File

@ -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

View File

@ -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));

View File

@ -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 */

View File

@ -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 */

View File

@ -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&);

View File

@ -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;

View File

@ -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")

View File

@ -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)

View File

@ -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));

View File

@ -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;

View File

@ -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",

View File

@ -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);
}
}

View File

@ -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;
}

File diff suppressed because it is too large Load Diff

View File

@ -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 */
}

View File

@ -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 */

View File

@ -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 */

View File

@ -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

View File

@ -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);
}

View File

@ -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();
};

View File

@ -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);
}

View File

@ -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);

View File

@ -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);
}