first round of changes to use timeline types, here basically for Region position/length/start

UNFINISHED WORK. Does not compile. But region.cc will compile, hence this snapshot
This commit is contained in:
Paul Davis 2020-08-09 14:18:28 -06:00
parent b5bf518a0a
commit d40bdf5e95
15 changed files with 384 additions and 362 deletions

View File

@ -113,7 +113,6 @@ class LIBARDOUR_API AudioRegion : public Region
/* Readable interface */
virtual samplecnt_t read (Sample*, samplepos_t pos, samplecnt_t cnt, int channel) const;
virtual samplecnt_t readable_length() const { return length(); }
virtual samplecnt_t read_at (Sample *buf, Sample *mixdown_buf, float *gain_buf,
samplepos_t position,

View File

@ -34,7 +34,7 @@ public:
~AudioRom();
samplecnt_t read (Sample*, samplepos_t pos, samplecnt_t cnt, int channel) const;
samplecnt_t readable_length() const { return _size; }
samplecnt_t readable_length_samples() const { return _size; }
uint32_t n_channels () const { return 1; }
private:

View File

@ -77,7 +77,6 @@ class LIBARDOUR_API MidiRegion : public Region
/* Stub Readable interface */
virtual samplecnt_t read (Sample*, samplepos_t /*pos*/, samplecnt_t /*cnt*/, int /*channel*/) const { return 0; }
virtual samplecnt_t readable_length() const { return length(); }
samplecnt_t read_at (Evoral::EventSink<samplepos_t>& dst,
samplepos_t position,
@ -157,12 +156,11 @@ class LIBARDOUR_API MidiRegion : public Region
bool set_name (const std::string & str);
void set_position_internal (samplepos_t pos, bool allow_bbt_recompute, const int32_t sub_num);
void set_position_music_internal (double qn);
void set_length_internal (samplecnt_t len, const int32_t sub_num);
void set_start_internal (samplecnt_t, const int32_t sub_num);
void trim_to_internal (samplepos_t position, samplecnt_t length, const int32_t sub_num);
void update_length_beats (const int32_t sub_num);
void set_position_internal (timepos_t pos);
void set_length_internal (timecnt_t const & len);
void set_start_internal (timecnt_t const &);
void trim_to_internal (timepos_t position, timecnt_t const & length);
void update_length_beats ();
void model_changed ();
void model_contents_changed ();

View File

@ -35,7 +35,7 @@ public:
load (Session&, std::string const&);
virtual samplecnt_t read (Sample*, samplepos_t pos, samplecnt_t cnt, int channel) const = 0;
virtual samplecnt_t readable_length() const = 0;
virtual samplecnt_t readable_length_samples() const = 0;
virtual uint32_t n_channels () const = 0;
};

View File

@ -29,6 +29,8 @@
#include <boost/enable_shared_from_this.hpp>
#include <boost/utility.hpp>
#include "temporal/timeline.h"
#include "pbd/undo.h"
#include "pbd/signals.h"
#include "ardour/ardour.h"
@ -59,14 +61,14 @@ namespace Properties {
LIBARDOUR_API extern PBD::PropertyDescriptor<bool> hidden;
LIBARDOUR_API extern PBD::PropertyDescriptor<bool> position_locked;
LIBARDOUR_API extern PBD::PropertyDescriptor<bool> valid_transients;
LIBARDOUR_API extern PBD::PropertyDescriptor<samplepos_t> start;
LIBARDOUR_API extern PBD::PropertyDescriptor<samplecnt_t> length;
LIBARDOUR_API extern PBD::PropertyDescriptor<samplepos_t> position;
LIBARDOUR_API extern PBD::PropertyDescriptor<timecnt_t> start;
LIBARDOUR_API extern PBD::PropertyDescriptor<timecnt_t> length;
LIBARDOUR_API extern PBD::PropertyDescriptor<timepos_t> position;
LIBARDOUR_API extern PBD::PropertyDescriptor<double> beat;
LIBARDOUR_API extern PBD::PropertyDescriptor<samplecnt_t> sync_position;
LIBARDOUR_API extern PBD::PropertyDescriptor<timecnt_t> sync_position;
LIBARDOUR_API extern PBD::PropertyDescriptor<layer_t> layer;
LIBARDOUR_API extern PBD::PropertyDescriptor<samplepos_t> ancestral_start;
LIBARDOUR_API extern PBD::PropertyDescriptor<samplecnt_t> ancestral_length;
LIBARDOUR_API extern PBD::PropertyDescriptor<timecnt_t> ancestral_start;
LIBARDOUR_API extern PBD::PropertyDescriptor<timecnt_t> ancestral_length;
LIBARDOUR_API extern PBD::PropertyDescriptor<float> stretch;
LIBARDOUR_API extern PBD::PropertyDescriptor<float> shift;
LIBARDOUR_API extern PBD::PropertyDescriptor<PositionLockStyle> position_lock_style;
@ -116,9 +118,22 @@ public:
* START: first sample of the region within its source(s)
* LENGTH: number of samples the region represents
*/
samplepos_t position () const { return _position; }
samplepos_t start () const { return _start; }
samplecnt_t length () const { return _length; }
timepos_t nt_position () const { return _position.val(); }
timecnt_t nt_start () const { return _start.val(); }
timecnt_t nt_length () const { return _length.val(); }
timepos_t nt_end() const;
timepos_t source_position () const;
timepos_t source_relative_position (Temporal::timepos_t const &) const;
timepos_t region_relative_position (Temporal::timepos_t const &) const;
samplepos_t position_sample () const { return _position.val().samples(); }
samplecnt_t start_sample () const { return _start.val().samples(); }
samplecnt_t length_samples () const { return _length.val().samples(); }
samplecnt_t readable_length_samples() const { return length_samples(); }
layer_t layer () const { return _layer; }
void set_selected_for_solo(bool yn);
@ -128,38 +143,41 @@ public:
/* these two are valid ONLY during a StateChanged signal handler */
samplepos_t last_position () const { return _last_position; }
samplecnt_t last_length () const { return _last_length; }
timepos_t last_position () const { return _last_position; }
timecnt_t last_length () const { return _last_length; }
samplepos_t ancestral_start () const { return _ancestral_start; }
samplecnt_t ancestral_length () const { return _ancestral_length; }
samplecnt_t ancestral_start_sample () const { return _ancestral_start.val().samples(); }
samplecnt_t ancestral_length_samples () const { return _ancestral_length.val().samples(); }
timecnt_t ancestral_start () const { return _ancestral_start.val(); }
timecnt_t ancestral_length () const { return _ancestral_length.val(); }
float stretch () const { return _stretch; }
float shift () const { return _shift; }
void set_ancestral_data (samplepos_t start, samplecnt_t length, float stretch, float shift);
void set_ancestral_data (timecnt_t const & start, timecnt_t const & length, float stretch, float shift);
sampleoffset_t sync_offset (int& dir) const;
samplepos_t sync_position () const;
timecnt_t sync_offset (int& dir) const;
timepos_t sync_position () const;
samplepos_t adjust_to_sync (samplepos_t) const;
timepos_t adjust_to_sync (timepos_t) const;
/* first_sample() is an alias; last_sample() just hides some math */
samplepos_t first_sample () const { return _position; }
samplepos_t last_sample () const { return _position + _length - 1; }
samplepos_t first_sample () const { return _position.val().samples(); }
samplepos_t last_sample () const { return first_sample() + length_samples() - 1; }
/** Return the earliest possible value of _position given the
* value of _start within the region's sources
*/
samplepos_t earliest_possible_position () const;
timepos_t earliest_possible_position () const;
/** Return the last possible value of _last_sample given the
* value of _startin the regions's sources
*/
samplepos_t latest_possible_sample () const;
Evoral::Range<samplepos_t> last_range () const {
return Evoral::Range<samplepos_t> (_last_position, _last_position + _last_length - 1);
//return Evoral::Range<samplepos_t> (_last_position, _last_position + _last_length - 1);
return Evoral::Range<samplepos_t> (0, 0);
}
Evoral::Range<samplepos_t> range () const {
@ -184,7 +202,7 @@ public:
PositionLockStyle position_lock_style () const { return _position_lock_style; }
void set_position_lock_style (PositionLockStyle ps);
void recompute_position_from_lock_style (const int32_t sub_num);
void recompute_position_from_lock_style ();
/* meter-based beat at the region position */
double beat () const { return _beat; }
@ -224,27 +242,27 @@ public:
/* EDITING OPERATIONS */
void set_length (samplecnt_t, const int32_t sub_num);
void set_start (samplepos_t);
void set_position (samplepos_t, int32_t sub_num = 0);
void set_position_music (double qn);
void set_initial_position (samplepos_t);
void special_set_position (samplepos_t);
void set_length (timecnt_t const &);
void set_start (timecnt_t const &);
void set_position (timepos_t);
void set_initial_position (timepos_t);
void special_set_position (timepos_t);
virtual void update_after_tempo_map_change (bool send_change = true);
void nudge_position (sampleoffset_t);
void nudge_position (timecnt_t const &);
bool at_natural_position () const;
void move_to_natural_position ();
void move_start (sampleoffset_t distance, const int32_t sub_num = 0);
void trim_front (samplepos_t new_position, const int32_t sub_num = 0);
void trim_end (samplepos_t new_position, const int32_t sub_num = 0);
void trim_to (samplepos_t position, samplecnt_t length, const int32_t sub_num = 0);
void move_start (timecnt_t const & distance);
void trim_front (timepos_t new_position);
void trim_end (timepos_t new_position);
void trim_to (timepos_t pos, timecnt_t const & length);
/* fades are inherently audio in nature and we specify them in samples */
virtual void fade_range (samplepos_t, samplepos_t) {}
void cut_front (samplepos_t new_position, const int32_t sub_num = 0);
void cut_end (samplepos_t new_position, const int32_t sub_num = 0);
void cut_front (timepos_t new_position);
void cut_end (timepos_t new_position);
void set_layer (layer_t l); /* ONLY Playlist can call this */
void raise ();
@ -252,7 +270,7 @@ public:
void raise_to_top ();
void lower_to_bottom ();
void set_sync_position (samplepos_t n);
void set_sync_position (timepos_t n);
void clear_sync_position ();
void set_hidden (bool yn);
void set_muted (bool yn);
@ -389,13 +407,13 @@ protected:
Region (boost::shared_ptr<const Region>);
/** Construct a region from another region, at an offset within that region */
Region (boost::shared_ptr<const Region>, ARDOUR::MusicSample start_offset);
Region (boost::shared_ptr<const Region>, timecnt_t start_offset);
/** Construct a region as a copy of another region, but with different sources */
Region (boost::shared_ptr<const Region>, const SourceList&);
/** Constructor for derived types only */
Region (Session& s, samplepos_t start, samplecnt_t length, const std::string& name, DataType);
Region (Session& s, timepos_t start, timecnt_t length, const std::string& name, DataType);
virtual bool can_trim_start_before_source_start () const {
return false;
@ -406,25 +424,24 @@ protected:
void send_change (const PBD::PropertyChange&);
virtual int _set_state (const XMLNode&, int version, PBD::PropertyChange& what_changed, bool send_signal);
void post_set (const PBD::PropertyChange&);
virtual void set_position_internal (samplepos_t pos, bool allow_bbt_recompute, const int32_t sub_num);
virtual void set_position_music_internal (double qn);
virtual void set_length_internal (samplecnt_t, const int32_t sub_num);
virtual void set_start_internal (samplecnt_t, const int32_t sub_num = 0);
bool verify_start_and_length (samplepos_t, samplecnt_t&);
virtual void set_position_internal (timepos_t pos);
virtual void set_length_internal (timecnt_t const &);
virtual void set_start_internal (timecnt_t const &);
bool verify_start_and_length (timecnt_t const &, timecnt_t&);
void first_edit ();
DataType _type;
PBD::Property<bool> _sync_marked;
PBD::Property<bool> _left_of_split;
PBD::Property<bool> _right_of_split;
PBD::Property<bool> _valid_transients;
PBD::Property<samplepos_t> _start;
PBD::Property<samplecnt_t> _length;
PBD::Property<samplepos_t> _position;
PBD::Property<double> _beat;
PBD::Property<bool> _sync_marked;
PBD::Property<bool> _left_of_split;
PBD::Property<bool> _right_of_split;
PBD::Property<bool> _valid_transients;
PBD::Property<timecnt_t> _start;
PBD::Property<timecnt_t> _length;
PBD::Property<timepos_t> _position;
PBD::Property<double> _beat;
/** Sync position relative to the start of our file */
PBD::Property<samplepos_t> _sync_position;
PBD::Property<timecnt_t> _sync_position;
double _quarter_note;
@ -452,15 +469,15 @@ protected:
private:
void mid_thaw (const PBD::PropertyChange&);
virtual void trim_to_internal (samplepos_t position, samplecnt_t length, const int32_t sub_num);
void modify_front (samplepos_t new_position, bool reset_fade, const int32_t sub_num);
void modify_end (samplepos_t new_position, bool reset_fade, const int32_t sub_num);
virtual void trim_to_internal (timepos_t position, timecnt_t const & length);
void modify_front (timepos_t new_position, bool reset_fade);
void modify_end (timepos_t new_position, bool reset_fade);
void maybe_uncopy ();
bool verify_start (samplepos_t);
bool verify_start_mutable (samplepos_t&_start);
bool verify_length (samplecnt_t&);
bool verify_start (timecnt_t const &);
bool verify_start_mutable (timecnt_t&);
bool verify_length (timecnt_t&);
virtual void recompute_at_start () = 0;
virtual void recompute_at_end () = 0;
@ -475,8 +492,8 @@ private:
PBD::Property<bool> _external;
PBD::Property<bool> _hidden;
PBD::Property<bool> _position_locked;
PBD::Property<samplepos_t> _ancestral_start;
PBD::Property<samplecnt_t> _ancestral_length;
PBD::Property<timecnt_t> _ancestral_start;
PBD::Property<timecnt_t> _ancestral_length;
PBD::Property<float> _stretch;
PBD::Property<float> _shift;
PBD::EnumProperty<PositionLockStyle> _position_lock_style;
@ -484,8 +501,8 @@ private:
PBD::Property<std::string> _tags;
PBD::Property<bool> _contents; // type is irrelevant
samplecnt_t _last_length;
samplepos_t _last_position;
timecnt_t _last_length;
timepos_t _last_position;
mutable RegionEditState _first_edit;
layer_t _layer;

View File

@ -43,7 +43,9 @@
#include <inttypes.h>
#include "temporal/bbt_time.h"
#include "temporal/superclock.h"
#include "temporal/time.h"
#include "temporal/timeline.h"
#include "temporal/types.h"
#include "pbd/id.h"
@ -85,6 +87,10 @@ typedef Temporal::samplecnt_t samplecnt_t;
typedef Temporal::samplepos_t samplepos_t;
typedef Temporal::sampleoffset_t sampleoffset_t;
typedef Temporal::timepos_t timepos_t;
typedef Temporal::timecnt_t timecnt_t;
typedef Temporal::superclock_t superclock_t;
static const layer_t max_layer = UINT32_MAX;
// a set of (time) intervals: first of pair is the offset of the start within the region, second is the offset of the end

View File

@ -79,6 +79,61 @@ DEFINE_ENUM_CONVERT(ARDOUR::LoopFadeChoice)
DEFINE_ENUM_CONVERT(MusicalMode::Type)
template <>
inline std::string to_string (ARDOUR::timepos_t val)
{
return val.to_string ();
}
template <>
inline ARDOUR::timepos_t string_to (std::string const & str)
{
ARDOUR::timepos_t tmp;
tmp.string_to (str);
return tmp;
}
template <>
inline bool to_string (ARDOUR::timepos_t val, std::string & str)
{
str = val.to_string ();
return true;
}
template <>
inline bool string_to (std::string const & str, ARDOUR::timepos_t & val)
{
return val.string_to (str);
}
template <>
inline std::string to_string (ARDOUR::timecnt_t val)
{
return val.to_string ();
}
template <>
inline ARDOUR::timecnt_t string_to (std::string const & str)
{
ARDOUR::timecnt_t tmp;
tmp.string_to (str);
return tmp;
}
template <>
inline bool to_string (ARDOUR::timecnt_t val, std::string & str)
{
str = val.to_string ();
return true;
}
template <>
inline bool string_to (std::string const & str, ARDOUR::timecnt_t & val)
{
return val.string_to (str);
}
template <>
inline bool to_string (ARDOUR::AutoState val, std::string& str)
{

View File

@ -46,7 +46,7 @@ EBUr128Analysis::run (Readable* src)
{
int ret = -1;
bool done = false;
samplecnt_t len = src->readable_length();
samplecnt_t len = src->readable_length_samples();
samplepos_t pos = 0;
uint32_t n_channels = src->n_channels();
Plugin::FeatureSet features;

View File

@ -114,13 +114,13 @@ Filter::finish (boost::shared_ptr<Region> region, SourceList& nsrcs, string regi
boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(*si);
if (afs) {
afs->done_with_peakfile_writes ();
afs->update_header (region->position(), *now, xnow);
afs->update_header (region->position_sample(), *now, xnow);
afs->mark_immutable ();
}
boost::shared_ptr<SMFSource> smfs = boost::dynamic_pointer_cast<SMFSource>(*si);
if (smfs) {
smfs->set_natural_position (region->position());
smfs->set_natural_position (region->position_sample());
smfs->flush ();
}
@ -139,10 +139,10 @@ Filter::finish (boost::shared_ptr<Region> region, SourceList& nsrcs, string regi
PropertyList plist;
plist.add (Properties::start, 0);
plist.add (Properties::length, region->length());
plist.add (Properties::length, region->nt_length());
plist.add (Properties::name, region_name);
plist.add (Properties::whole_file, true);
plist.add (Properties::position, region->position());
plist.add (Properties::position, region->nt_position());
boost::shared_ptr<Region> r = RegionFactory::create (nsrcs, plist);

View File

@ -354,24 +354,6 @@ MidiRegion::set_position_internal (samplepos_t pos, bool allow_bbt_recompute, co
}
}
void
MidiRegion::set_position_music_internal (double qn)
{
Region::set_position_music_internal (qn);
/* set _start to new position in tempo map */
_start = _session.tempo_map().samples_between_quarter_notes (quarter_note() - start_beats(), quarter_note());
if (position_lock_style() == AudioTime) {
_length_beats = _session.tempo_map().quarter_note_at_sample (_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 samples).
*/
_length = _session.tempo_map().samples_between_quarter_notes (quarter_note(), quarter_note() + length_beats());
}
}
samplecnt_t
MidiRegion::read_at (Evoral::EventSink<samplepos_t>& out,
samplepos_t position,

View File

@ -776,7 +776,9 @@ Playlist::add_region_internal (boost::shared_ptr<Region> region, samplepos_t pos
boost::shared_ptr<Playlist> foo (shared_from_this ());
region->set_playlist (boost::weak_ptr<Playlist> (foo));
}
if (for_music) {
#warning NUTEMPO FIXME need timepos_t here
region->set_position_music (quarter_note);
} else {
region->set_position (position, sub_num);

View File

@ -84,11 +84,11 @@ RBEffect::run (boost::shared_ptr<Region> r, Progress* progress)
string::size_type at;
#ifndef NDEBUG
cerr << "RBEffect: source region: position = " << region->position ()
<< ", start = " << region->start ()
<< ", length = " << region->length ()
<< ", ancestral_start = " << region->ancestral_start ()
<< ", ancestral_length = " << region->ancestral_length ()
cerr << "RBEffect: source region: position = " << region->position_sample ()
<< ", start = " << region->start_sample ()
<< ", length = " << region->length_samples ()
<< ", ancestral_start = " << region->ancestral_start_sample ()
<< ", ancestral_length = " << region->ancestral_length_samples ()
<< ", stretch " << region->stretch ()
<< ", shift " << region->shift () << endl;
#endif
@ -151,11 +151,10 @@ RBEffect::run (boost::shared_ptr<Region> r, Progress* progress)
double stretch = region->stretch () * tsr.time_fraction;
double shift = region->shift () * tsr.pitch_fraction;
samplecnt_t read_start = region->ancestral_start () +
samplecnt_t (region->start () / (double)region->stretch ());
samplecnt_t read_start = region->ancestral_start_sample () +
samplecnt_t (region->start_sample () / (double)region->stretch ());
samplecnt_t read_duration =
samplecnt_t (region->length () / (double)region->stretch ());
samplecnt_t read_duration = samplecnt_t (region->length_samples () / (double)region->stretch ());
uint32_t channels = region->n_channels ();
@ -221,7 +220,7 @@ RBEffect::run (boost::shared_ptr<Region> r, Progress* progress)
samplepos_t this_position;
this_position = read_start + pos -
region->start () + region->position ();
region->start_sample () + region->position_sample ();
this_read = region->master_read_at (buffers[i],
buffers[i],
@ -258,7 +257,7 @@ RBEffect::run (boost::shared_ptr<Region> r, Progress* progress)
samplepos_t this_position;
this_position = read_start + pos -
region->start () + region->position ();
region->start_sample () + region->position_sample ();
this_read = region->master_read_at (buffers[i],
buffers[i],
@ -269,7 +268,7 @@ RBEffect::run (boost::shared_ptr<Region> r, Progress* progress)
if (this_read != this_time) {
error << string_compose (_("tempoize: error reading data from %1 at %2 (wanted %3, got %4)"),
region->name (), pos + region->position (), this_time, this_read)
region->name (), pos + region->position_sample (), this_time, this_read)
<< endmsg;
goto out;
}
@ -353,15 +352,16 @@ RBEffect::run (boost::shared_ptr<Region> r, Progress* progress)
/* now reset ancestral data for each new region */
for (vector<boost::shared_ptr<Region> >::iterator x = results.begin (); x != results.end (); ++x) {
(*x)->set_ancestral_data (read_start,
read_duration,
(*x)->set_ancestral_data (timecnt_t (read_start, timepos_t()),
timecnt_t (read_duration, read_start),
stretch,
shift);
(*x)->set_master_sources (region->master_sources ());
/* multiply the old (possibly previously stretched) region length by the extra
* stretch this time around to get its new length. this is a non-music based edit atm.
*/
(*x)->set_length ((*x)->length () * tsr.time_fraction, 0);
#warning NUTEMPO FIXME should use (*x)->position() sa 2nd arg also needs to figure out units for first arg
(*x)->set_length (timecnt_t (samplepos_t ((*x)->length_samples () * tsr.time_fraction), (*x)->position_samples()));
}
/* stretch region gain envelope */

View File

@ -69,14 +69,14 @@ namespace ARDOUR {
PBD::PropertyDescriptor<bool> hidden;
PBD::PropertyDescriptor<bool> position_locked;
PBD::PropertyDescriptor<bool> valid_transients;
PBD::PropertyDescriptor<samplepos_t> start;
PBD::PropertyDescriptor<samplecnt_t> length;
PBD::PropertyDescriptor<samplepos_t> position;
PBD::PropertyDescriptor<timecnt_t> start;
PBD::PropertyDescriptor<timecnt_t> length;
PBD::PropertyDescriptor<timepos_t> position;
PBD::PropertyDescriptor<double> beat;
PBD::PropertyDescriptor<samplecnt_t> sync_position;
PBD::PropertyDescriptor<timecnt_t> sync_position;
PBD::PropertyDescriptor<layer_t> layer;
PBD::PropertyDescriptor<samplepos_t> ancestral_start;
PBD::PropertyDescriptor<samplecnt_t> ancestral_length;
PBD::PropertyDescriptor<timecnt_t> ancestral_start;
PBD::PropertyDescriptor<timecnt_t> ancestral_length;
PBD::PropertyDescriptor<float> stretch;
PBD::PropertyDescriptor<float> shift;
PBD::PropertyDescriptor<PositionLockStyle> position_lock_style;
@ -188,11 +188,11 @@ Region::register_properties ()
, _left_of_split (Properties::left_of_split, false) \
, _right_of_split (Properties::right_of_split, false) \
, _valid_transients (Properties::valid_transients, false) \
, _start (Properties::start, (s)) \
, _length (Properties::length, (l)) \
, _position (Properties::position, 0) \
, _start (Properties::start, timecnt_t (s, _type == DataType::MIDI ? timepos_t (Temporal::Beats()) : timepos_t (superclock_t (0)))) \
, _length (Properties::length, timecnt_t (l,timepos_t (s))) \
, _position (Properties::position, _type == DataType::MIDI ? timepos_t (Temporal::Beats()) : timepos_t (superclock_t (0))) \
, _beat (Properties::beat, 0.0) \
, _sync_position (Properties::sync_position, (s)) \
, _sync_position (Properties::sync_position, timecnt_t (s, _type == DataType::MIDI ? timepos_t (Temporal::Beats()) : timepos_t (superclock_t (0)))) \
, _quarter_note (0.0) \
, _transient_user_start (0) \
, _transient_analysis_start (0) \
@ -208,7 +208,7 @@ Region::register_properties ()
, _external (Properties::external, false) \
, _hidden (Properties::hidden, false) \
, _position_locked (Properties::position_locked, false) \
, _ancestral_start (Properties::ancestral_start, (s)) \
, _ancestral_start (Properties::ancestral_start, timecnt_t (s, _type == DataType::MIDI ? timepos_t (Temporal::Beats()) : timepos_t (superclock_t (0)))) \
, _ancestral_length (Properties::ancestral_length, (l)) \
, _stretch (Properties::stretch, 1.0) \
, _shift (Properties::shift, 1.0) \
@ -254,12 +254,12 @@ Region::register_properties ()
, _contents (Properties::contents, other->_contents)
/* derived-from-derived constructor (no sources in constructor) */
Region::Region (Session& s, samplepos_t start, samplecnt_t length, const string& name, DataType type)
Region::Region (Session& s, timepos_t start, timecnt_t length, const string& name, DataType type)
: SessionObject(s, name)
, _type(type)
, REGION_DEFAULT_STATE(start,length)
, _last_length (length)
, _last_position (0)
, _last_position (_type == DataType::MIDI ? timepos_t (Temporal::Beats()) : timepos_t (superclock_t (0)))
, _first_edit (EditChangesNothing)
, _layer (0)
, _changemap (0)
@ -273,9 +273,10 @@ Region::Region (Session& s, samplepos_t start, samplecnt_t length, const string&
Region::Region (const SourceList& srcs)
: SessionObject(srcs.front()->session(), "toBeRenamed")
, _type (srcs.front()->type())
, REGION_DEFAULT_STATE(0,0)
, _last_length (0)
, _last_position (0)
, REGION_DEFAULT_STATE(_type == DataType::MIDI ? timecnt_t (Temporal::Beats()) : timecnt_t (superclock_t(0)),
_type == DataType::MIDI ? timecnt_t (Temporal::Beats()) : timecnt_t (superclock_t (0)))
, _last_length (_type == DataType::MIDI ? timecnt_t (Temporal::Beats()) : timecnt_t (superclock_t (0)))
, _last_position (_type == DataType::MIDI ? timepos_t (Temporal::Beats()) : timepos_t (superclock_t (0)))
, _first_edit (EditChangesNothing)
, _layer (0)
, _changemap (0)
@ -354,7 +355,7 @@ Region::Region (boost::shared_ptr<const Region> other)
* the start within \a other is given by \a offset
* (i.e. relative to the start of \a other's sources, the start is \a offset + \a other.start()
*/
Region::Region (boost::shared_ptr<const Region> other, MusicSample offset)
Region::Region (boost::shared_ptr<const Region> other, timecnt_t offset)
: SessionObject(other->session(), other->name())
, _type (other->data_type())
, REGION_COPY_STATE (other)
@ -376,19 +377,8 @@ Region::Region (boost::shared_ptr<const Region> other, MusicSample offset)
use_sources (other->_sources);
set_master_sources (other->_master_sources);
_position = other->_position + offset.sample;
_start = other->_start + offset.sample;
/* prevent offset of 0 from altering musical position */
if (offset.sample != 0) {
const double offset_qn = _session.tempo_map().exact_qn_at_sample (other->_position + offset.sample, offset.division)
- other->_quarter_note;
_quarter_note = other->_quarter_note + offset_qn;
_beat = _session.tempo_map().beat_at_quarter_note (_quarter_note);
} else {
_quarter_note = _session.tempo_map().quarter_note_at_beat (_beat);
}
_position = other->_position.val() + offset;
_start = other->_start.val() + offset;
/* if the other region had a distinct sync point
* set, then continue to use it as best we can.
@ -482,29 +472,31 @@ Region::set_selected_for_solo(bool yn)
}
void
Region::set_length (samplecnt_t len, const int32_t sub_num)
Region::set_length (timecnt_t const & len)
{
//cerr << "Region::set_length() len = " << len << endl;
if (locked()) {
return;
}
if (_length != len && len != 0) {
if (_length != len && !len.zero()) {
/* check that the current _position wouldn't make the new
* length impossible.
*/
if (max_samplepos - len < _position) {
if (timepos_t::max().earlier (len) < _position) {
return;
}
if (!verify_length (len)) {
timecnt_t l = len;
if (!verify_length (l)) {
return;
}
set_length_internal (len, sub_num);
set_length_internal (l);
_whole_file = false;
first_edit ();
maybe_uncopy ();
@ -519,7 +511,7 @@ Region::set_length (samplecnt_t len, const int32_t sub_num)
}
void
Region::set_length_internal (samplecnt_t len, const int32_t sub_num)
Region::set_length_internal (timecnt_t const & len)
{
_last_length = _length;
_length = len;
@ -559,7 +551,7 @@ Region::at_natural_position () const
boost::shared_ptr<Region> whole_file_region = get_parent();
if (whole_file_region) {
if (_position == whole_file_region->position() + _start) {
if (_position == whole_file_region->nt_position() + _start) {
return true;
}
}
@ -579,12 +571,12 @@ Region::move_to_natural_position ()
boost::shared_ptr<Region> whole_file_region = get_parent();
if (whole_file_region) {
set_position (whole_file_region->position() + _start);
set_position (whole_file_region->nt_position() + _start);
}
}
void
Region::special_set_position (samplepos_t pos)
Region::special_set_position (timepos_t pos)
{
/* this is used when creating a whole file region as
* a way to store its "natural" or "captured" position.
@ -615,17 +607,10 @@ Region::update_after_tempo_map_change (bool send)
return;
}
if (_position_lock_style == AudioTime) {
/* don't signal as the actual position has not chnged */
recompute_position_from_lock_style (0);
if (_position.val().time_domain() == Temporal::AudioTime) {
return;
}
/* prevent movement before 0 */
const samplepos_t pos = max ((samplepos_t) 0, _session.tempo_map().sample_at_beat (_beat));
/* we have _beat. update sample position non-musically */
set_position_internal (pos, false, 0);
/* do this even if the position is the same. this helps out
* a GUI that has moved its representation already.
*/
@ -636,7 +621,7 @@ Region::update_after_tempo_map_change (bool send)
}
void
Region::set_position (samplepos_t pos, int32_t sub_num)
Region::set_position (timepos_t pos)
{
if (!can_move()) {
return;
@ -649,18 +634,16 @@ Region::set_position (samplepos_t pos, int32_t sub_num)
p_and_l.add (Properties::position);
if (position_lock_style() == AudioTime) {
set_position_internal (pos, true, sub_num);
} else {
if (!_session.loading()) {
_beat = _session.tempo_map().exact_beat_at_sample (pos, sub_num);
_quarter_note = _session.tempo_map().quarter_note_at_beat (_beat);
}
set_position_internal (pos);
set_position_internal (pos, false, sub_num);
}
/* if locked to beats or bbt, changing position can potentially change
* the length, because the tempo map may differ at the two different
* positions. Theoretically we could check this, but the cost of
* notifying about a (potential) length change is not that expensive
* given that we already are notifying about position change.
*/
if (position_lock_style() == MusicTime) {
if (position_lock_style() != AudioTime) {
p_and_l.add (Properties::length);
}
@ -669,85 +652,28 @@ Region::set_position (samplepos_t pos, int32_t sub_num)
}
void
Region::set_position_internal (samplepos_t pos, bool allow_bbt_recompute, const int32_t sub_num)
Region::set_position_internal (timepos_t pos)
{
/* We emit a change of Properties::position even if the position hasn't changed
* (see Region::set_position), so we must always set this up so that
* e.g. Playlist::notify_region_moved doesn't use an out-of-date last_position.
*/
_last_position = _position;
_last_length.set_position (_position);
if (_position != pos) {
_position = pos;
if (allow_bbt_recompute) {
recompute_position_from_lock_style (sub_num);
} else {
/* MusicTime dictates that we glue to ardour beats. the pulse may have changed.*/
_quarter_note = _session.tempo_map().quarter_note_at_beat (_beat);
}
_start.call().set_position (pos);
_length.call().set_position (pos);
/* check that the new _position wouldn't make the current
* length impossible - if so, change the length.
*
* XXX is this the right thing to do?
*/
if (max_samplepos - _length < _position) {
if (timepos_t::max().earlier (_length) < _position) {
_last_length = _length;
_length = max_samplepos - _position;
}
}
}
void
Region::set_position_music (double qn)
{
if (!can_move()) {
return;
}
/* do this even if the position is the same. this helps out
* a GUI that has moved its representation already.
*/
PropertyChange p_and_l;
p_and_l.add (Properties::position);
if (!_session.loading()) {
_beat = _session.tempo_map().beat_at_quarter_note (qn);
}
/* will set sample accordingly */
set_position_music_internal (qn);
if (position_lock_style() == MusicTime) {
p_and_l.add (Properties::length);
}
send_change (p_and_l);
}
void
Region::set_position_music_internal (double qn)
{
/* We emit a change of Properties::position even if the position hasn't changed
* (see Region::set_position), so we must always set this up so that
* e.g. Playlist::notify_region_moved doesn't use an out-of-date last_position.
*/
_last_position = _position;
if (_quarter_note != qn) {
_position = _session.tempo_map().sample_at_quarter_note (qn);
_quarter_note = qn;
/* check that the new _position wouldn't make the current
* length impossible - if so, change the length.
*
* XXX is this the right thing to do?
*/
if (max_samplepos - _length < _position) {
_last_length = _length;
_length = max_samplepos - _position;
_length = _position.call().distance (timepos_t::max());
}
}
}
@ -758,7 +684,7 @@ Region::set_position_music_internal (double qn)
* _last_position to prevent an implied move.
*/
void
Region::set_initial_position (samplepos_t pos)
Region::set_initial_position (timepos_t pos)
{
if (!can_move()) {
return;
@ -773,14 +699,15 @@ Region::set_initial_position (samplepos_t pos)
* XXX is this the right thing to do?
*/
if (max_samplepos - _length < _position) {
if (timepos_t::max().earlier (_length) < _position) {
_last_length = _length;
_length = max_samplepos - _position;
_length = _position.call().distance (timepos_t::max());
}
recompute_position_from_lock_style (0);
recompute_position_from_lock_style ();
/* ensure that this move doesn't cause a range move */
_last_position = _position;
_last_length.set_position (_position);
}
@ -791,46 +718,48 @@ Region::set_initial_position (samplepos_t pos)
}
void
Region::recompute_position_from_lock_style (const int32_t sub_num)
Region::recompute_position_from_lock_style ()
{
_beat = _session.tempo_map().exact_beat_at_sample (_position, sub_num);
_quarter_note = _session.tempo_map().exact_qn_at_sample (_position, sub_num);
/* XXX currently do nothing, but if we wanted to reduce lazy evaluation
* of timepos_t non-canonical values, we could possibly do it here.
*/
}
void
Region::nudge_position (sampleoffset_t n)
Region::nudge_position (timecnt_t const & n)
{
if (locked() || video_locked()) {
return;
}
if (n == 0) {
if (n.zero()) {
return;
}
samplepos_t new_position = _position;
timepos_t new_position = _position;
if (n > 0) {
if (_position > max_samplepos - n) {
new_position = max_samplepos;
if (n.positive()) {
if (nt_position() > timepos_t::max().earlier (n)) {
new_position = timepos_t::max();
} else {
new_position += n;
}
} else {
if (_position < -n) {
if (nt_position() < -n) {
new_position = 0;
} else {
new_position += n;
}
}
/* assumes non-musical nudge */
set_position_internal (new_position, true, 0);
set_position_internal (new_position);
send_change (Properties::position);
}
void
Region::set_ancestral_data (samplepos_t s, samplecnt_t l, float st, float sh)
Region::set_ancestral_data (timecnt_t const & s, timecnt_t const & l, float st, float sh)
{
_ancestral_length = l;
_ancestral_start = s;
@ -839,7 +768,7 @@ Region::set_ancestral_data (samplepos_t s, samplecnt_t l, float st, float sh)
}
void
Region::set_start (samplepos_t pos)
Region::set_start (timecnt_t const & pos)
{
if (locked() || position_locked() || video_locked()) {
return;
@ -851,11 +780,13 @@ Region::set_start (samplepos_t pos)
if (_start != pos) {
if (!verify_start (pos)) {
timecnt_t p = pos;
if (!verify_start (p)) {
return;
}
set_start_internal (pos);
set_start_internal (p);
_whole_file = false;
first_edit ();
maybe_invalidate_transients ();
@ -865,43 +796,40 @@ Region::set_start (samplepos_t pos)
}
void
Region::move_start (sampleoffset_t distance, const int32_t sub_num)
Region::move_start (timecnt_t const & distance)
{
if (locked() || position_locked() || video_locked()) {
return;
}
samplepos_t new_start;
timecnt_t new_start (_start);
if (distance > 0) {
if (distance.positive()) {
if (_start > max_samplepos - distance) {
new_start = max_samplepos; // makes no sense
if (_start > timecnt_t::max() - distance) {
new_start = timecnt_t::max(); // makes no sense
} else {
new_start = _start + distance;
new_start = nt_start() + distance;
}
if (!verify_start (new_start)) {
return;
}
} else if (distance < 0) {
} else {
if (_start < -distance) {
new_start = 0;
} else {
new_start = _start + distance;
new_start = nt_start() + distance;
}
} else {
return;
}
if (new_start == _start) {
return;
}
set_start_internal (new_start, sub_num);
set_start_internal (new_start);
_whole_file = false;
first_edit ();
@ -910,55 +838,56 @@ Region::move_start (sampleoffset_t distance, const int32_t sub_num)
}
void
Region::trim_front (samplepos_t new_position, const int32_t sub_num)
Region::trim_front (timepos_t new_position)
{
modify_front (new_position, false, sub_num);
modify_front (new_position, false);
}
void
Region::cut_front (samplepos_t new_position, const int32_t sub_num)
Region::cut_front (timepos_t new_position)
{
modify_front (new_position, true, sub_num);
modify_front (new_position, true);
}
void
Region::cut_end (samplepos_t new_endpoint, const int32_t sub_num)
Region::cut_end (timepos_t new_endpoint)
{
modify_end (new_endpoint, true, sub_num);
modify_end (new_endpoint, true);
}
void
Region::modify_front (samplepos_t new_position, bool reset_fade, const int32_t sub_num)
Region::modify_front (timepos_t new_position, bool reset_fade)
{
if (locked()) {
return;
}
samplepos_t end = last_sample();
samplepos_t source_zero;
timepos_t end = nt_end().decrement();
timepos_t source_zero;
if (_position > _start) {
source_zero = _position - _start;
if (nt_position() > nt_start()) {
source_zero = source_position ();
} else {
source_zero = 0; // its actually negative, but this will work for us
}
if (new_position < end) { /* can't trim it zero or negative length */
samplecnt_t newlen = 0;
timecnt_t newlen (_length);
timepos_t np = new_position;
if (!can_trim_start_before_source_start ()) {
/* can't trim it back past where source position zero is located */
new_position = max (new_position, source_zero);
np = max (np, source_zero);
}
if (new_position > _position) {
newlen = _length - (new_position - _position);
if (np > nt_position()) {
newlen = nt_length() - (nt_position().distance (np));
} else {
newlen = _length + (_position - new_position);
newlen = nt_length() + (np.distance (nt_position()));
}
trim_to_internal (new_position, newlen, sub_num);
trim_to_internal (np, newlen);
if (reset_fade) {
_right_of_split = true;
@ -973,14 +902,14 @@ Region::modify_front (samplepos_t new_position, bool reset_fade, const int32_t s
}
void
Region::modify_end (samplepos_t new_endpoint, bool reset_fade, const int32_t sub_num)
Region::modify_end (timepos_t new_endpoint, bool reset_fade)
{
if (locked()) {
return;
}
if (new_endpoint > _position) {
trim_to_internal (_position, new_endpoint - _position, sub_num);
trim_to_internal (_position, nt_position().distance (new_endpoint));
if (reset_fade) {
_left_of_split = true;
}
@ -994,19 +923,19 @@ Region::modify_end (samplepos_t new_endpoint, bool reset_fade, const int32_t sub
* a region at 0 of length 10 has an endpoint of 9.
*/
void
Region::trim_end (samplepos_t new_endpoint, const int32_t sub_num)
Region::trim_end (timepos_t new_endpoint)
{
modify_end (new_endpoint, false, sub_num);
modify_end (new_endpoint, false);
}
void
Region::trim_to (samplepos_t position, samplecnt_t length, const int32_t sub_num)
Region::trim_to (timepos_t position, timecnt_t const & length)
{
if (locked()) {
return;
}
trim_to_internal (position, length, sub_num);
trim_to_internal (position, length);
if (!property_changes_suspended()) {
recompute_at_start ();
@ -1015,48 +944,50 @@ Region::trim_to (samplepos_t position, samplecnt_t length, const int32_t sub_num
}
void
Region::trim_to_internal (samplepos_t position, samplecnt_t length, const int32_t sub_num)
Region::trim_to_internal (timepos_t position, timecnt_t const & length)
{
samplepos_t new_start;
timecnt_t new_start;
if (locked()) {
return;
}
sampleoffset_t const start_shift = position - _position;
timecnt_t const start_shift = nt_position().distance (position);
if (start_shift > 0) {
if (start_shift.positive()) {
if (_start > max_samplepos - start_shift) {
new_start = max_samplepos;
if (nt_start() > timecnt_t::max() - start_shift) {
new_start = timecnt_t::max();
} else {
new_start = _start + start_shift;
new_start = nt_start() + start_shift;
}
} else if (start_shift < 0) {
} else if (start_shift.negative()) {
if (_start < -start_shift && !can_trim_start_before_source_start ()) {
if (nt_start() < -start_shift && !can_trim_start_before_source_start ()) {
new_start = 0;
} else {
new_start = _start + start_shift;
new_start = nt_start() + start_shift;
}
} else {
new_start = _start;
new_start = nt_start();
}
if (!verify_start_and_length (new_start, length)) {
timecnt_t ns = new_start;
timecnt_t nl = length;
if (!verify_start_and_length (ns, nl)) {
return;
}
PropertyChange what_changed;
if (_start != new_start) {
set_start_internal (new_start, sub_num);
if (nt_start() != ns) {
set_start_internal (ns);
what_changed.add (Properties::start);
}
/* Set position before length, otherwise for MIDI regions this bad thing happens:
* 1. we call set_length_internal; length in beats is computed using the region's current
* (soon-to-be old) position
@ -1065,19 +996,19 @@ Region::trim_to_internal (samplepos_t position, samplecnt_t length, const int32_
* straddles a tempo/meter change.
*/
if (_position != position) {
if (nt_position() != position) {
if (!property_changes_suspended()) {
_last_position = _position;
}
set_position_internal (position, true, sub_num);
set_position_internal (position);
what_changed.add (Properties::position);
}
if (_length != length) {
if (nt_length() != nl) {
if (!property_changes_suspended()) {
_last_length = _length;
}
set_length_internal (length, sub_num);
set_length_internal (nl);
what_changed.add (Properties::length);
}
@ -1169,10 +1100,10 @@ Region::set_position_locked (bool yn)
* @param absolute_pos Session time.
*/
void
Region::set_sync_position (samplepos_t absolute_pos)
Region::set_sync_position (timepos_t absolute_pos)
{
/* position within our file */
samplepos_t const file_pos = _start + (absolute_pos - _position);
const timecnt_t file_pos = nt_start() + nt_position().distance (absolute_pos);
if (file_pos != _sync_position) {
_sync_marked = true;
@ -1199,7 +1130,7 @@ Region::clear_sync_position ()
}
/* @return the sync point relative the first sample of the region */
sampleoffset_t
timecnt_t
Region::sync_offset (int& dir) const
{
if (sync_marked()) {
@ -1212,42 +1143,43 @@ Region::sync_offset (int& dir) const
}
} else {
dir = 0;
return 0;
return timecnt_t ();
}
}
samplepos_t
Region::adjust_to_sync (samplepos_t pos) const
timepos_t
Region::adjust_to_sync (timepos_t pos) const
{
int sync_dir;
sampleoffset_t offset = sync_offset (sync_dir);
timepos_t p = pos;
timecnt_t offset = sync_offset (sync_dir);
// cerr << "adjusting pos = " << pos << " to sync at " << _sync_position << " offset = " << offset << " with dir = " << sync_dir << endl;
if (sync_dir > 0) {
if (pos > offset) {
pos -= offset;
p.shift_earlier (offset);
} else {
pos = 0;
p = 0;
}
} else {
if (max_samplepos - pos > offset) {
pos += offset;
if (timepos_t::max().earlier (timecnt_t (p, p)) > offset) {
p += offset;
}
}
return pos;
return p;
}
/** @return Sync position in session time */
samplepos_t
timepos_t
Region::sync_position() const
{
if (sync_marked()) {
return _position - _start + _sync_position;
return source_position() + _sync_position;
} else {
/* if sync has not been marked, use the start of the region */
return _position;
return nt_position();
}
}
@ -1409,8 +1341,9 @@ Region::_set_state (const XMLNode& node, int /*version*/, PropertyChange& what_c
*/
if (!_sources.empty() && _type == DataType::AUDIO) {
if (_length > _sources.front()->length(_position)) {
_length = _sources.front()->length(_position) - _start;
if ((nt_length().time_domain() == Temporal::AudioTime) && (length_samples() > _sources.front()->length(position_sample()))) {
#warning NUTEMPO FIXME do this better
//_length = Temporal::samples_to_superclock (_sources.front()->length(position_sample()) - start_sample(), Temporal::_thread_sample_rate);
}
}
@ -1424,7 +1357,7 @@ Region::_set_state (const XMLNode& node, int /*version*/, PropertyChange& what_c
&bbt_time.beats,
&bbt_time.ticks) != 3) {
_position_lock_style = AudioTime;
_beat = _session.tempo_map().beat_at_sample (_position);
_beat = _session.tempo_map().beat_at_sample (position_sample());
} else {
_beat = _session.tempo_map().beat_at_bbt (bbt_time);
}
@ -1745,20 +1678,23 @@ samplecnt_t
Region::source_length(uint32_t n) const
{
assert (n < _sources.size());
return _sources[n]->length (_position - _start);
#warning NUTEMPO FIXME needs Source to use timeline types
// return _sources[n]->length (_position - _start);
return 0;
}
bool
Region::verify_length (samplecnt_t& len)
Region::verify_length (timecnt_t& len)
{
if (source() && source()->length_mutable()) {
return true;
}
samplecnt_t maxlen = 0;
timecnt_t maxlen;
for (uint32_t n = 0; n < _sources.size(); ++n) {
maxlen = max (maxlen, source_length(n) - _start);
#warning NUTEMPO FIXME source needs timeline types
// maxlen = max (maxlen, source_length(n) - _start);
}
len = min (len, maxlen);
@ -1767,16 +1703,17 @@ Region::verify_length (samplecnt_t& len)
}
bool
Region::verify_start_and_length (samplepos_t new_start, samplecnt_t& new_length)
Region::verify_start_and_length (timecnt_t const & new_start, timecnt_t& new_length)
{
if (source() && source()->length_mutable()) {
return true;
}
samplecnt_t maxlen = 0;
timecnt_t maxlen;
for (uint32_t n = 0; n < _sources.size(); ++n) {
maxlen = max (maxlen, source_length(n) - new_start);
#warning NUTEMPO FIXME source needs timeline types
// maxlen = max (maxlen, source_length(n) - new_start);
}
new_length = min (new_length, maxlen);
@ -1785,31 +1722,33 @@ Region::verify_start_and_length (samplepos_t new_start, samplecnt_t& new_length)
}
bool
Region::verify_start (samplepos_t pos)
Region::verify_start (timecnt_t const & pos)
{
if (source() && source()->length_mutable()) {
return true;
}
for (uint32_t n = 0; n < _sources.size(); ++n) {
if (pos > source_length(n) - _length) {
return false;
}
#warning NUTEMPO FIXME source needs timeline types
// if (pos > source_length(n) - _length) {
// return false;
// }
}
return true;
}
bool
Region::verify_start_mutable (samplepos_t& new_start)
Region::verify_start_mutable (timecnt_t & new_start)
{
if (source() && source()->length_mutable()) {
return true;
}
for (uint32_t n = 0; n < _sources.size(); ++n) {
if (new_start > source_length(n) - _length) {
new_start = source_length(n) - _length;
}
#warning NUTEMPO FIXME source needs timeline types
// if (new_start > source_length(n) - _length) {
// new_start = source_length(n) - _length;
// }
}
return true;
}
@ -1855,8 +1794,8 @@ Region::transients (AnalysisFeatureList& afl)
{
int cnt = afl.empty() ? 0 : 1;
Region::merge_features (afl, _onsets, _position);
Region::merge_features (afl, _user_transients, _position + _transient_user_start - _start);
Region::merge_features (afl, _onsets, position_sample());
Region::merge_features (afl, _user_transients, position_sample() + _transient_user_start - start_sample());
if (!_onsets.empty ()) {
++cnt;
}
@ -2000,14 +1939,15 @@ Region::can_trim () const
ct = CanTrim (ct | FrontTrimLater | EndTrimEarlier);
if (start() != 0 || can_trim_start_before_source_start ()) {
if (nt_start() != 0 || can_trim_start_before_source_start ()) {
ct = CanTrim (ct | FrontTrimEarlier);
}
if (!_sources.empty()) {
if ((start() + length()) < _sources.front()->length (0)) {
ct = CanTrim (ct | EndTrimLater);
}
#warning NUTEMPO FIXME source needs timeline types
//if ((nt_start() + nt_length()) < _sources.front()->length (0)) {
// ct = CanTrim (ct | EndTrimLater);
//}
}
return ct;
@ -2038,18 +1978,18 @@ Region::post_set (const PropertyChange& pc)
}
void
Region::set_start_internal (samplecnt_t s, const int32_t sub_num)
Region::set_start_internal (timecnt_t const & s)
{
_start = s;
}
samplepos_t
timepos_t
Region::earliest_possible_position () const
{
if (_start > _position) {
if (nt_start() > timecnt_t (_position, timepos_t())) {
return 0;
} else {
return _position - _start;
return source_position();
}
}
@ -2062,12 +2002,32 @@ Region::latest_possible_sample () const
/* non-audio regions have a length that may vary based on their
* position, so we have to pass it in the call.
*/
minlen = min (minlen, (*i)->length (_position));
#warning NUTEMPO FIXME source needs timeline types
// minlen = min (minlen, (*i)->length_samples ((*i)->timeline_position()));
}
/* the latest possible last sample is determined by the current
* position, plus the shortest source extent past _start.
*/
return _position + (minlen - _start) - 1;
return position_sample() + (minlen - start_sample()) - 1;
}
timepos_t
Region::source_position () const
{
return _position.val().earlier (_start.val());
}
timepos_t
Region::source_relative_position (timepos_t const & p) const
{
return p.earlier (source_position());
}
timepos_t
Region::region_relative_position (timepos_t const & p) const
{
return p.earlier (_position.val());
}

View File

@ -52,8 +52,10 @@ Reverse::run (boost::shared_ptr<Region> r, Progress*)
int ret = -1;
boost::shared_ptr<AudioRegion> region = boost::dynamic_pointer_cast<AudioRegion>(r);
if (!region)
if (!region) {
return ret;
}
/* create new sources */
@ -61,13 +63,13 @@ Reverse::run (boost::shared_ptr<Region> r, Progress*)
goto out;
}
fstart = region->start();
fstart = region->start_sample();
if (blocksize > region->length()) {
blocksize = region->length();
if (blocksize > region->length_samples()) {
blocksize = region->length_samples();
}
fpos = max (fstart, (fstart + region->length() - blocksize));
fpos = max (fstart, (fstart + region->length_samples() - blocksize));
buf = new Sample[blocksize];
to_read = blocksize;

View File

@ -66,7 +66,7 @@ StripSilence::run (boost::shared_ptr<Region> r, Progress* progress)
const AudioIntervalResult& silence = sm->second;
if (silence.size () == 1 && silence.front().first == 0 && silence.front().second == region->length() - 1) {
if (silence.size () == 1 && silence.front().first == 0 && silence.front().second == region->length_samples() - 1) {
/* the region is all silence, so just return with nothing */
return 0;
}
@ -82,8 +82,8 @@ StripSilence::run (boost::shared_ptr<Region> r, Progress* progress)
/* Add the possible audible section at the start of the region */
AudioIntervalResult::const_iterator first_silence = silence.begin ();
if (first_silence->first != region->start()) {
audible.push_back (std::make_pair (r->start(), first_silence->first));
if (first_silence->first != region->start_sample()) {
audible.push_back (std::make_pair (r->start_sample(), first_silence->first));
}
/* Add audible sections in the middle of the region */
@ -100,7 +100,7 @@ StripSilence::run (boost::shared_ptr<Region> r, Progress* progress)
AudioIntervalResult::const_iterator last_silence = silence.end ();
--last_silence;
sampleoffset_t const end_of_region = r->start() + r->length();
sampleoffset_t const end_of_region = r->start_sample() + r->length_samples();
if (last_silence->second < end_of_region - 1) {
audible.push_back (std::make_pair (last_silence->second, end_of_region - 1));
@ -115,11 +115,12 @@ StripSilence::run (boost::shared_ptr<Region> r, Progress* progress)
boost::shared_ptr<AudioRegion> copy;
plist.add (Properties::length, i->second - i->first);
plist.add (Properties::position, r->position() + (i->first - r->start()));
plist.add (Properties::position, r->position_sample() + (i->first - r->start_sample()));
copy = boost::dynamic_pointer_cast<AudioRegion> (
RegionFactory::create (region, MusicSample (i->first - r->start(), 0), plist)
);
#warning NUTEMPO FIXME need new constructors etc.
// copy = boost::dynamic_pointer_cast<AudioRegion> (
// RegionFactory::create (region, MusicSample (i->first - r->start(), 0), plist)
// );
copy->set_name (RegionFactory::new_region_name (region->name ()));