summaryrefslogtreecommitdiff
path: root/libs/ardour/midi_region.cc
diff options
context:
space:
mode:
authornick_m <mainsbridge@gmail.com>2016-06-16 00:18:27 +1000
committernick_m <mainsbridge@gmail.com>2016-07-10 02:18:36 +1000
commit94e0a15325278ec26dbeba4990a0e883db859338 (patch)
treee4d97368112f92ba8a66c673b68c68f7a76b025a /libs/ardour/midi_region.cc
parent2d5238d87581bc0ff9dcaaa8aad9e255b5d9c370 (diff)
Exact beat - provide audio->music mapping for region split.
- for those not in the know, this series provides a way to remove the temporal distortion introduced when using an audio frame-based gui for music-locked objects. In short, the gui uses an audio frame representation to move objects. It displays the object using frame_at_beat(), quantizing the time value to audio frames. This is fine until the user selects that frame but expects it to be interpreted as a beat. Thus beat_at_frame() would not produce the user-expected beat (temporal quantization error of up to 0.5 audio samples). This is one method of mapping audio time to music time accurately.
Diffstat (limited to 'libs/ardour/midi_region.cc')
-rw-r--r--libs/ardour/midi_region.cc47
1 files changed, 25 insertions, 22 deletions
diff --git a/libs/ardour/midi_region.cc b/libs/ardour/midi_region.cc
index 26a8509aca..4d4c081c24 100644
--- a/libs/ardour/midi_region.cc
+++ b/libs/ardour/midi_region.cc
@@ -102,15 +102,14 @@ MidiRegion::MidiRegion (boost::shared_ptr<const MidiRegion> other)
}
/** Create a new MidiRegion that is part of an existing one */
-MidiRegion::MidiRegion (boost::shared_ptr<const MidiRegion> other, frameoffset_t offset)
- : Region (other, offset)
+MidiRegion::MidiRegion (boost::shared_ptr<const MidiRegion> other, frameoffset_t offset, const int32_t& sub_num)
+ : Region (other, offset, sub_num)
, _start_beats (Properties::start_beats, Evoral::Beats())
, _length_beats (Properties::length_beats, other->_length_beats)
{
- BeatsFramesConverter bfc (_session.tempo_map(), other->_position);
- Evoral::Beats const offset_beats = bfc.from (offset);
-
- _start_beats = other->_start_beats.val() + offset_beats;
+ const double offset_beat = _session.tempo_map().exact_beat_at_frame (other->_position + offset, sub_num) - other->beat();
+ _start_beats = Evoral::Beats (other->_start_beats.val().to_double() + offset_beat);
+ update_length_beats (sub_num);
register_properties ();
assert(_name.val().find("/") == string::npos);
@@ -173,7 +172,8 @@ MidiRegion::post_set (const PropertyChange& pc)
Region::post_set (pc);
if (pc.contains (Properties::length) && !pc.contains (Properties::length_beats)) {
- update_length_beats ();
+ /* update non-musically */
+ update_length_beats (0);
} else if (pc.contains (Properties::start) && !pc.contains (Properties::start_beats)) {
set_start_beats_from_start_frames ();
}
@@ -186,10 +186,10 @@ MidiRegion::set_start_beats_from_start_frames ()
}
void
-MidiRegion::set_length_internal (framecnt_t len)
+MidiRegion::set_length_internal (framecnt_t len, const int32_t& sub_num)
{
- Region::set_length_internal (len);
- update_length_beats ();
+ Region::set_length_internal (len, sub_num);
+ update_length_beats (sub_num);
}
void
@@ -198,26 +198,27 @@ MidiRegion::update_after_tempo_map_change (bool /* send */)
Region::update_after_tempo_map_change (false);
/* _start has now been updated. */
- _length = _session.tempo_map().framepos_plus_beats (_position, _length_beats) - _position;
+ _length = _session.tempo_map().frame_at_beat (beat() + _length_beats.val().to_double()) - _position;
PropertyChange s_and_l;
s_and_l.add (Properties::start);
s_and_l.add (Properties::length);
+ s_and_l.add (Properties::length_beats);
s_and_l.add (Properties::position);
send_change (s_and_l);
}
void
-MidiRegion::update_length_beats ()
+MidiRegion::update_length_beats (const int32_t& sub_num)
{
- _length_beats = Evoral::Beats (_session.tempo_map().beat_at_frame (_position + _length) - beat());
+ _length_beats = Evoral::Beats (_session.tempo_map().exact_beat_at_frame (_position + _length, sub_num) - beat());
}
void
-MidiRegion::set_position_internal (framepos_t pos, bool allow_bbt_recompute)
+MidiRegion::set_position_internal (framepos_t pos, bool allow_bbt_recompute, const int32_t& sub_num)
{
- Region::set_position_internal (pos, allow_bbt_recompute);
+ Region::set_position_internal (pos, allow_bbt_recompute, sub_num);
/* set _start to new position in tempo map */
_start = _position - _session.tempo_map().frame_at_beat (beat() - _start_beats.val().to_double());
@@ -225,7 +226,7 @@ MidiRegion::set_position_internal (framepos_t pos, bool allow_bbt_recompute)
/* 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_beat (beat() + _length_beats.val().to_double()) - _position);
+ Region::set_length_internal (_session.tempo_map().frame_at_beat (beat() + _length_beats.val().to_double()) - _position, sub_num);
}
framecnt_t
@@ -328,7 +329,10 @@ MidiRegion::set_state (const XMLNode& node, int version)
int ret = Region::set_state (node, version);
if (ret == 0) {
- update_length_beats ();
+ /* set length beats to the frame (non-musical) */
+ if (position_lock_style() == AudioTime) {
+ update_length_beats (0);
+ }
}
return ret;
@@ -490,11 +494,11 @@ MidiRegion::trim_to_internal (framepos_t position, framecnt_t length, const int3
*/
if (_position != position) {
- set_position_internal (position, true);
+ set_position_internal (position, true, sub_num);
what_changed.add (Properties::position);
}
- const double new_beat = _session.tempo_map().beat_at_frame (position);
+ const double new_beat = _session.tempo_map().exact_beat_at_frame (position, sub_num);
const double new_start_beat = _start_beats.val().to_double() + beat_delta;
new_start = _position - _session.tempo_map().frame_at_beat (new_beat - new_start_beat);
@@ -511,11 +515,10 @@ MidiRegion::trim_to_internal (framepos_t position, framecnt_t length, const int3
what_changed.add (Properties::start);
}
-
-
if (_length != length) {
- set_length_internal (length);
+ set_length_internal (length, sub_num);
what_changed.add (Properties::length);
+ what_changed.add (Properties::length_beats);
}
set_whole_file (false);