namespace Properties {
PBD::PropertyDescriptor<Evoral::Beats> start_beats;
PBD::PropertyDescriptor<Evoral::Beats> length_beats;
- PBD::PropertyDescriptor<double> start_pulse;
- PBD::PropertyDescriptor<double> length_pulse;
}
}
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for start-beats = %1\n", Properties::start_beats.property_id));
Properties::length_beats.property_id = g_quark_from_static_string (X_("length-beats"));
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for length-beats = %1\n", Properties::length_beats.property_id));
- Properties::start_pulse.property_id = g_quark_from_static_string (X_("start-pulse"));
- DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for start-pulse = %1\n", Properties::start_pulse.property_id));
- Properties::length_pulse.property_id = g_quark_from_static_string (X_("length-pulse"));
- DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for length-pulse = %1\n", Properties::length_pulse.property_id));
}
void
{
add_property (_start_beats);
add_property (_length_beats);
- add_property (_start_pulse);
- add_property (_length_pulse);
}
/* Basic MidiRegion constructor (many channels) */
: Region (srcs)
, _start_beats (Properties::start_beats, Evoral::Beats())
, _length_beats (Properties::length_beats, midi_source(0)->length_beats())
- , _start_pulse (Properties::start_pulse, 0)
- , _length_pulse (Properties::length_pulse, midi_source(0)->length_pulse())
{
register_properties ();
-
midi_source(0)->ModelChanged.connect_same_thread (_source_connection, boost::bind (&MidiRegion::model_changed, this));
model_changed ();
assert(_name.val().find("/") == string::npos);
: Region (other)
, _start_beats (Properties::start_beats, other->_start_beats)
, _length_beats (Properties::length_beats, other->_length_beats)
- , _start_pulse (Properties::start_pulse, other->_start_pulse)
- , _length_pulse (Properties::length_pulse, other->_length_pulse)
{
//update_length_beats ();
register_properties ();
: Region (other, offset, sub_num)
, _start_beats (Properties::start_beats, Evoral::Beats())
, _length_beats (Properties::length_beats, other->_length_beats)
- , _start_pulse (Properties::start_pulse, 0)
- , _length_pulse (Properties::length_pulse, other->_length_pulse)
{
- _start_beats = Evoral::Beats (_session.tempo_map().exact_beat_at_frame (other->_position + offset, sub_num) - other->beat()) + other->_start_beats;
- _start_pulse = ((_session.tempo_map().exact_qn_at_frame (other->_position + offset, sub_num) / 4.0) - other->_pulse) + other->_start_pulse;
+ _start_beats = Evoral::Beats (_session.tempo_map().exact_qn_at_frame (other->_position + offset, sub_num) - (other->pulse() * 4.0)) + other->_start_beats;
update_length_beats (sub_num);
register_properties ();
plist.add (Properties::start_beats, _start_beats);
plist.add (Properties::length, _length);
plist.add (Properties::length_beats, _length_beats);
- plist.add (Properties::start_pulse, _start_pulse);
- plist.add (Properties::length_pulse, _length_pulse);
plist.add (Properties::layer, 0);
boost::shared_ptr<MidiRegion> ret (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (newsrc, plist, true)));
void
MidiRegion::set_start_beats_from_start_frames ()
{
- _start_beats = Evoral::Beats (beat() - _session.tempo_map().beat_at_frame (_position - _start));
- _start_pulse = pulse() - _session.tempo_map().pulse_at_frame (_position - _start);
+ _start_beats = Evoral::Beats ((pulse() * 4.0) - _session.tempo_map().quarter_note_at_frame (_position - _start));
}
void
/*
set _start to new position in tempo map.
- The user probably expects the region contents to maintain audio position as the
+ The user probably expects the region contents to maintain audio position as the
tempo changes, but AFAICT this requires modifying the src file to use
SMPTE timestamps with the current disk read model (?).
For now, the musical position at the region start is retained, but subsequent events
will maintain their beat distance according to the map.
*/
- _start = _position - _session.tempo_map().frame_at_beat (beat() - _start_beats.val().to_double());
+ _start = _position - _session.tempo_map().frame_at_pulse (pulse() - (_start_beats.val().to_double() / 4.0));
/* _length doesn't change for audio-locked regions. update length_beats to match. */
- _length_beats = Evoral::Beats (_session.tempo_map().beat_at_frame (_position + _length) - _session.tempo_map().beat_at_frame (_position));
- _length_pulse = _session.tempo_map().pulse_at_frame (_position + _length) - _session.tempo_map().pulse_at_frame (_position);
+ _length_beats = Evoral::Beats (_session.tempo_map().quarter_note_at_frame (_position + _length) - _session.tempo_map().quarter_note_at_frame (_position));
s_and_l.add (Properties::start);
s_and_l.add (Properties::length_beats);
Region::update_after_tempo_map_change (false);
/* _start has now been updated. */
- _length = _session.tempo_map().frame_at_pulse (pulse() + _length_pulse) - _position;
+ _length = _session.tempo_map().frame_at_pulse (pulse() + (_length_beats.val().to_double() / 4.0)) - _position;
if (old_start != _start) {
s_and_l.add (Properties::start);
void
MidiRegion::update_length_beats (const int32_t sub_num)
{
- _length_beats = Evoral::Beats (_session.tempo_map().exact_beat_at_frame (_position + _length, sub_num) - beat());
- _length_pulse = (_session.tempo_map().exact_qn_at_frame (_position + _length, sub_num) / 4.0) - pulse();
+ _length_beats = Evoral::Beats (_session.tempo_map().exact_qn_at_frame (_position + _length, sub_num) - (pulse() * 4.0));
}
void
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());
+ _start = _position - _session.tempo_map().frame_at_pulse (pulse() - (_start_beats.val().to_double() / 4.0));
/* in construction from src */
if (_length_beats == Evoral::Beats()) {
}
if (position_lock_style() == AudioTime) {
- _length_beats = Evoral::Beats (_session.tempo_map().beat_at_frame (_position + _length) - _session.tempo_map().beat_at_frame (_position));
- _length_pulse = _session.tempo_map().pulse_at_frame (_position + _length) - _session.tempo_map().pulse_at_frame (_position);
+ _length_beats = Evoral::Beats (_session.tempo_map().quarter_note_at_frame (_position + _length) - _session.tempo_map().quarter_note_at_frame (_position));
} 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_pulse (pulse() + _length_pulse) - _position, sub_num);
+ Region::set_length_internal (_session.tempo_map().frame_at_pulse (pulse() + (_length_beats.val().to_double() / 4.0)) - _position, sub_num);
}
}
MidiRegion::read_at (Evoral::EventSink<framepos_t>& out,
framepos_t position,
framecnt_t dur,
+ Evoral::Range<framepos_t>* loop_range,
uint32_t chan_n,
NoteMode mode,
MidiStateTracker* tracker,
MidiChannelFilter* filter) const
{
- return _read_at (_sources, out, position, dur, chan_n, mode, tracker, filter);
+ return _read_at (_sources, out, position, dur, loop_range, chan_n, mode, tracker, filter);
}
framecnt_t
-MidiRegion::master_read_at (MidiRingBuffer<framepos_t>& out, framepos_t position, framecnt_t dur, uint32_t chan_n, NoteMode mode) const
+MidiRegion::master_read_at (MidiRingBuffer<framepos_t>& out,
+ framepos_t position,
+ framecnt_t dur,
+ Evoral::Range<framepos_t>* loop_range,
+ uint32_t chan_n,
+ NoteMode mode) const
{
- return _read_at (_master_sources, out, position, dur, chan_n, mode); /* no tracker */
+ return _read_at (_master_sources, out, position, dur, loop_range, chan_n, mode); /* no tracker */
}
framecnt_t
Evoral::EventSink<framepos_t>& dst,
framepos_t position,
framecnt_t dur,
+ Evoral::Range<framepos_t>* loop_range,
uint32_t chan_n,
NoteMode mode,
MidiStateTracker* tracker,
src->set_note_mode(lm, mode);
- /*
- cerr << "MR " << name () << " read @ " << position << " * " << to_read
- << " _position = " << _position
- << " _start = " << _start
- << " intoffset = " << internal_offset
- << " pulse = " << pulse()
- << " start_pulse = " << start_pulse()
- << " start_beat = " << _start_beats
- << endl;
- */
+#if 0
+ cerr << "MR " << name () << " read @ " << position << " + " << to_read
+ << " dur was " << dur
+ << " len " << _length
+ << " l-io " << (_length - internal_offset)
+ << " _position = " << _position
+ << " _start = " << _start
+ << " intoffset = " << internal_offset
+ << " pulse = " << pulse()
+ << " start_pulse = " << start_pulse()
+ << " start_beat = " << _start_beats
+ << endl;
+#endif
/* This call reads events from a source and writes them to `dst' timed in session frames */
if (src->midi_read (
lm, // source lock
- dst, // destination buffer
- _position - _start, // start position of the source in session frames
- _start + internal_offset, // where to start reading in the source
- to_read, // read duration in frames
- tracker,
- filter,
- _filtered_parameters,
- pulse(),
- start_pulse()
+ dst, // destination buffer
+ _position - _start, // start position of the source in session frames
+ _start + internal_offset, // where to start reading in the source
+ to_read, // read duration in frames
+ loop_range,
+ tracker,
+ filter,
+ _filtered_parameters,
+ pulse(),
+ _start_beats.val().to_double()
) != to_read) {
return 0; /* "read nothing" */
}
return boost::dynamic_pointer_cast<MidiSource>(source(n));
}
+/* don't use this. hopefully it will go away.
+ currently used by headless-chicken session utility.
+*/
+void
+MidiRegion::clobber_sources (boost::shared_ptr<MidiSource> s)
+{
+ drop_sources();
+
+ _sources.push_back (s);
+ s->inc_use_count ();
+ _master_sources.push_back (s);
+ s->inc_use_count ();
+
+ s->DropReferences.connect_same_thread (*this, boost::bind (&Region::source_deleted, this, boost::weak_ptr<Source>(s)));
+
+}
+
void
MidiRegion::model_changed ()
{
model()->insert_silence_at_start (c.from (-_start));
_start = 0;
_start_beats = Evoral::Beats();
- _start_pulse = 0.0;
}
void
working in beats seems the correct thing to do, but reports of a missing first note
on playback suggest otherwise. for now, we work in exact beats.
*/
- const double pos_beat = _session.tempo_map().exact_beat_at_frame (position, sub_num);
- const double beat_delta = pos_beat - beat();
const double pos_pulse = _session.tempo_map().exact_qn_at_frame (position, sub_num) / 4.0;
const double pulse_delta = pos_pulse - pulse();
set_position_internal (position, true, sub_num);
what_changed.add (Properties::position);
- const double new_start_beat = _start_beats.val().to_double() + beat_delta;
- const double new_start_pulse = _start_pulse + pulse_delta;
+ const double new_start_pulse = (_start_beats.val().to_double() / 4.0) + pulse_delta;
const framepos_t new_start = _position - _session.tempo_map().frame_at_pulse (pulse() - new_start_pulse);
if (!verify_start_and_length (new_start, length)) {
return;
}
- _start_beats = Evoral::Beats (new_start_beat);
+ _start_beats = Evoral::Beats (new_start_pulse * 4.0);
what_changed.add (Properties::start_beats);
- _start_pulse = new_start_pulse;
- what_changed.add (Properties::start_pulse);
-
set_start_internal (new_start, sub_num);
what_changed.add (Properties::start);
}