libardour: conversion to use timeline types (mega-commit)

This commit is contained in:
Paul Davis 2020-09-20 16:34:09 -06:00
parent bca8e2e8cc
commit eae9d276fe
131 changed files with 2088 additions and 2856 deletions

View File

@ -103,7 +103,7 @@ Analyser::work ()
boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (src);
if (afs && afs->length(afs->natural_position())) {
if (afs && !afs->empty()) {
Glib::Threads::Mutex::Lock lm (analysis_active_lock);
analyse_audio_file_source (afs);
}

View File

@ -76,23 +76,24 @@ AnalysisGraph::analyze_region (AudioRegion const* region, bool raw, ARDOUR::Prog
_session->nominal_sample_rate(),
n_channels,
n_samples,
region->length()));
region->length_samples()));
interleaver->add_output(chunker);
chunker->add_output (analyser);
samplecnt_t x = 0;
samplecnt_t length = region->length();
samplecnt_t length = region->length_samples();
while (x < length) {
samplecnt_t chunk = std::min (_max_chunksize, length - x);
samplecnt_t n = 0;
for (unsigned int channel = 0; channel < region->n_channels(); ++channel) {
memset (_buf, 0, chunk * sizeof (Sample));
if (raw) {
n = region->read_raw_internal (_buf, region->start() + x, chunk, channel);
n = region->read_raw_internal (_buf, region->start_sample() + x, chunk, channel);
} else {
n = region->read_at (_buf, _mixbuf, _gainbuf, region->position() + x, chunk, channel);
n = region->read_at (_buf, _mixbuf, _gainbuf, region->position_sample() + x, chunk, channel);
}
ConstProcessContext<Sample> context (_buf, n, 1);
if (n < _max_chunksize) {
context().set_flag (ProcessContext<Sample>::EndOfInput);
@ -121,7 +122,7 @@ AnalysisGraph::analyze_region (AudioRegion const* region, bool raw, ARDOUR::Prog
}
void
AnalysisGraph::analyze_range (boost::shared_ptr<Route> route, boost::shared_ptr<AudioPlaylist> pl, const std::list<AudioRange>& range)
AnalysisGraph::analyze_range (boost::shared_ptr<Route> route, boost::shared_ptr<AudioPlaylist> pl, const std::list<TimelineRange>& range)
{
const uint32_t n_audio = route->n_inputs().n_audio();
if (n_audio == 0 || n_audio > _max_chunksize) {
@ -129,7 +130,7 @@ AnalysisGraph::analyze_range (boost::shared_ptr<Route> route, boost::shared_ptr<
}
const samplecnt_t n_samples = _max_chunksize - (_max_chunksize % n_audio);
for (std::list<AudioRange>::const_iterator j = range.begin(); j != range.end(); ++j) {
for (std::list<TimelineRange>::const_iterator j = range.begin(); j != range.end(); ++j) {
interleaver.reset (new Interleaver<Sample> ());
interleaver->init (n_audio, _max_chunksize);
@ -137,17 +138,21 @@ AnalysisGraph::analyze_range (boost::shared_ptr<Route> route, boost::shared_ptr<
chunker.reset (new Chunker<Sample> (n_samples));
analyser.reset (new Analyser (
_session->nominal_sample_rate(),
n_audio, n_samples, (*j).length()));
n_audio, n_samples, (*j).length_samples()));
interleaver->add_output(chunker);
chunker->add_output (analyser);
samplecnt_t x = 0;
while (x < j->length()) {
samplecnt_t chunk = std::min (_max_chunksize, (*j).length() - x);
const samplecnt_t rlen = j->length().samples();
const samplepos_t rpos = j->start().samples();
while (x < rlen) {
samplecnt_t chunk = std::min (_max_chunksize, rlen - x);
samplecnt_t n = 0;
for (uint32_t channel = 0; channel < n_audio; ++channel) {
n = pl->read (_buf, _mixbuf, _gainbuf, (*j).start + x, chunk, channel);
n = pl->read (_buf, _mixbuf, _gainbuf, timepos_t (rpos + x), timecnt_t (chunk), channel).samples();
ConstProcessContext<Sample> context (_buf, n, 1);
if (n < _max_chunksize) {
@ -165,11 +170,11 @@ AnalysisGraph::analyze_range (boost::shared_ptr<Route> route, boost::shared_ptr<
std::string name = string_compose (_("%1 (%2..%3)"), route->name(),
Timecode::timecode_format_sampletime (
(*j).start,
rpos,
_session->nominal_sample_rate(),
100, false),
Timecode::timecode_format_sampletime (
(*j).start + (*j).length(),
(*j).end().samples(),
_session->nominal_sample_rate(),
100, false)
);

View File

@ -48,7 +48,8 @@ class LIBARDOUR_API AnalysisGraph {
void analyze_region (ARDOUR::AudioRegion const*, bool raw = false, ARDOUR::Progress* = 0);
void analyze_region (boost::shared_ptr<ARDOUR::AudioRegion>, bool raw = false);
void analyze_range (boost::shared_ptr<ARDOUR::Route>, boost::shared_ptr<ARDOUR::AudioPlaylist>, const std::list<AudioRange>&);
void analyze_range (boost::shared_ptr<ARDOUR::Route>, boost::shared_ptr<ARDOUR::AudioPlaylist>, const std::list<TimelineRange>&);
const AnalysisResults& results () const { return _results; }
void cancel () { _canceled = true; }

View File

@ -51,13 +51,13 @@ public:
int set_state (const XMLNode&, int version);
bool can_truncate_peaks() const { return false; }
bool can_be_analysed() const { return _length > 0; }
bool can_be_analysed() const { return _length.positive(); }
protected:
friend class SourceFactory;
AudioPlaylistSource (Session&, const PBD::ID& orig, const std::string& name, boost::shared_ptr<AudioPlaylist>, uint32_t chn,
sampleoffset_t begin, samplecnt_t len, Source::Flag flags);
timepos_t const & begin, timepos_t const & len, Source::Flag flags);
AudioPlaylistSource (Session&, const XMLNode&);

View File

@ -30,7 +30,7 @@
namespace ARDOUR {
class Readable;
class AudioReadable;
class Session;
class LIBARDOUR_API AudioAnalyser : public boost::noncopyable {
@ -44,7 +44,7 @@ class LIBARDOUR_API AudioAnalyser : public boost::noncopyable {
/* analysis object should provide a run method
that accepts a path to write the results to (optionally empty)
a Readable* to read data from
a AudioReadable* to read data from
and a reference to a type-specific container to return the
results.
*/
@ -60,7 +60,7 @@ class LIBARDOUR_API AudioAnalyser : public boost::noncopyable {
samplecnt_t stepsize;
int initialize_plugin (AnalysisPluginKey name, float sample_rate);
int analyse (const std::string& path, Readable*, uint32_t channel);
int analyse (const std::string& path, AudioReadable*, uint32_t channel);
/* instances of an analysis object will have this method called
whenever there are results to process. if out is non-null,

View File

@ -70,7 +70,7 @@ public:
int set_state (const XMLNode&, int version);
bool can_truncate_peaks() const { return true; }
bool can_be_analysed() const { return _length > 0; }
bool can_be_analysed() const { return _length.positive(); }
static bool safe_audio_file_extension (const std::string& path);

View File

@ -41,9 +41,9 @@ public:
AudioPlaylist (Session&, const XMLNode&, bool hidden = false);
AudioPlaylist (Session&, std::string name, bool hidden = false);
AudioPlaylist (boost::shared_ptr<const AudioPlaylist>, std::string name, bool hidden = false);
AudioPlaylist (boost::shared_ptr<const AudioPlaylist>, samplepos_t start, samplecnt_t cnt, std::string name, bool hidden = false);
AudioPlaylist (boost::shared_ptr<const AudioPlaylist>, timepos_t const & start, timepos_t const & cnt, std::string name, bool hidden = false);
samplecnt_t read (Sample *dst, Sample *mixdown, float *gain_buffer, samplepos_t start, samplecnt_t cnt, uint32_t chan_n=0);
timecnt_t read (Sample *dst, Sample *mixdown, float *gain_buffer, timepos_t const & start, timecnt_t const & cnt, uint32_t chan_n=0);
bool destroy_region (boost::shared_ptr<Region>);

View File

@ -62,7 +62,7 @@ class Filter;
class AudioSource;
class LIBARDOUR_API AudioRegion : public Region
class LIBARDOUR_API AudioRegion : public Region, public AudioReadable
{
public:
static void make_property_quarks ();
@ -104,26 +104,28 @@ class LIBARDOUR_API AudioRegion : public Region
boost::shared_ptr<AutomationList> inverse_fade_out() { return _inverse_fade_out.val (); }
boost::shared_ptr<AutomationList> envelope() { return _envelope.val (); }
Evoral::Range<samplepos_t> body_range () const;
Temporal::Range body_range () const;
virtual samplecnt_t read_peaks (PeakData *buf, samplecnt_t npeaks,
samplecnt_t offset, samplecnt_t cnt,
uint32_t chan_n=0, double samples_per_pixel = 1.0) const;
/* Readable interface */
/* AudioReadable interface */
virtual samplecnt_t read (Sample*, samplepos_t pos, samplecnt_t cnt, int channel) const;
samplecnt_t read (Sample*, samplepos_t pos, samplecnt_t cnt, int channel) const;
samplecnt_t readable_length_samples() const { return length_samples(); }
uint32_t n_channels() const { return _sources.size(); }
virtual samplecnt_t read_at (Sample *buf, Sample *mixdown_buf, float *gain_buf,
samplecnt_t read_at (Sample *buf, Sample *mixdown_buf, float *gain_buf,
samplepos_t position,
samplecnt_t cnt,
uint32_t chan_n = 0) const;
virtual samplecnt_t master_read_at (Sample *buf, Sample *mixdown_buf, float *gain_buf,
samplecnt_t master_read_at (Sample *buf, Sample *mixdown_buf, float *gain_buf,
samplepos_t position, samplecnt_t cnt,
uint32_t chan_n=0) const;
virtual samplecnt_t read_raw_internal (Sample*, samplepos_t, samplecnt_t, int channel) const;
samplecnt_t read_raw_internal (Sample*, samplepos_t, samplecnt_t, int channel) const;
XMLNode& state ();
XMLNode& get_basic_state ();
@ -245,7 +247,7 @@ class LIBARDOUR_API AudioRegion : public Region
protected:
/* default constructor for derived (compound) types */
AudioRegion (Session& s, samplepos_t, samplecnt_t, std::string name);
AudioRegion (Session& s, timecnt_t const &, timecnt_t const &, std::string name);
int _set_state (const XMLNode&, int version, PBD::PropertyChange& what_changed, bool send_signal);
};

View File

@ -27,7 +27,7 @@ namespace ARDOUR {
class Session;
class LIBARDOUR_API AudioRom : public Readable
class LIBARDOUR_API AudioRom : public AudioReadable
{
public:
static boost::shared_ptr<AudioRom> new_rom (Sample*, size_t);

View File

@ -41,20 +41,17 @@
namespace ARDOUR {
class LIBARDOUR_API AudioSource : virtual public Source,
public ARDOUR::Readable
class LIBARDOUR_API AudioSource : virtual public Source, public ARDOUR::AudioReadable
{
public:
AudioSource (Session&, const std::string& name);
AudioSource (Session&, const XMLNode&);
virtual ~AudioSource ();
samplecnt_t readable_length() const { return _length; }
samplecnt_t readable_length_samples() const { return _length.samples(); }
virtual uint32_t n_channels() const { return 1; }
virtual bool empty() const;
samplecnt_t length (samplepos_t pos) const;
void update_length (samplecnt_t cnt);
void update_length (timecnt_t const & cnt);
virtual samplecnt_t available_peaks (double zoom) const;
@ -107,7 +104,19 @@ class LIBARDOUR_API AudioSource : virtual public Source,
static bool _build_missing_peakfiles;
static bool _build_peakfiles;
samplecnt_t _length;
/* these collections of working buffers for supporting
playlist's reading from potentially nested/recursive
sources assume SINGLE THREADED reads by the butler
thread, or a lock around calls that use them.
*/
static std::vector<boost::shared_array<Sample> > _mixdown_buffers;
static std::vector<boost::shared_array<gain_t> > _gain_buffers;
static Glib::Threads::Mutex _level_buffer_lock;
static void ensure_buffers_for_level (uint32_t, samplecnt_t);
static void ensure_buffers_for_level_locked (uint32_t, samplecnt_t);
std::string _peakpath;
int initialize_peakfile (const std::string& path, const bool in_session = false);

View File

@ -102,7 +102,7 @@ private:
samplepos_t current_sample;
mutable GATOMIC_QUAL gint _auditioning;
Glib::Threads::Mutex lock;
samplecnt_t length;
timecnt_t length;
sampleoffset_t _seek_sample;
bool _seeking;
bool _seek_complete;
@ -120,7 +120,7 @@ private:
static void*_drop_ports (void*);
void actually_drop_ports ();
void output_changed (IOChange, void*);
sampleoffset_t _import_position;
timepos_t _import_position;
};
}; /* namespace ARDOUR */

View File

@ -85,7 +85,7 @@ public:
boost::shared_ptr<const AutomationControl> automation_control (const Evoral::Parameter& id) const;
virtual void add_control(boost::shared_ptr<Evoral::Control>);
virtual bool find_next_event (double start, double end, Evoral::ControlEvent& ev, bool only_active = true) const;
virtual bool find_next_event (Temporal::timepos_t const & start, Temporal::timepos_t const & end, Evoral::ControlEvent& ev, bool only_active = true) const;
void clear_controls ();
virtual void non_realtime_locate (samplepos_t now);
@ -131,9 +131,8 @@ protected:
SlavableControlList slavables () const { return SlavableControlList(); }
protected:
void find_next_ac_event (boost::shared_ptr<AutomationControl>, double start, double end, Evoral::ControlEvent& ev) const;
void find_prev_ac_event (boost::shared_ptr<AutomationControl>, double start, double end, Evoral::ControlEvent& ev) const;
void find_next_ac_event (boost::shared_ptr<AutomationControl>, Temporal::timepos_t const & start, Temporal::timepos_t const & end, Evoral::ControlEvent& ev) const;
void find_prev_ac_event (boost::shared_ptr<AutomationControl>, Temporal::timepos_t const & start, Temporal::timepos_t const & end, Evoral::ControlEvent& ev) const;
private:
PBD::ScopedConnectionList _control_connections; ///< connections to our controls' signals

View File

@ -85,8 +85,8 @@ public:
}
void set_automation_state(AutoState as);
void start_touch(double when);
void stop_touch(double when);
void start_touch(timepos_t const & when);
void stop_touch(timepos_t const & when);
/* inherited from PBD::Controllable. */
virtual double get_value () const;

View File

@ -73,20 +73,21 @@ private:
class LIBARDOUR_API AutomationList : public Evoral::ControlList, public PBD::StatefulDestructible
{
public:
AutomationList (const Evoral::Parameter& id, const Evoral::ParameterDescriptor& desc);
AutomationList (const Evoral::Parameter& id);
AutomationList (const Evoral::Parameter& id, const Evoral::ParameterDescriptor& desc, Temporal::TimeDomain);
AutomationList (const Evoral::Parameter& id, Temporal::TimeDomain);
AutomationList (const XMLNode&, Evoral::Parameter id);
AutomationList (const AutomationList&);
AutomationList (const AutomationList&, double start, double end);
AutomationList (const AutomationList&, timepos_t const & start, timepos_t const & end);
~AutomationList();
virtual boost::shared_ptr<ControlList> create(const Evoral::Parameter& id,
const Evoral::ParameterDescriptor& desc);
const Evoral::ParameterDescriptor& desc,
Temporal::TimeDomain);
AutomationList& operator= (const AutomationList&);
void thaw ();
bool paste (const ControlList&, double, BeatsSamplesConverter const&);
bool paste (const ControlList&, timepos_t const &, BeatsSamplesConverter const&);
void set_automation_state (AutoState);
AutoState automation_state() const;
@ -103,11 +104,11 @@ public:
static PBD::Signal1<void,AutomationList*> AutomationListCreated;
void start_write_pass (double when);
void write_pass_finished (double when, double thinning_factor=0.0);
void start_write_pass (timepos_t const & when);
void write_pass_finished (timepos_t const & when, double thinning_factor=0.0);
void start_touch (double when);
void stop_touch (double when);
void start_touch (timepos_t const & when);
void stop_touch (timepos_t const & when);
bool touching () const { return g_atomic_int_get (&_touching) != 0; }
bool writing () const { return _state == Write; }

View File

@ -16,10 +16,10 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <cstdlib>
#include "temporal/beats.h"
#include "evoral/TimeConverter.h"
#include "temporal/superclock.h"
#include "temporal/time_converter.h"
#include "temporal/types.h"
#include "ardour/libardour_visibility.h"
#include "ardour/types.h"
@ -27,49 +27,31 @@
#ifndef __ardour_beats_samples_converter_h__
#define __ardour_beats_samples_converter_h__
namespace Temporal {
class TempoMap;
}
namespace ARDOUR {
class TempoMap;
/** Converter between quarter-note beats and samples. Takes distances in quarter-note beats or samples
* from some origin (supplied to the constructor in samples), and converts
* them to the opposite unit, taking tempo changes into account.
/** Converter between quarter-note beats and samplepos_t. Takes distances in
* quarter-note beats or samplepos_t from some origin (supplied to the
* constructor in samplepos_t), and converts them to the opposite unit,
* taking tempo changes into account.
*/
class LIBARDOUR_API BeatsSamplesConverter
: public Evoral::TimeConverter<Temporal::Beats,samplepos_t> {
class LIBARDOUR_API BeatsSamplesConverter : public Temporal::TimeConverter<Temporal::Beats,samplepos_t,samplecnt_t> {
public:
BeatsSamplesConverter (const TempoMap& tempo_map, samplepos_t origin)
: Evoral::TimeConverter<Temporal::Beats, samplepos_t> (origin)
, _tempo_map(tempo_map)
BeatsSamplesConverter (const Temporal::TempoMap& tempo_map, Temporal::samplepos_t origin)
: Temporal::TimeConverter<Temporal::Beats, samplepos_t, samplecnt_t> (origin)
, _tempo_map (tempo_map)
{}
samplepos_t to (Temporal::Beats beats) const;
Temporal::Beats from (samplepos_t samples) const;
samplecnt_t to (Temporal::Beats beats) const;
Temporal::Beats from (samplecnt_t distance) const;
private:
const TempoMap& _tempo_map;
const Temporal::TempoMap& _tempo_map;
};
/** Converter between quarter-note beats and samples. Takes distances in quarter-note beats or samples
* from some origin (supplied to the constructor in samples), and converts
* them to the opposite unit, taking tempo changes into account.
*/
class LIBARDOUR_API DoubleBeatsSamplesConverter
: public Evoral::TimeConverter<double,samplepos_t> {
public:
DoubleBeatsSamplesConverter (const TempoMap& tempo_map, samplepos_t origin)
: Evoral::TimeConverter<double, samplepos_t> (origin)
, _tempo_map(tempo_map)
{}
samplepos_t to (double beats) const;
double from (samplepos_t samples) const;
private:
const TempoMap& _tempo_map;
};
} /* namespace ARDOUR */
#endif /* __ardour_beats_samples_converter_h__ */

View File

@ -39,7 +39,7 @@ public:
bool add_impdata (
uint32_t c_in,
uint32_t c_out,
boost::shared_ptr<Readable> r,
boost::shared_ptr<AudioReadable> r,
float gain = 1.0,
uint32_t pre_delay = 0,
sampleoffset_t offset = 0,
@ -64,10 +64,10 @@ protected:
bool _threaded;
private:
class ImpData : public Readable
class ImpData : public AudioReadable
{
public:
ImpData (uint32_t ci, uint32_t co, boost::shared_ptr<Readable> r, float g, float d, sampleoffset_t s = 0, samplecnt_t l = 0, uint32_t c = 0)
ImpData (uint32_t ci, uint32_t co, boost::shared_ptr<AudioReadable> r, float g, float d, sampleoffset_t s = 0, samplecnt_t l = 0, uint32_t c = 0)
: c_in (ci)
, c_out (co)
, gain (g)
@ -87,8 +87,8 @@ private:
return _readable->read (s, pos + _offset, cnt, _channel);
}
samplecnt_t readable_length () const {
samplecnt_t rl = _readable->readable_length ();
samplecnt_t readable_length_samples () const {
samplecnt_t rl = _readable->readable_length_samples ();
if (rl < _offset) {
return 0;
} else if (_length > 0) {
@ -103,7 +103,7 @@ private:
}
private:
boost::shared_ptr<Readable> _readable;
boost::shared_ptr<AudioReadable> _readable;
sampleoffset_t _offset;
samplecnt_t _length;
@ -172,7 +172,7 @@ public:
void run_stereo_no_latency (float* L, float* R, uint32_t);
private:
std::vector<boost::shared_ptr<Readable> > _readables;
std::vector<boost::shared_ptr<AudioReadable> > _readables;
IRChannelConfig _irc;
IRSettings _ir_settings;

View File

@ -181,13 +181,13 @@ protected:
virtual void playlist_changed (const PBD::PropertyChange&) {}
virtual void playlist_deleted (boost::weak_ptr<Playlist>);
virtual void playlist_ranges_moved (std::list< Evoral::RangeMove<samplepos_t> > const &, bool) {}
virtual void playlist_ranges_moved (std::list<Temporal::RangeMove> const &, bool) {}
/* The MIDI stuff */
MidiRingBuffer<samplepos_t>* _midi_buf;
static void get_location_times (const Location* location, samplepos_t* start, samplepos_t* end, samplepos_t* length);
static void get_location_times (const Location* location, timepos_t* start, timepos_t* end, timecnt_t* length);
};
} // namespace ARDOUR

View File

@ -73,7 +73,7 @@ public:
float buffer_load () const;
void move_processor_automation (boost::weak_ptr<Processor>, std::list<Evoral::RangeMove<samplepos_t> > const&);
void move_processor_automation (boost::weak_ptr<Processor>, std::list<Temporal::RangeMove> const&);
/* called by the Butler in a non-realtime context as part of its normal
* buffer refill loop (not due to transport-mechanism requests like
@ -151,7 +151,7 @@ protected:
void resolve_tracker (Evoral::EventSink<samplepos_t>& buffer, samplepos_t time);
int use_playlist (DataType, boost::shared_ptr<Playlist>);
void playlist_ranges_moved (std::list<Evoral::RangeMove<samplepos_t> > const&, bool);
void playlist_ranges_moved (std::list<Temporal::RangeMove> const&, bool);
int add_channel_to (boost::shared_ptr<ChannelList>, uint32_t how_many);

View File

@ -157,7 +157,7 @@ private:
bool prep_record_enable ();
bool prep_record_disable ();
void calculate_record_range (Evoral::OverlapType ot, samplepos_t transport_sample,
void calculate_record_range (Temporal::OverlapType ot, samplepos_t transport_sample,
samplecnt_t nframes, samplecnt_t& rec_nframes,
samplecnt_t& rec_offset);

View File

@ -33,7 +33,7 @@ public:
EBUr128Analysis (float sample_rate);
~EBUr128Analysis();
int run (Readable*);
int run (AudioReadable*);
float loudness () const { return _loudness; }
float loudness_range () const { return _loudness_range; }

View File

@ -125,8 +125,8 @@ class LIBARDOUR_API RegionExportChannelFactory
size_t n_channels;
BufferSet buffers;
bool buffers_up_to_date;
samplecnt_t region_start;
samplecnt_t position;
samplepos_t region_start;
samplepos_t position;
boost::scoped_array<Sample> mixdown_buffer;
boost::scoped_array<Sample> gain_buffer;

View File

@ -65,7 +65,7 @@ public:
};
Location (Session &);
Location (Session &, samplepos_t, samplepos_t, const std::string &, Flags bits = Flags(0), const uint32_t sub_num = 0);
Location (Session &, Temporal::timepos_t const &, Temporal::timepos_t const &, const std::string &, Flags bits = Flags(0));
Location (const Location& other);
Location (Session &, const XMLNode&);
Location* operator= (const Location& other);
@ -77,15 +77,19 @@ public:
void unlock ();
int64_t timestamp() const { return _timestamp; };
samplepos_t start() const { return _start; }
samplepos_t end() const { return _end; }
samplecnt_t length() const { return _end - _start; }
timepos_t start() const { return _start; }
timepos_t end() const { return _end; }
timecnt_t length() const { return _start.distance (_end); }
int set_start (samplepos_t s, bool force = false, bool allow_beat_recompute = true, const uint32_t sub_num = 0);
int set_end (samplepos_t e, bool force = false, bool allow_beat_recompute = true, const uint32_t sub_num = 0);
int set (samplepos_t start, samplepos_t end, bool allow_beat_recompute = true, const uint32_t sub_num = 0);
samplepos_t start_sample() const { return _start.samples(); }
samplepos_t end_sample() const { return _end.samples(); }
samplecnt_t length_samples() const { return _end.samples() - _start.samples(); }
int move_to (samplepos_t pos, const uint32_t sub_num);
int set_start (timepos_t const & s, bool force = false);
int set_end (timepos_t const & e, bool force = false);
int set (timepos_t const & start, timepos_t const & end);
int move_to (timepos_t const & pos);
const std::string& name() const { return _name; }
void set_name (const std::string &str);
@ -126,7 +130,7 @@ public:
static PBD::Signal1<void,Location*> start_changed;
static PBD::Signal1<void,Location*> flags_changed;
static PBD::Signal1<void,Location*> lock_changed;
static PBD::Signal1<void,Location*> position_lock_style_changed;
static PBD::Signal1<void,Location*> position_time_domain_changed;
/* this is sent only when both start and end change at the same time */
static PBD::Signal1<void,Location*> changed;
@ -142,7 +146,7 @@ public:
PBD::Signal0<void> StartChanged;
PBD::Signal0<void> FlagsChanged;
PBD::Signal0<void> LockChanged;
PBD::Signal0<void> PositionLockStyleChanged;
PBD::Signal0<void> TimeDomainChanged;
/* CD Track / CD-Text info */
@ -152,28 +156,23 @@ public:
XMLNode& get_state (void);
int set_state (const XMLNode&, int version);
PositionLockStyle position_lock_style() const { return _position_lock_style; }
void set_position_lock_style (PositionLockStyle ps);
void recompute_samples_from_beat ();
Temporal::TimeDomain position_time_domain() const { return _start.time_domain(); }
void set_position_time_domain (Temporal::TimeDomain ps);
static PBD::Signal0<void> scene_changed; /* for use by backend scene change management, class level */
PBD::Signal0<void> SceneChangeChanged; /* for use by objects interested in this object */
private:
std::string _name;
samplepos_t _start;
double _start_beat;
samplepos_t _end;
double _end_beat;
timepos_t _start;
timepos_t _end;
Flags _flags;
bool _locked;
PositionLockStyle _position_lock_style;
boost::shared_ptr<SceneChange> _scene_change;
int64_t _timestamp;
void set_mark (bool yn);
bool set_flag_internal (bool yn, Flags flag);
void recompute_beat_from_samples (const uint32_t sub_num);
};
/** A collection of session locations including unique dedicated locations (loop, punch, etc) */
@ -229,7 +228,7 @@ public:
samplepos_t first_mark_before (samplepos_t, bool include_special_ranges = false);
samplepos_t first_mark_after (samplepos_t, bool include_special_ranges = false);
void marks_either_side (samplepos_t const, samplepos_t &, samplepos_t &) const;
void marks_either_side (timepos_t const &, timepos_t &, timepos_t &) const;
/** Return range with closest start pos to the where argument
*
@ -239,9 +238,9 @@ public:
*
* @return Location object or nil
*/
Location* range_starts_at(samplepos_t pos, samplecnt_t slop = 0, bool incl = false) const;
Location* range_starts_at(samplepos_t, samplecnt_t slop = 0, bool incl = false) const;
void find_all_between (samplepos_t start, samplepos_t, LocationList&, Location::Flags);
void find_all_between (timepos_t const & start, timepos_t const & end, LocationList&, Location::Flags);
PBD::Signal1<void,Location*> current_changed;

View File

@ -36,7 +36,7 @@
#include "ardour/session.h"
namespace ARDOUR {
class Readable;
class AudioReadable;
}
namespace ARDOUR { namespace LuaAPI {
@ -269,7 +269,7 @@ namespace ARDOUR { namespace LuaAPI {
*
* This interface allows to load a plugins and directly access it using the Vamp Plugin API.
*
* A convenience method is provided to analyze Ardour::Readable objects (Regions).
* A convenience method is provided to analyze Ardour::AudioReadable objects (Regions).
*/
public:
Vamp (const std::string&, float sample_rate);
@ -282,7 +282,7 @@ namespace ARDOUR { namespace LuaAPI {
::Vamp::Plugin* plugin () { return _plugin; }
/** high-level abstraction to process a single channel of the given Readable.
/** high-level abstraction to process a single channel of the given AudioReadable.
*
* If the plugin is not yet initialized, initialize() is called.
*
@ -294,7 +294,7 @@ namespace ARDOUR { namespace LuaAPI {
* @param fn lua callback function or nil
* @return 0 on success
*/
int analyze (boost::shared_ptr<ARDOUR::Readable> r, uint32_t channel, luabridge::LuaRef fn);
int analyze (boost::shared_ptr<ARDOUR::AudioReadable> r, uint32_t channel, luabridge::LuaRef fn);
/** call plugin():reset() and clear intialization flag */
void reset ();
@ -341,7 +341,7 @@ namespace ARDOUR { namespace LuaAPI {
};
class Rubberband : public Readable , public boost::enable_shared_from_this<Rubberband>
class Rubberband : public AudioReadable , public boost::enable_shared_from_this<Rubberband>
{
public:
Rubberband (boost::shared_ptr<AudioRegion>, bool percussive);
@ -349,10 +349,10 @@ namespace ARDOUR { namespace LuaAPI {
bool set_strech_and_pitch (double stretch_ratio, double pitch_ratio);
bool set_mapping (luabridge::LuaRef tbl);
boost::shared_ptr<AudioRegion> process (luabridge::LuaRef cb);
boost::shared_ptr<Readable> readable ();
boost::shared_ptr<AudioReadable> readable ();
/* readable API */
samplecnt_t readable_length () const { return _read_len; }
/* audioreadable API */
samplecnt_t readable_length_samples () const { return _read_len; }
uint32_t n_channels () const { return _n_channels; }
samplecnt_t read (Sample*, samplepos_t pos, samplecnt_t cnt, int channel) const;

View File

@ -35,7 +35,7 @@
namespace ARDOUR {
struct MidiCursor : public boost::noncopyable {
MidiCursor() : last_read_end(0) {}
MidiCursor() {}
void connect(PBD::Signal1<void, bool>& invalidated) {
connections.drop_connections();
@ -50,7 +50,7 @@ struct MidiCursor : public boost::noncopyable {
Evoral::Sequence<Temporal::Beats>::const_iterator iter;
std::set<Evoral::Sequence<Temporal::Beats>::WeakNotePtr> active_notes;
samplepos_t last_read_end;
timepos_t last_read_end;
PBD::ScopedConnectionList connections;
};

View File

@ -300,7 +300,7 @@ public:
int set_state(const XMLNode&) { return 0; }
PBD::Signal0<void> ContentsChanged;
PBD::Signal1<void, double> ContentsShifted;
PBD::Signal1<void, Temporal::timecnt_t> ContentsShifted;
boost::shared_ptr<const MidiSource> midi_source ();
void set_midi_source (boost::shared_ptr<MidiSource>);

View File

@ -64,8 +64,8 @@ public:
/** This constructor does NOT notify others (session) */
MidiPlaylist (boost::shared_ptr<const MidiPlaylist> other,
samplepos_t start,
samplecnt_t cnt,
timepos_t const & start,
timepos_t const & cnt,
std::string name,
bool hidden = false);
@ -77,7 +77,8 @@ public:
int set_state (const XMLNode&, int version);
bool destroy_region (boost::shared_ptr<Region>);
void _split_region (boost::shared_ptr<Region>, const MusicSample& position, ThawList& thawlist);
void _split_region (boost::shared_ptr<Region>, timepos_t const & position, Thawlist& thawlist);
void set_note_mode (NoteMode m) { _note_mode = m; }

View File

@ -1,84 +0,0 @@
/*
* Copyright (C) 2011-2015 David Robillard <d@drobilla.net>
* Copyright (C) 2011-2017 Paul Davis <paul@linuxaudiosystems.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __ardour_midi_playlist_source_h__
#define __ardour_midi_playlist_source_h__
#include <string>
#include <boost/shared_ptr.hpp>
#include "ardour/ardour.h"
#include "ardour/midi_source.h"
#include "ardour/playlist_source.h"
namespace ARDOUR {
class MidiPlaylist;
class LIBARDOUR_API MidiPlaylistSource : public MidiSource, public PlaylistSource {
public:
virtual ~MidiPlaylistSource ();
bool empty() const;
samplecnt_t length (samplepos_t) const;
samplecnt_t read_unlocked (Sample *dst, samplepos_t start, samplecnt_t cnt) const;
samplecnt_t write_unlocked (Sample *src, samplecnt_t cnt);
XMLNode& get_state ();
int set_state (const XMLNode&, int version);
void append_event_beats(const Glib::Threads::Mutex::Lock& lock, const Evoral::Event<Temporal::Beats>& ev);
void append_event_samples(const Glib::Threads::Mutex::Lock& lock, const Evoral::Event<samplepos_t>& ev, samplepos_t source_start);
void load_model(const Glib::Threads::Mutex::Lock& lock, bool force_reload=false);
void destroy_model(const Glib::Threads::Mutex::Lock& lock);
protected:
friend class SourceFactory;
MidiPlaylistSource (Session&, const PBD::ID& orig, const std::string& name, boost::shared_ptr<MidiPlaylist>, uint32_t chn,
sampleoffset_t begin, samplecnt_t len, Source::Flag flags);
MidiPlaylistSource (Session&, const XMLNode&);
void flush_midi(const Lock& lock);
samplecnt_t read_unlocked (const Lock& lock,
Evoral::EventSink<samplepos_t>& dst,
samplepos_t position,
samplepos_t start,
samplecnt_t cnt,
Evoral::Range<samplepos_t>* loop_range,
MidiStateTracker* tracker,
MidiChannelFilter* filter) const;
samplecnt_t write_unlocked (const Lock& lock,
MidiRingBuffer<samplepos_t>& dst,
samplepos_t position,
samplecnt_t cnt);
private:
int set_state (const XMLNode&, int version, bool with_descendants);
samplecnt_t _length;
};
} /* namespace */
#endif /* __ardour_midi_playlist_source_h__ */

View File

@ -26,7 +26,7 @@
#include <vector>
#include "temporal/beats.h"
#include "evoral/Range.h"
#include "temporal/range.h"
#include "pbd/string_convert.h"
@ -68,26 +68,23 @@ class LIBARDOUR_API MidiRegion : public Region
boost::shared_ptr<MidiSource> midi_source (uint32_t n=0) const;
/* Stub Readable interface */
virtual samplecnt_t read (Sample*, samplepos_t /*pos*/, samplecnt_t /*cnt*/, int /*channel*/) const { return 0; }
timecnt_t read_at (Evoral::EventSink<samplepos_t>& dst,
timepos_t const & position,
timecnt_t const & dur,
Temporal::Range* loop_range,
MidiCursor& cursor,
uint32_t chan_n = 0,
NoteMode mode = Sustained,
MidiStateTracker* tracker = 0,
MidiChannelFilter* filter = 0) const;
samplecnt_t read_at (Evoral::EventSink<samplepos_t>& dst,
samplepos_t position,
samplecnt_t dur,
Evoral::Range<samplepos_t>* loop_range,
MidiCursor& cursor,
uint32_t chan_n = 0,
NoteMode mode = Sustained,
MidiStateTracker* tracker = 0,
MidiChannelFilter* filter = 0) const;
samplecnt_t master_read_at (MidiRingBuffer<samplepos_t>& dst,
samplepos_t position,
samplecnt_t dur,
Evoral::Range<samplepos_t>* loop_range,
MidiCursor& cursor,
uint32_t chan_n = 0,
NoteMode mode = Sustained) const;
timecnt_t master_read_at (MidiRingBuffer<samplepos_t>& dst,
timepos_t const & position,
timecnt_t const & dur,
Temporal::Range* loop_range,
MidiCursor& cursor,
uint32_t chan_n = 0,
NoteMode mode = Sustained) const;
XMLNode& state ();
int set_state (const XMLNode&, int version);
@ -127,38 +124,30 @@ class LIBARDOUR_API MidiRegion : public Region
MidiRegion (boost::shared_ptr<const MidiRegion>);
MidiRegion (boost::shared_ptr<const MidiRegion>, timecnt_t const & offset);
samplecnt_t _read_at (const SourceList&, Evoral::EventSink<samplepos_t>& dst,
samplepos_t position,
samplecnt_t dur,
Evoral::Range<samplepos_t>* loop_range,
MidiCursor& cursor,
uint32_t chan_n = 0,
NoteMode mode = Sustained,
MidiStateTracker* tracker = 0,
MidiChannelFilter* filter = 0) const;
timecnt_t _read_at (const SourceList&, Evoral::EventSink<samplepos_t>& dst,
timepos_t const & position,
timecnt_t const & dur,
Temporal::Range* loop_range,
MidiCursor& cursor,
uint32_t chan_n = 0,
NoteMode mode = Sustained,
MidiStateTracker* tracker = 0,
MidiChannelFilter* filter = 0) const;
void register_properties ();
void post_set (const PBD::PropertyChange&);
void recompute_at_start ();
void recompute_at_end ();
bool set_name (const std::string & str);
void set_position_internal (timepos_t const & pos);
void set_length_internal (timecnt_t const & len);
void set_start_internal (timecnt_t const &);
void trim_to_internal (timepos_t const & position, timecnt_t const & length);
void update_length_beats ();
void model_changed ();
void model_contents_changed ();
void model_shifted (double qn_distance);
void model_shifted (timecnt_t qn_distance);
void model_automation_state_changed (Evoral::Parameter const &);
void set_start_beats_from_start_samples ();
void update_after_tempo_map_change (bool send_change = true);
std::set<Evoral::Parameter> _filtered_parameters; ///< parameters that we ask our source not to return when reading
PBD::ScopedConnection _model_connection;
PBD::ScopedConnection _model_shift_connection;

View File

@ -27,10 +27,14 @@
#include <time.h>
#include <glibmm/threads.h>
#include <boost/enable_shared_from_this.hpp>
#include "pbd/stateful.h"
#include "pbd/xml++.h"
#include "evoral/Sequence.h"
#include "evoral/Range.h"
#include "temporal/range.h"
#include "ardour/ardour.h"
#include "ardour/buffer.h"
#include "ardour/midi_cursor.h"
@ -95,21 +99,17 @@ class LIBARDOUR_API MidiSource : virtual public Source
* @param filter Channel filter to apply or NULL to disable filter
* @param tracker an optional pointer to MidiStateTracker object, for note on/off tracking.
* @param filtered Parameters whose MIDI messages will not be returned.
* @param pos_beats Start position (quarter note = \p pos_beats - \p start_beats)
* @param start_beats Start position offset
*/
virtual samplecnt_t midi_read (const Lock& lock,
Evoral::EventSink<samplepos_t>& dst,
samplepos_t source_start,
samplepos_t start,
samplecnt_t cnt,
Evoral::Range<samplepos_t>* loop_range,
MidiCursor& cursor,
MidiStateTracker* tracker,
MidiChannelFilter* filter,
const std::set<Evoral::Parameter>& filtered,
const double pos_beats,
const double start_beats) const;
virtual timecnt_t midi_read (const Lock& lock,
Evoral::EventSink<samplepos_t>& dst,
timepos_t const & source_start,
timecnt_t const & start,
timecnt_t const & cnt,
Temporal::Range* loop_range,
MidiCursor& cursor,
MidiStateTracker* tracker,
MidiChannelFilter* filter,
const std::set<Evoral::Parameter>& filtered);
/** Write data from a MidiRingBuffer to this source.
* @param lock Reference to the Mutex to lock before modification
@ -117,10 +117,10 @@ class LIBARDOUR_API MidiSource : virtual public Source
* @param source_start This source's start position in session samples.
* @param cnt The length of time to write.
*/
virtual samplecnt_t midi_write (const Lock& lock,
MidiRingBuffer<samplepos_t>& source,
samplepos_t source_start,
samplecnt_t cnt);
virtual timecnt_t midi_write (const Lock& lock,
MidiRingBuffer<samplepos_t>& source,
timepos_t const & source_start,
timecnt_t const & cnt);
/** Append a single event with a timestamp in beats.
*
@ -137,10 +137,6 @@ class LIBARDOUR_API MidiSource : virtual public Source
const Evoral::Event<samplepos_t>& ev,
samplepos_t source_start) = 0;
virtual bool empty () const;
virtual samplecnt_t length (samplepos_t pos) const;
virtual void update_length (samplecnt_t);
virtual void mark_streaming_midi_write_started (const Lock& lock, NoteMode mode);
virtual void mark_streaming_write_started (const Lock& lock);
virtual void mark_streaming_write_completed (const Lock& lock);
@ -216,14 +212,14 @@ class LIBARDOUR_API MidiSource : virtual public Source
protected:
virtual void flush_midi(const Lock& lock) = 0;
virtual samplecnt_t read_unlocked (const Lock& lock,
Evoral::EventSink<samplepos_t>& dst,
samplepos_t position,
samplepos_t start,
samplecnt_t cnt,
Evoral::Range<samplepos_t>* loop_range,
MidiStateTracker* tracker,
MidiChannelFilter* filter) const = 0;
virtual timecnt_t read_unlocked (const Lock& lock,
Evoral::EventSink<samplepos_t>& dst,
timepos_t const & position,
timecnt_t const & start,
timecnt_t const & cnt,
Temporal::Range* loop_range,
MidiStateTracker* tracker,
MidiChannelFilter* filter) const = 0;
/** Write data to this source from a MidiRingBuffer.
* @param lock Reference to the Mutex to lock before modification
@ -231,10 +227,10 @@ class LIBARDOUR_API MidiSource : virtual public Source
* @param position This source's start position in session samples.
* @param cnt The duration of this block to write for.
*/
virtual samplecnt_t write_unlocked (const Lock& lock,
MidiRingBuffer<samplepos_t>& source,
samplepos_t position,
samplecnt_t cnt) = 0;
virtual timecnt_t write_unlocked (const Lock& lock,
MidiRingBuffer<samplepos_t>& source,
timepos_t const & position,
timecnt_t const & cnt) = 0;
boost::shared_ptr<MidiModel> _model;
bool _writing;

View File

@ -40,7 +40,7 @@ public:
void set_minioi (float);
void set_function (int);
int run (const std::string& path, Readable*, uint32_t channel, AnalysisFeatureList& results);
int run (const std::string& path, AudioReadable*, uint32_t channel, AnalysisFeatureList& results);
static void cleanup_onsets (AnalysisFeatureList&, float sr, float gap_msecs);

View File

@ -37,11 +37,12 @@ class Pannable;
class LIBARDOUR_API PanControllable : public AutomationControl
{
public:
#warning NUTEMPO QUESTION what time domain shoudl this really use?
PanControllable (Session& s, std::string name, Pannable* o, Evoral::Parameter param)
: AutomationControl (s,
param,
ParameterDescriptor(param),
boost::shared_ptr<AutomationList>(new AutomationList(param)),
boost::shared_ptr<AutomationList>(new AutomationList(param, Temporal::AudioTime)),
name)
, owner (o)
{}

View File

@ -64,9 +64,11 @@ public:
return ((_auto_state & Write) || ((_auto_state & (Touch | Latch)) && touching()));
}
void start_touch (double when);
void stop_touch (double when);
void start_touch (timepos_t const & when);
void stop_touch (timepos_t const & when);
bool touching() const { return g_atomic_int_get (&_touching); }
bool writing() const { return _auto_state == Write; }
bool touch_enabled() const { return _auto_state & (Touch | Latch); }

View File

@ -46,7 +46,7 @@
#include "pbd/undo.h"
#include "pbd/g_atomic_compat.h"
#include "evoral/Range.h"
#include "temporal/range.h"
#include "ardour/ardour.h"
#include "ardour/data_type.h"
@ -95,7 +95,7 @@ public:
Playlist (Session&, const XMLNode&, DataType type, bool hidden = false);
Playlist (Session&, std::string name, DataType type, bool hidden = false);
Playlist (boost::shared_ptr<const Playlist>, std::string name, bool hidden = false);
Playlist (boost::shared_ptr<const Playlist>, samplepos_t start, samplecnt_t cnt, std::string name, bool hidden = false);
Playlist (boost::shared_ptr<const Playlist>, timepos_t const & start, timepos_t const & cnt, std::string name, bool hidden = false);
virtual ~Playlist ();
@ -159,51 +159,54 @@ public:
bool shared_with (const PBD::ID&) const;
void reset_shares ();
uint32_t n_regions () const;
bool all_regions_empty () const;
std::pair<samplepos_t, samplepos_t> get_extent () const;
std::pair<samplepos_t, samplepos_t> get_extent_with_endspace () const;
layer_t top_layer () const;
uint32_t n_regions() const;
bool all_regions_empty() const;
std::pair<timepos_t, timepos_t> get_extent () const;
std::pair<timepos_t, timepos_t> get_extent_with_endspace() const;
layer_t top_layer() const;
EditMode get_edit_mode() const { return _edit_mode; }
void set_edit_mode (EditMode);
/* Editing operations */
void add_region (boost::shared_ptr<Region>, samplepos_t position, float times = 1, bool auto_partition = false, int32_t sub_num = 0, double quarter_note = 0.0, bool for_music = false);
void add_region (boost::shared_ptr<Region>, timepos_t const & position, float times = 1, bool auto_partition = false);
void remove_region (boost::shared_ptr<Region>);
void get_equivalent_regions (boost::shared_ptr<Region>, std::vector<boost::shared_ptr<Region> >&);
void replace_region (boost::shared_ptr<Region> old, boost::shared_ptr<Region> newr, samplepos_t pos);
void split_region (boost::shared_ptr<Region>, const MusicSample& position);
void split (const MusicSample& at);
void shift (samplepos_t at, sampleoffset_t distance, bool move_intersected, bool ignore_music_glue);
void partition (samplepos_t start, samplepos_t end, bool cut = false);
void duplicate (boost::shared_ptr<Region>, samplepos_t position, float times);
void duplicate (boost::shared_ptr<Region>, samplepos_t position, samplecnt_t gap, float times);
void duplicate_until (boost::shared_ptr<Region>, samplepos_t position, samplecnt_t gap, samplepos_t end);
void duplicate_range (AudioRange&, float times);
void duplicate_ranges (std::list<AudioRange>&, float times);
void nudge_after (samplepos_t start, samplecnt_t distance, bool forwards);
void fade_range (std::list<AudioRange>&);
void remove_gaps (samplepos_t gap_threshold, samplepos_t leave_gap, boost::function<void (samplepos_t, samplecnt_t)> gap_callback);
void get_region_list_equivalent_regions (boost::shared_ptr<Region>, std::vector<boost::shared_ptr<Region> >&);
void get_source_equivalent_regions (boost::shared_ptr<Region>, std::vector<boost::shared_ptr<Region> >&);
void replace_region (boost::shared_ptr<Region> old, boost::shared_ptr<Region> newr, timepos_t const & pos);
void split_region (boost::shared_ptr<Region>, timepos_t const & position);
void split (timepos_t const & at);
void shift (timepos_t const & at, timecnt_t const & distance, bool move_intersected, bool ignore_music_glue);
void partition (timepos_t const & start, timepos_t const & end, bool cut = false);
void duplicate (boost::shared_ptr<Region>, timepos_t & position, float times);
void duplicate (boost::shared_ptr<Region>, timepos_t & position, timecnt_t const & gap, float times);
void duplicate_until (boost::shared_ptr<Region>, timepos_t & position, timecnt_t const & gap, timepos_t const & end);
void duplicate_range (TimelineRange&, float times);
void duplicate_ranges (std::list<TimelineRange>&, float times);
void nudge_after (timepos_t const & start, timecnt_t const & distance, bool forwards);
boost::shared_ptr<Region> combine (const RegionList&);
void uncombine (boost::shared_ptr<Region>);
void uncombine (boost::shared_ptr<Region>);
void fade_range (std::list<TimelineRange>&);
void shuffle (boost::shared_ptr<Region>, int dir);
void ripple (samplepos_t at, samplecnt_t distance, RegionList* exclude);
void ripple (samplepos_t at, samplecnt_t distance, boost::shared_ptr<Region> exclude)
{
RegionList el;
if (exclude) {
el.push_back (exclude);
}
ripple (at, distance, &el);
void ripple (timepos_t const & at, timecnt_t const & distance, RegionList *exclude);
void ripple (timepos_t const & at, timecnt_t const & distance, boost::shared_ptr<Region> exclude) {
RegionList el;
if (exclude) {
el.push_back (exclude);
}
ripple (at, distance, &el);
}
void update_after_tempo_map_change ();
boost::shared_ptr<Playlist> cut (std::list<AudioRange>&, bool result_is_hidden = true);
boost::shared_ptr<Playlist> copy (std::list<AudioRange>&, bool result_is_hidden = true);
int paste (boost::shared_ptr<Playlist>, samplepos_t position, float times, const int32_t sub_num);
boost::shared_ptr<Playlist> cut (std::list<TimelineRange>&, bool result_is_hidden = true);
boost::shared_ptr<Playlist> copy (std::list<TimelineRange>&, bool result_is_hidden = true);
int paste (boost::shared_ptr<Playlist>, timepos_t const & position, float times);
const RegionListProperty& region_list_property () const
{
@ -212,31 +215,31 @@ public:
boost::shared_ptr<RegionList> region_list ();
boost::shared_ptr<RegionList> regions_at (samplepos_t sample);
uint32_t count_regions_at (samplepos_t) const;
boost::shared_ptr<RegionList> regions_at (timepos_t const & sample);
uint32_t count_regions_at (timepos_t const &) const;
/** @param start Range start.
* @param end Range end.
* @return regions which have some part within this range.
*/
boost::shared_ptr<RegionList> regions_touched (samplepos_t start, samplepos_t end);
boost::shared_ptr<RegionList> regions_with_start_within (Evoral::Range<samplepos_t>);
boost::shared_ptr<RegionList> regions_with_end_within (Evoral::Range<samplepos_t>);
uint32_t region_use_count (boost::shared_ptr<Region>) const;
boost::shared_ptr<Region> find_region (const PBD::ID&) const;
boost::shared_ptr<Region> top_region_at (samplepos_t sample);
boost::shared_ptr<Region> top_unmuted_region_at (samplepos_t sample);
boost::shared_ptr<Region> find_next_region (samplepos_t sample, RegionPoint point, int dir);
samplepos_t find_next_region_boundary (samplepos_t sample, int dir);
bool region_is_shuffle_constrained (boost::shared_ptr<Region>);
bool has_region_at (samplepos_t const) const;
boost::shared_ptr<RegionList> regions_touched (timepos_t const & start, timepos_t const & end);
boost::shared_ptr<RegionList> regions_with_start_within (Temporal::TimeRange);
boost::shared_ptr<RegionList> regions_with_end_within (Temporal::TimeRange);
uint32_t region_use_count (boost::shared_ptr<Region>) const;
boost::shared_ptr<Region> find_region (const PBD::ID&) const;
boost::shared_ptr<Region> top_region_at (timepos_t const &);
boost::shared_ptr<Region> top_unmuted_region_at (timepos_t const &);
boost::shared_ptr<Region> find_next_region (timepos_t const &, RegionPoint point, int dir);
timepos_t find_next_region_boundary (timepos_t const &, int dir);
bool region_is_shuffle_constrained (boost::shared_ptr<Region>);
bool has_region_at (timepos_t const &) const;
samplepos_t find_prev_region_start (samplepos_t sample);
bool uses_source (boost::shared_ptr<const Source> src, bool shallow = false) const;
void deep_sources (std::set<boost::shared_ptr<Source> >&) const;
samplepos_t find_next_transient (samplepos_t position, int dir);
samplepos_t find_next_transient (timepos_t const & position, int dir);
void foreach_region (boost::function<void(boost::shared_ptr<Region>)>);
@ -252,12 +255,12 @@ public:
PBD::Signal0<void> LayeringChanged;
/** Emitted when regions have moved (not when regions have only been trimmed) */
PBD::Signal2<void, std::list<Evoral::RangeMove<samplepos_t> > const&, bool> RangesMoved;
PBD::Signal2<void,std::list< Temporal::RangeMove> const &, bool> RangesMoved;
/** Emitted when regions are extended; the ranges passed are the new extra time ranges
that these regions now occupy.
*/
PBD::Signal1<void, std::list<Evoral::Range<samplepos_t> > const&> RegionsExtended;
PBD::Signal1<void,std::list< Temporal::Range> const &> RegionsExtended;
static std::string bump_name (std::string old_name, Session&);
@ -289,11 +292,8 @@ public:
return boost::shared_ptr<Crossfade> ();
}
samplepos_t find_next_top_layer_position (samplepos_t) const;
uint32_t combine_ops () const
{
return _combine_ops;
}
timepos_t find_next_top_layer_position (timepos_t const &) const;
uint32_t combine_ops() const { return _combine_ops; }
void set_layer (boost::shared_ptr<Region>, double);
@ -373,6 +373,7 @@ protected:
* region trims are not included in this list; it is used to
* do automation-follows-regions.
*/
std::list<Evoral::RangeMove<samplepos_t> > pending_range_moves;
/** Extra sections added to regions during trims */
@ -393,6 +394,7 @@ protected:
uint32_t subcnt;
PBD::ID _orig_track_id;
uint32_t _combine_ops;
std::list<PBD::ID> _shared_with_ids;
void init (bool hide);
@ -410,7 +412,7 @@ protected:
void _set_sort_id ();
boost::shared_ptr<RegionList> regions_touched_locked (samplepos_t start, samplepos_t end);
boost::shared_ptr<RegionList> regions_touched_locked (timepos_t const & start, timepos_t const & end);
void notify_region_removed (boost::shared_ptr<Region>);
void notify_region_added (boost::shared_ptr<Region>);
@ -431,34 +433,34 @@ protected:
void sort_regions ();
void ripple_locked (samplepos_t at, samplecnt_t distance, RegionList* exclude);
bool ripple_unlocked (samplepos_t at, samplecnt_t distance, RegionList* exclude, ThawList& thawlist);
void ripple_locked (timepos_t const & at, timecnt_t const & distance, RegionList *exclude);
void ripple_unlocked (timepos_t const & at, timecnt_t const & distance, RegionList *exclude, Thawlist& thawlist);
virtual void remove_dependents (boost::shared_ptr<Region> /*region*/) {}
virtual void region_going_away (boost::weak_ptr<Region> /*region*/) {}
virtual XMLNode& state (bool);
bool add_region_internal (boost::shared_ptr<Region>, samplepos_t position, ThawList& thawlist, int32_t sub_num = 0, double quarter_note = 0.0, bool for_music = false);
bool add_region_internal (boost::shared_ptr<Region>, timepos_t const & position, Thawlist& thawlist);
int remove_region_internal (boost::shared_ptr<Region>, ThawList& thawlist);
void copy_regions (RegionList&) const;
void partition_internal (samplepos_t start, samplepos_t end, bool cutting, ThawList& thawlist);
std::pair<samplepos_t, samplepos_t> _get_extent () const;
void partition_internal (timepos_t const & start, timepos_t const & end, bool cutting, ThawList& thawlist);
boost::shared_ptr<Playlist> cut_copy (boost::shared_ptr<Playlist> (Playlist::*pmf) (samplepos_t, samplecnt_t, bool),
std::list<AudioRange>& ranges, bool result_is_hidden);
boost::shared_ptr<Playlist> cut (samplepos_t start, samplecnt_t cnt, bool result_is_hidden);
boost::shared_ptr<Playlist> copy (samplepos_t start, samplecnt_t cnt, bool result_is_hidden);
std::pair<timepos_t, timepos_t> _get_extent() const;
boost::shared_ptr<Playlist> cut_copy (boost::shared_ptr<Playlist> (Playlist::*pmf)(timepos_t const &, timecnt_t const &, bool),
std::list<TimelineRange>& ranges, bool result_is_hidden);
boost::shared_ptr<Playlist> cut (timepos_t const & start, timecnt_t const & cnt, bool result_is_hidden);
boost::shared_ptr<Playlist> copy (timepos_t const & start, timecnt_t const & cnt, bool result_is_hidden);
void relayer ();
void begin_undo ();
void end_undo ();
virtual void _split_region (boost::shared_ptr<Region>, const MusicSample& position, ThawList& thawlist);
virtual void _split_region (boost::shared_ptr<Region>, timepos_t const & position, Thawlist& thawlist);
typedef std::pair<boost::shared_ptr<Region>, boost::shared_ptr<Region> > TwoRegions;
@ -479,15 +481,13 @@ private:
private:
void freeze_locked ();
void setup_layering_indices (RegionList const&);
void coalesce_and_check_crossfades (std::list<Evoral::Range<samplepos_t> >);
void setup_layering_indices (RegionList const &);
void coalesce_and_check_crossfades (std::list<Temporal::TimeRange>);
boost::shared_ptr<RegionList> find_regions_at (timepos_t const &);
boost::shared_ptr<RegionList> find_regions_at (samplepos_t);
mutable boost::optional<std::pair<samplepos_t, samplepos_t> > _cached_extent;
samplepos_t _end_space; // this is used when we are pasting a range with extra space at the end
bool _playlist_shift_active;
mutable boost::optional<std::pair<timepos_t, timepos_t> > _cached_extent;
timepos_t _end_space; //this is used when we are pasting a range with extra space at the end
bool _playlist_shift_active;
std::string _pgroup_id; // when we make multiple playlists in one action, they will share the same pgroup_id
};
@ -495,3 +495,4 @@ private:
} /* namespace ARDOUR */
#endif /* __ardour_playlist_h__ */

View File

@ -37,7 +37,7 @@ class LIBARDOUR_API PlaylistFactory {
static boost::shared_ptr<Playlist> create (Session&, const XMLNode&, bool hidden = false, bool unused = false);
static boost::shared_ptr<Playlist> create (DataType type, Session&, std::string name, bool hidden = false);
static boost::shared_ptr<Playlist> create (boost::shared_ptr<const Playlist>, std::string name, bool hidden = false);
static boost::shared_ptr<Playlist> create (boost::shared_ptr<const Playlist>, samplepos_t start, samplecnt_t cnt, std::string name, bool hidden = false);
static boost::shared_ptr<Playlist> create (boost::shared_ptr<const Playlist>, timepos_t const & start, timepos_t const & cnt, std::string name, bool hidden = false);
};
}

View File

@ -45,11 +45,11 @@ protected:
boost::shared_ptr<Playlist> _playlist;
PBD::ID _original;
PBD::ID _owner;
sampleoffset_t _playlist_offset;
samplecnt_t _playlist_length;
timepos_t _playlist_offset;
timepos_t _playlist_length;
PlaylistSource (Session&, const PBD::ID&, const std::string& name, boost::shared_ptr<Playlist>, DataType,
sampleoffset_t begin, samplecnt_t len, Source::Flag flags);
timepos_t const & begin, timepos_t const & len, Source::Flag flags);
PlaylistSource (Session&, const XMLNode&);
void add_state (XMLNode&);

View File

@ -88,7 +88,7 @@ public:
bool write_immediate_event (Evoral::EventType event_type, size_t size, const uint8_t* buf);
void automation_run (samplepos_t, pframes_t, bool only_active = false);
bool find_next_event (double, double, Evoral::ControlEvent&, bool only_active = true) const;
bool find_next_event (Temporal::timepos_t const &, Temporal::timepos_t const &, Evoral::ControlEvent&, bool only_active = true) const;
int set_block_size (pframes_t nframes);

View File

@ -29,7 +29,7 @@ namespace ARDOUR {
class LIBARDOUR_API Quantize : public MidiOperator {
public:
Quantize (bool snap_start, bool snap_end,
double start_grid, double end_grid,
int start_grid, int end_grid,
float strength, float swing, Temporal::Beats const & threshold);
~Quantize ();
@ -41,8 +41,8 @@ public:
private:
bool _snap_start;
bool _snap_end;
double _start_grid;
double _end_grid;
int _start_grid;
int _end_grid;
float _strength;
float _swing;
Temporal::Beats _threshold;

View File

@ -27,11 +27,11 @@ namespace ARDOUR {
class Session;
class LIBARDOUR_API Readable {
class LIBARDOUR_API AudioReadable {
public:
virtual ~Readable() {}
virtual ~AudioReadable() {}
static std::vector<boost::shared_ptr<Readable> >
static std::vector<boost::shared_ptr<AudioReadable> >
load (Session&, std::string const&);
virtual samplecnt_t read (Sample*, samplepos_t pos, samplecnt_t cnt, int channel) const = 0;

View File

@ -71,7 +71,6 @@ namespace Properties {
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;
LIBARDOUR_API extern PBD::PropertyDescriptor<uint64_t> layering_index;
LIBARDOUR_API extern PBD::PropertyDescriptor<std::string> tags;
LIBARDOUR_API extern PBD::PropertyDescriptor<bool> contents; // type doesn't matter here
@ -92,7 +91,6 @@ enum LIBARDOUR_API RegionEditState {
class LIBARDOUR_API Region
: public SessionObject
, public boost::enable_shared_from_this<Region>
, public Readable
, public Trimmable
, public Movable
{
@ -123,6 +121,7 @@ public:
timecnt_t nt_start () const { return _start.val(); }
timecnt_t nt_length () const { return _length.val(); }
timepos_t nt_end() const;
timepos_t nt_last() const { return nt_end().decrement(); }
timepos_t source_position () const;
timepos_t source_relative_position (Temporal::timepos_t const &) const;
@ -132,8 +131,6 @@ public:
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);
@ -180,7 +177,11 @@ public:
}
Temporal::TimeRange range_samples () const {
return Temporal::TimeRange (timepos_t::from_samples (first_sample()), timepos_t::from_samples (first_sample() + length_samples()));
return Temporal::TimeRange (timepos_t (first_sample()), timepos_t (first_sample() + length_samples()));
}
Temporal::TimeRange range () const {
return Temporal::TimeRange (nt_position(), nt_position() + nt_length());
}
bool hidden () const { return _hidden; }
@ -199,9 +200,9 @@ public:
Trimmable::CanTrim can_trim () const;
PositionLockStyle position_lock_style () const { return _position_lock_style; }
void set_position_lock_style (PositionLockStyle ps);
void recompute_position_from_lock_style ();
Temporal::TimeDomain position_time_domain () const;
void set_position_time_domain (Temporal::TimeDomain ps);
void recompute_position_from_time_domain ();
void suspend_property_changes ();
@ -209,14 +210,18 @@ public:
return first_sample() <= sample && sample <= last_sample();
}
bool covers (timepos_t const & pos) const {
return nt_position() <= pos && pos <= nt_last();
}
/** @return coverage of this region with the given range;
* OverlapInternal: the range is internal to this region.
* OverlapStart: the range overlaps the start of this region.
* OverlapEnd: the range overlaps the end of this region.
* OverlapExternal: the range overlaps all of this region.
*/
Evoral::OverlapType coverage (samplepos_t start, samplepos_t end) const {
return Evoral::coverage (first_sample(), last_sample(), start, end);
Temporal::OverlapType coverage (timepos_t const & start, timepos_t const & end) const {
return Temporal::coverage_exclusive_ends (_position.val(), nt_last(), start, end);
}
bool exact_equivalent (boost::shared_ptr<const Region>) const;
@ -283,7 +288,6 @@ public:
bool is_compound () const;
boost::shared_ptr<Source> source (uint32_t n=0) const { return _sources[ (n < _sources.size()) ? n : 0 ]; }
uint32_t n_channels() const { return _sources.size(); }
SourceList& sources_for_edit () { return _sources; }
const SourceList& sources () const { return _sources; }
@ -415,7 +419,6 @@ 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 (timepos_t const & pos);
virtual void set_length_internal (timecnt_t const &);
virtual void set_start_internal (timecnt_t const &);
@ -458,7 +461,7 @@ protected:
private:
void mid_thaw (const PBD::PropertyChange&);
virtual void trim_to_internal (timepos_t const & position, timecnt_t const & length);
void trim_to_internal (timepos_t const & position, timecnt_t const & length);
void modify_front (timepos_t const & new_position, bool reset_fade);
void modify_end (timepos_t const & new_position, bool reset_fade);
@ -485,7 +488,6 @@ private:
PBD::Property<timecnt_t> _ancestral_length;
PBD::Property<float> _stretch;
PBD::Property<float> _shift;
PBD::EnumProperty<PositionLockStyle> _position_lock_style;
PBD::Property<uint64_t> _layering_index;
PBD::Property<std::string> _tags;
PBD::Property<bool> _contents; // type is irrelevant

View File

@ -165,7 +165,7 @@ public:
/* end of vfunc-based API */
void shift (samplepos_t, samplecnt_t);
void shift (timepos_t const &, timecnt_t const &);
/* controls use set_solo() to modify this route's solo state */

View File

@ -66,7 +66,7 @@
#include "lua/luastate.h"
#include "evoral/Range.h"
#include "temporal/range.h"
#include "midi++/types.h"
#include "midi++/mmc.h"
@ -336,7 +336,7 @@ public:
StripableList get_stripables () const;
boost::shared_ptr<RouteList> get_tracks() const;
boost::shared_ptr<RouteList> get_routes_with_internal_returns() const;
boost::shared_ptr<RouteList> get_routes_with_regions_at (samplepos_t const) const;
boost::shared_ptr<RouteList> get_routes_with_regions_at (timepos_t const &) const;
boost::shared_ptr<AudioTrack> get_nth_audio_track (uint32_t) const;
@ -528,7 +528,7 @@ public:
void set_auto_punch_location (Location *);
void set_auto_loop_location (Location *);
void set_session_extents (samplepos_t start, samplepos_t end);
void set_session_extents (timepos_t const & start, timepos_t const & end);
bool session_range_is_free () const { return _session_range_is_free; }
void set_session_range_is_free (bool);
@ -1122,11 +1122,11 @@ public:
/* ranges */
void request_play_range (std::list<AudioRange>*, bool leave_rolling = false);
void request_play_range (std::list<TimelineRange>*, bool leave_rolling = false);
void request_cancel_play_range ();
bool get_play_range () const { return _play_range; }
void maybe_update_session_range (samplepos_t, samplepos_t);
void maybe_update_session_range (timepos_t const &, timepos_t const &);
/* preroll */
samplecnt_t preroll_samples (samplepos_t) const;
@ -1311,7 +1311,7 @@ public:
void import_pt_sources (PTFFormat& ptf, ImportStatus& status);
void import_pt_rest (PTFFormat& ptf);
bool import_sndfile_as_region (std::string path, SrcQuality quality, samplepos_t& pos, SourceList& sources, ImportStatus& status, uint32_t current, uint32_t total);
bool import_sndfile_as_region (std::string path, SrcQuality quality, timepos_t& pos, SourceList& sources, ImportStatus& status, uint32_t current, uint32_t total);
struct ptflookup {
uint16_t index1;
@ -1965,8 +1965,8 @@ private:
void remove_playlist (boost::weak_ptr<Playlist>);
void track_playlist_changed (boost::weak_ptr<Track>);
void playlist_region_added (boost::weak_ptr<Region>);
void playlist_ranges_moved (std::list<Evoral::RangeMove<samplepos_t> > const &);
void playlist_regions_extended (std::list<Evoral::Range<samplepos_t> > const &);
void playlist_ranges_moved (std::list<Temporal::RangeMove> const &);
void playlist_regions_extended (std::list<Temporal::Range> const &);
/* CURVES and AUTOMATION LISTS */
std::map<PBD::ID, AutomationList*> automation_lists;
@ -2106,16 +2106,16 @@ private:
/* range playback */
std::list<AudioRange> current_audio_range;
std::list<TimelineRange> current_audio_range;
bool _play_range;
void set_play_range (std::list<AudioRange>&, bool leave_rolling);
void set_play_range (std::list<TimelineRange>&, bool leave_rolling);
void unset_play_range ();
/* temporary hacks to allow selection to be pushed from GUI into backend
Whenever we move the selection object into libardour, these will go away.
*/
Evoral::Range<samplepos_t> _range_selection;
Evoral::Range<samplepos_t> _object_selection;
Temporal::Range _range_selection;
Temporal::Range _object_selection;
void unset_preroll_record_trim ();

View File

@ -114,8 +114,8 @@ public:
RTeventCallback rt_return; /* called after rt_slot, with this event as an argument */
PBD::EventLoop* event_loop;
std::list<AudioRange> audio_range;
std::list<MusicRange> music_range;
std::list<TimelineRange> audio_range;
std::list<TimelineRange> music_range;
boost::shared_ptr<Region> region;
boost::shared_ptr<TransportMaster> transport_master;

View File

@ -54,7 +54,7 @@ protected:
}
samplecnt_t read_unlocked (Sample *dst, samplepos_t start, samplecnt_t cnt) const {
cnt = std::min (cnt, std::max<samplecnt_t> (0, _length - start));
cnt = std::min (cnt, std::max<samplecnt_t> (0, _length.samples() - start));
memset (dst, 0, sizeof (Sample) * cnt);
return cnt;
}

View File

@ -76,13 +76,13 @@ public:
int set_state (XMLNode const&, int);
XMLNode& get_state();
bool find_next_event (double n, double e, Evoral::ControlEvent& ev) const
bool find_next_event (Temporal::timepos_t const & n, Temporal::timepos_t const & e, Evoral::ControlEvent& ev) const
{
Glib::Threads::RWLock::ReaderLock lm (master_lock);
return find_next_event_locked (n, e, ev);
}
bool find_next_event_locked (double now, double end, Evoral::ControlEvent& next_event) const;
bool find_next_event_locked (Temporal::timepos_t const & now, Temporal::timepos_t const & end, Evoral::ControlEvent& next_event) const;
protected:
@ -136,7 +136,7 @@ protected:
void update_boolean_masters_records (boost::shared_ptr<AutomationControl>);
virtual bool get_masters_curve_locked (samplepos_t, samplepos_t, float*, samplecnt_t) const;
bool masters_curve_multiply (samplepos_t, samplepos_t, float*, samplecnt_t) const;
bool masters_curve_multiply (timepos_t const &, timepos_t const &, float*, samplecnt_t) const;
virtual double reduce_by_masters_locked (double val, bool) const;
virtual double scale_automation_callback (double val, double ratio) const;

View File

@ -80,34 +80,33 @@ public:
private:
bool _open;
Temporal::Beats _last_ev_time_beats;
samplepos_t _last_ev_time_samples;
Temporal::Beats _last_ev_time_beats;
samplepos_t _last_ev_time_samples;
/** end time (start + duration) of last call to read_unlocked */
mutable samplepos_t _smf_last_read_end;
mutable timecnt_t _smf_last_read_end;
/** time (in SMF ticks, 1 tick per _ppqn) of the last event read by read_unlocked */
mutable samplepos_t _smf_last_read_time;
mutable timepos_t _smf_last_read_time;
int open_for_write ();
void ensure_disk_file (const Lock& lock);
samplecnt_t read_unlocked (const Lock& lock,
Evoral::EventSink<samplepos_t>& dst,
samplepos_t position,
samplepos_t start,
samplecnt_t cnt,
Evoral::Range<samplepos_t>* loop_range,
MidiStateTracker* tracker,
MidiChannelFilter* filter) const;
timecnt_t read_unlocked (const Lock& lock,
Evoral::EventSink<samplepos_t>& dst,
timepos_t const & position,
timecnt_t const & start,
timecnt_t const & cnt,
Temporal::Range* loop_range,
MidiStateTracker* tracker,
MidiChannelFilter* filter) const;
samplecnt_t write_unlocked (const Lock& lock,
MidiRingBuffer<samplepos_t>& src,
samplepos_t position,
samplecnt_t cnt);
timecnt_t write_unlocked (const Lock& lock,
MidiRingBuffer<samplepos_t>& src,
timepos_t const & position,
timecnt_t const & cnt);
};
}; /* namespace ARDOUR */
#endif /* __ardour_smf_source_h__ */

View File

@ -94,7 +94,7 @@ class LIBARDOUR_API SndFileSource : public AudioFileSource {
int setup_broadcast_info (samplepos_t when, struct tm&, time_t);
void file_closed ();
void set_natural_position (samplepos_t);
void set_natural_position (timepos_t const &);
samplecnt_t nondestructive_write_unlocked (Sample *dst, samplecnt_t cnt);
PBD::ScopedConnection header_position_connection;
};

View File

@ -74,9 +74,11 @@ public:
time_t timestamp() const { return _timestamp; }
void stamp (time_t when) { _timestamp = when; }
virtual bool empty () const = 0;
virtual samplecnt_t length (samplepos_t pos) const = 0;
virtual void update_length (samplecnt_t cnt) = 0;
timecnt_t length() const;
virtual bool empty () const;
virtual samplecnt_t length_samples (timepos_t const & pos) const { return _length.samples(); };
virtual void update_length (timecnt_t const & cnt) {}
void set_take_id (std::string id) { _take_id =id; }
const std::string& take_id () const { return _take_id; }
@ -114,14 +116,15 @@ public:
CueMarkers const & cue_markers() const { return _cue_markers; }
bool add_cue_marker (CueMarker const &);
bool move_cue_marker (CueMarker const &, samplepos_t source_relative_position);
bool move_cue_marker (CueMarker const &, timepos_t const & source_relative_position);
bool remove_cue_marker (CueMarker const &);
bool rename_cue_marker (CueMarker&, std::string const &);
bool clear_cue_markers ();
PBD::Signal0<void> CueMarkersChanged;
virtual samplepos_t natural_position() const { return _natural_position; }
virtual void set_natural_position (samplepos_t pos);
virtual timepos_t natural_position() const { return _natural_position; }
virtual void set_natural_position (timepos_t const & pos);
bool have_natural_position() const { return _have_natural_position; }
void set_allow_remove_if_empty (bool yn);
@ -143,19 +146,19 @@ public:
std::string captured_for() const { return _captured_for; }
protected:
DataType _type;
Flag _flags;
time_t _timestamp;
std::string _take_id;
samplepos_t _natural_position;
samplepos_t _have_natural_position;
bool _analysed;
DataType _type;
Flag _flags;
time_t _timestamp;
std::string _take_id;
timepos_t _natural_position;
bool _have_natural_position;
bool _analysed;
GATOMIC_QUAL gint _use_count; /* atomic */
uint32_t _level; /* how deeply nested is this source w.r.t a disk file */
std::string _ancestor_name;
std::string _captured_for;
XrunPositions _xruns;
CueMarkers _cue_markers;
uint32_t _level; /* how deeply nested is this source w.r.t a disk file */
std::string _ancestor_name;
std::string _captured_for;
timecnt_t _length;
XrunPositions _xruns;
mutable Glib::Threads::Mutex _lock;
mutable Glib::Threads::Mutex _analysis_lock;

View File

@ -62,7 +62,7 @@ class LIBARDOUR_API SourceFactory {
static boost::shared_ptr<Source> createFromPlaylist
(DataType type, Session& s, boost::shared_ptr<Playlist> p, const PBD::ID& orig, const std::string& name,
uint32_t chn, sampleoffset_t start, samplecnt_t len, bool copy, bool defer_peaks);
uint32_t chn, timepos_t start, timepos_t const & len, bool copy, bool defer_peaks);
static Glib::Threads::Cond PeaksToBuild;
static Glib::Threads::Mutex peak_building_lock;

View File

@ -42,9 +42,9 @@ public:
float sample_rate () const { return _session.nominal_sample_rate(); }
samplepos_t natural_position() const { return _source->natural_position() * _ratio;}
samplecnt_t readable_length() const { return _source->readable_length() * _ratio; }
samplecnt_t length (samplepos_t pos) const { return _source->length(pos) * _ratio; }
timepos_t natural_position() const { return _source->natural_position() * _ratio;}
samplecnt_t readable_length_samples() const { return _source->length_samples (timepos_t (Temporal::AudioTime)) * _ratio; }
samplecnt_t length (samplepos_t /*pos*/) const { return _source->length_samples (timepos_t (Temporal::AudioTime)) * _ratio; }
bool can_be_analysed() const { return false; }
bool clamped_at_unity() const { return false; }

View File

@ -50,6 +50,11 @@ class XMLNode;
namespace ARDOUR {
enum PositionLockStyle {
AudioTime,
MusicTime
};
class Meter;
class TempoMap;

View File

@ -19,15 +19,21 @@
#ifndef __libardour_timefx_request_h__
#define __libardour_timefx_request_h__
#include "temporal/types.h"
#include "ardour/interthread_info.h"
namespace ARDOUR {
struct TimeFXRequest : public InterThreadInfo {
TimeFXRequest()
: time_fraction(0), pitch_fraction(0),
use_soundtouch(false), quick_seek(false), antialias(false), opts(0) {}
float time_fraction;
: time_fraction(0,0)
, pitch_fraction(0)
, use_soundtouch(false)
, quick_seek(false)
, antialias(false)
, opts(0) {}
Temporal::ratio_t time_fraction;
float pitch_fraction;
/* SoundTouch */
bool use_soundtouch;

View File

@ -25,7 +25,7 @@
namespace ARDOUR {
class AudioSource;
class Readable;
class AudioReadable;
class Session;
class LIBARDOUR_API TransientDetector : public AudioAnalyser
@ -39,8 +39,8 @@ public:
void set_threshold (float);
void set_sensitivity (uint32_t, float);
int run (const std::string& path, Readable*, uint32_t channel, AnalysisFeatureList& results);
void update_positions (Readable* src, uint32_t channel, AnalysisFeatureList& results);
int run (const std::string& path, AudioReadable*, uint32_t channel, AnalysisFeatureList& results);
void update_positions (AudioReadable* src, uint32_t channel, AnalysisFeatureList& results);
static void cleanup_transients (AnalysisFeatureList&, float sr, float gap_msecs);

View File

@ -43,6 +43,7 @@
#include <inttypes.h>
#include "temporal/bbt_time.h"
#include "temporal/range.h"
#include "temporal/superclock.h"
#include "temporal/time.h"
#include "temporal/timeline.h"
@ -51,8 +52,6 @@
#include "pbd/id.h"
#include "pbd/microseconds.h"
#include "evoral/Range.h"
#include "ardour/chan_count.h"
#include "ardour/plugin_types.h"
@ -355,64 +354,41 @@ struct MusicSample {
MusicSample operator- (MusicSample other) { return MusicSample (sample - other.sample, 0); }
};
/* XXX: slightly unfortunate that there is this and Evoral::Range<>,
but this has a uint32_t id which Evoral::Range<> does not.
*/
struct AudioRange {
samplepos_t start;
samplepos_t end;
/* Just a Temporal::Range with an ID for identity
*/
struct TimelineRange : public Temporal::TimeRange
{
uint32_t id;
AudioRange (samplepos_t s, samplepos_t e, uint32_t i) : start (s), end (e) , id (i) {}
TimelineRange (Temporal::timepos_t const & s, Temporal::timepos_t e, uint32_t i) : Temporal::TimeRange (s, e), id (i) {}
samplecnt_t length() const { return end - start + 1; }
samplecnt_t length_samples() const { return length().samples(); }
bool operator== (const AudioRange& other) const {
return start == other.start && end == other.end && id == other.id;
bool operator== (const TimelineRange& other) const {
return id == other.id && Temporal::TimeRange::operator== (other);
}
bool equal (const AudioRange& other) const {
return start == other.start && end == other.end;
}
Evoral::OverlapType coverage (samplepos_t s, samplepos_t e) const {
return Evoral::coverage (start, end, s, e);
}
};
struct MusicRange {
Temporal::BBT_Time start;
Temporal::BBT_Time end;
uint32_t id;
MusicRange (Temporal::BBT_Time& s, Temporal::BBT_Time& e, uint32_t i)
: start (s), end (e), id (i) {}
bool operator== (const MusicRange& other) const {
return start == other.start && end == other.end && id == other.id;
}
bool equal (const MusicRange& other) const {
return start == other.start && end == other.end;
bool equal (const TimelineRange& other) const {
return Temporal::TimeRange::operator== (other);
}
};
class CueMarker {
public:
CueMarker (std::string const& text, samplepos_t position) : _text (text), _position (position) {}
CueMarker (std::string const& text, timepos_t const & position) : _text (text), _position (position) {}
std::string text() const { return _text; }
void set_text (std::string const & str) { _text = str; }
samplepos_t position() const { return _position; }
void set_position (samplepos_t pos) { _position = pos; }
timepos_t position() const { return _position; }
void set_position (timepos_t const & pos) { _position = pos; }
bool operator== (CueMarker const & other) const { return _position == other.position() && _text == other.text(); }
bool operator< (CueMarker const & other) const { return _position < other.position(); }
private:
std::string _text;
samplepos_t _position;
timepos_t _position;
};
typedef std::set<CueMarker> CueMarkers;
@ -692,11 +668,6 @@ struct CleanupReport {
size_t space;
};
enum PositionLockStyle {
AudioTime,
MusicTime
};
/** A struct used to describe changes to processors in a route.
* This is useful because objects that respond to a change in processors
* can optimise what work they do based on details of what has changed.

View File

@ -51,7 +51,6 @@ DEFINE_ENUM_CONVERT(ARDOUR::SyncSource)
DEFINE_ENUM_CONVERT(ARDOUR::ShuttleUnits)
DEFINE_ENUM_CONVERT(ARDOUR::ClockDeltaMode)
DEFINE_ENUM_CONVERT(ARDOUR::DenormalModel)
DEFINE_ENUM_CONVERT(ARDOUR::PositionLockStyle)
DEFINE_ENUM_CONVERT(ARDOUR::FadeShape)
DEFINE_ENUM_CONVERT(ARDOUR::RegionSelectionAfterSplit)
DEFINE_ENUM_CONVERT(ARDOUR::RangeSelectionAfterSplit)
@ -88,7 +87,7 @@ inline std::string to_string (ARDOUR::timepos_t val)
template <>
inline ARDOUR::timepos_t string_to (std::string const & str)
{
ARDOUR::timepos_t tmp;
ARDOUR::timepos_t tmp (Temporal::AudioTime); /* domain may be changed */
tmp.string_to (str);
return tmp;
}
@ -116,7 +115,7 @@ inline std::string to_string (ARDOUR::timecnt_t val)
template <>
inline ARDOUR::timecnt_t string_to (std::string const & str)
{
ARDOUR::timecnt_t tmp;
ARDOUR::timecnt_t tmp (Temporal::AudioTime); /* domain may change */
tmp.string_to (str);
return tmp;
}

View File

@ -67,13 +67,14 @@ AudioPlaylist::AudioPlaylist (boost::shared_ptr<const AudioPlaylist> other, stri
{
}
AudioPlaylist::AudioPlaylist (boost::shared_ptr<const AudioPlaylist> other, samplepos_t start, samplecnt_t cnt, string name, bool hidden)
AudioPlaylist::AudioPlaylist (boost::shared_ptr<const AudioPlaylist> other, timepos_t const & start, timepos_t const & cnt, string name, bool hidden)
: Playlist (other, start, cnt, name, hidden)
{
RegionReadLock rlock2 (const_cast<AudioPlaylist*> (other.get()));
in_set_state++;
samplepos_t const end = start + cnt - 1;
const timepos_t tend = start + cnt;
samplepos_t end = tend.samples();
/* Audio regions that have been created by the Playlist constructor
will currently have the same fade in/out as the regions that they
@ -89,43 +90,46 @@ AudioPlaylist::AudioPlaylist (boost::shared_ptr<const AudioPlaylist> other, samp
samplecnt_t fade_in = 64;
samplecnt_t fade_out = 64;
switch (region->coverage (start, end)) {
case Evoral::OverlapNone:
switch (region->coverage (start, tend)) {
case Temporal::OverlapNone:
continue;
case Evoral::OverlapInternal:
case Temporal::OverlapInternal:
{
samplecnt_t const offset = start - region->position ();
samplecnt_t const offset = start.samples() - region->position_sample ();
samplecnt_t const trim = region->last_sample() - end;
if (region->fade_in()->back()->when > offset) {
fade_in = region->fade_in()->back()->when - offset;
fade_in = region->fade_in()->back()->when.earlier (timepos_t (offset)).samples();
}
if (region->fade_out()->back()->when > trim) {
fade_out = region->fade_out()->back()->when - trim;
fade_out = region->fade_out()->back()->when.earlier (timepos_t (trim)).samples();
}
break;
}
case Evoral::OverlapStart: {
if (end > region->position() + region->fade_in()->back()->when)
fade_in = region->fade_in()->back()->when; //end is after fade-in, preserve the fade-in
if (end > region->last_sample() - region->fade_out()->back()->when)
fade_out = region->fade_out()->back()->when - ( region->last_sample() - end ); //end is inside the fadeout, preserve the fades endpoint
case Temporal::OverlapStart: {
if (timepos_t (end) > region->nt_position() + region->fade_in()->back()->when) {
fade_in = region->fade_in()->back()->when.samples(); //end is after fade-in, preserve the fade-in
}
if (timepos_t (end) >= region->nt_end().earlier (region->fade_out()->back()->when)) {
fade_out = region->fade_out()->back()->when.earlier (timepos_t (region->last_sample() - end)).samples(); //end is inside the fadeout, preserve the fades endpoint
}
break;
}
case Evoral::OverlapEnd: {
if (start < region->last_sample() - region->fade_out()->back()->when) //start is before fade-out, preserve the fadeout
fade_out = region->fade_out()->back()->when;
if (start < region->position() + region->fade_in()->back()->when)
fade_in = region->fade_in()->back()->when - (start - region->position()); //end is inside the fade-in, preserve the fade-in endpoint
case Temporal::OverlapEnd: {
if (start < region->nt_end().earlier (region->fade_out()->back()->when)) { //start is before fade-out, preserve the fadeout
fade_out = region->fade_out()->back()->when.samples();
}
if (start < region->nt_position() + region->fade_in()->back()->when) {
fade_in = region->fade_in()->back()->when.earlier (start.distance (region->nt_position())).samples(); //end is inside the fade-in, preserve the fade-in endpoint
}
break;
}
case Evoral::OverlapExternal:
fade_in = region->fade_in()->back()->when;
fade_out = region->fade_out()->back()->when;
case Temporal::OverlapExternal:
fade_in = region->fade_in()->back()->when.samples();
fade_out = region->fade_out()->back()->when.samples();
break;
}
@ -149,23 +153,23 @@ struct ReadSorter {
return a->layer() > b->layer();
}
return a->position() < b->position();
return a->nt_position() < b->nt_position();
}
};
/** A segment of region that needs to be read */
struct Segment {
Segment (boost::shared_ptr<AudioRegion> r, Evoral::Range<samplepos_t> a) : region (r), range (a) {}
Segment (boost::shared_ptr<AudioRegion> r, Temporal::Range a) : region (r), range (a) {}
boost::shared_ptr<AudioRegion> region; ///< the region
Evoral::Range<samplepos_t> range; ///< range of the region to read, in session samples
Temporal::Range range; ///< range of the region to read, in session samples
};
/** @param start Start position in session samples.
* @param cnt Number of samples to read.
*/
ARDOUR::samplecnt_t
AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, samplepos_t start, samplecnt_t cnt, unsigned chan_n)
ARDOUR::timecnt_t
AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, timepos_t const & start, timecnt_t const & cnt, uint32_t chan_n)
{
DEBUG_TRACE (DEBUG::AudioPlayback, string_compose ("Playlist %1 read @ %2 for %3, channel %4, regions %5 mixdown @ %6 gain @ %7\n",
name(), start, cnt, chan_n, regions.size(), mixdown_buffer, gain_buffer));
@ -183,7 +187,7 @@ AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, sa
zeroed.
*/
memset (buf, 0, sizeof (Sample) * cnt);
memset (buf, 0, sizeof (Sample) * cnt.samples());
/* this function is never called from a realtime thread, so
its OK to block (for short intervals).
@ -194,14 +198,14 @@ AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, sa
/* Find all the regions that are involved in the bit we are reading,
and sort them by descending layer and ascending position.
*/
boost::shared_ptr<RegionList> all = regions_touched_locked (start, start + cnt - 1);
boost::shared_ptr<RegionList> all = regions_touched_locked (start, start + cnt);
all->sort (ReadSorter ());
/* This will be a list of the bits of our read range that we have
handled completely (ie for which no more regions need to be read).
It is a list of ranges in session samples.
*/
Evoral::RangeList<samplepos_t> done;
Temporal::RangeList done;
/* This will be a list of the bits of regions that we need to read */
list<Segment> to_do;
@ -224,30 +228,31 @@ AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, sa
/* Work out which bits of this region need to be read;
first, trim to the range we are reading...
*/
Evoral::Range<samplepos_t> region_range = ar->range ();
region_range.from = max (region_range.from, start);
region_range.to = min (region_range.to, start + cnt - 1);
Temporal::Range rrange = ar->range_samples ();
Temporal::Range region_range (max (rrange.start(), start),
min (rrange.end(), start + cnt));
/* ... and then remove the bits that are already done */
Evoral::RangeList<samplepos_t> region_to_do = Evoral::subtract (region_range, done);
Temporal::RangeList region_to_do = region_range.subtract (done);
/* Make a note to read those bits, adding their bodies (the parts between end-of-fade-in
and start-of-fade-out) to the `done' list.
*/
Evoral::RangeList<samplepos_t>::List t = region_to_do.get ();
Temporal::RangeList::List t = region_to_do.get ();
for (Evoral::RangeList<samplepos_t>::List::iterator j = t.begin(); j != t.end(); ++j) {
Evoral::Range<samplepos_t> d = *j;
for (Temporal::RangeList::List::iterator j = t.begin(); j != t.end(); ++j) {
Temporal::Range d = *j;
to_do.push_back (Segment (ar, d));
if (ar->opaque ()) {
/* Cut this range down to just the body and mark it done */
Evoral::Range<samplepos_t> body = ar->body_range ();
if (body.from < d.to && body.to > d.from) {
d.from = max (d.from, body.from);
d.to = min (d.to, body.to);
Temporal::Range body = ar->body_range ();
if (body.start() < d.end() && body.end() > d.start()) {
d.set_start (max (d.start(), body.start()));
d.set_end (min (d.end(), body.end()));
done.add (d);
}
}
@ -255,12 +260,14 @@ AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, sa
}
/* Now go backwards through the to_do list doing the actual reads */
for (list<Segment>::reverse_iterator i = to_do.rbegin(); i != to_do.rend(); ++i) {
DEBUG_TRACE (DEBUG::AudioPlayback, string_compose ("\tPlaylist %1 read %2 @ %3 for %4, channel %5, buf @ %6 offset %7\n",
name(), i->region->name(), i->range.from,
i->range.to - i->range.from + 1, (int) chan_n,
buf, i->range.from - start));
i->region->read_at (buf + i->range.from - start, mixdown_buffer, gain_buffer, i->range.from, i->range.to - i->range.from + 1, chan_n);
name(), i->region->name(), i->range.start(),
i->range.length(), (int) chan_n,
buf, i->range.start().earlier (start)));
i->region->read_at (buf + start.distance (i->range.start()).samples(), mixdown_buffer, gain_buffer, i->range.start().samples(), i->range.start().distance (i->range.end()).samples(), chan_n);
}
return cnt;
@ -278,9 +285,9 @@ AudioPlaylist::dump () const
for (RegionList::const_iterator i = regions.begin(); i != regions.end(); ++i) {
r = *i;
cerr << " " << r->name() << " @ " << r << " ["
<< r->start() << "+" << r->length()
<< r->nt_start() << "+" << r->nt_length()
<< "] at "
<< r->position()
<< r->nt_position()
<< " on layer "
<< r->layer ()
<< endl;
@ -460,7 +467,7 @@ AudioPlaylist::pre_uncombine (vector<boost::shared_ptr<Region> >& originals, boo
original region.
*/
if (cr->fade_in()->back()->when <= ar->length()) {
if (cr->fade_in()->back()->when <= ar->nt_length()) {
/* don't do this if the fade is longer than the
* region
*/
@ -474,7 +481,7 @@ AudioPlaylist::pre_uncombine (vector<boost::shared_ptr<Region> >& originals, boo
original region.
*/
if (cr->fade_out()->back()->when <= ar->length()) {
if (cr->fade_out()->back()->when <= ar->nt_length()) {
/* don't do this if the fade is longer than the
* region
*/

View File

@ -45,13 +45,14 @@ using namespace ARDOUR;
using namespace PBD;
AudioPlaylistSource::AudioPlaylistSource (Session& s, const ID& orig, const std::string& name, boost::shared_ptr<AudioPlaylist> p,
uint32_t chn, sampleoffset_t begin, samplecnt_t len, Source::Flag flags)
uint32_t chn, timepos_t const & begin, timepos_t const & len, Source::Flag flags)
: Source (s, DataType::AUDIO, name)
, PlaylistSource (s, orig, name, p, DataType::AUDIO, begin, len, flags)
, AudioSource (s, name)
, _playlist_channel (chn)
{
AudioSource::_length = len;
AudioSource::_length = timecnt_t (len);
ensure_buffers_for_level (_level, _session.sample_rate());
}
AudioPlaylistSource::AudioPlaylistSource (Session& s, const XMLNode& node)
@ -70,7 +71,7 @@ AudioPlaylistSource::AudioPlaylistSource (Session& s, const XMLNode& node)
throw failed_constructor ();
}
AudioSource::_length = _playlist_length;
_length = timecnt_t (_playlist_length);
}
AudioPlaylistSource::~AudioPlaylistSource ()
@ -108,9 +109,9 @@ AudioPlaylistSource::set_state (const XMLNode& node, int version, bool with_desc
}
}
pair<samplepos_t,samplepos_t> extent = _playlist->get_extent();
pair<timepos_t,timepos_t> extent = _playlist->get_extent();
AudioSource::_length = extent.second - extent.first;
AudioSource::_length = extent.first.distance (extent.second);
if (!node.get_property (X_("channel"), _playlist_channel)) {
throw failed_constructor ();
@ -130,8 +131,8 @@ AudioPlaylistSource::read_unlocked (Sample* dst, samplepos_t start, samplecnt_t
* is not supposed be part of our data.
*/
if (cnt > _playlist_length - start) {
to_read = _playlist_length - start;
if (cnt > _playlist_length.samples() - start) {
to_read = _playlist_length.samples() - start;
to_zero = cnt - to_read;
} else {
to_read = cnt;
@ -141,7 +142,7 @@ AudioPlaylistSource::read_unlocked (Sample* dst, samplepos_t start, samplecnt_t
boost::scoped_array<float> sbuf(new float[to_read]);
boost::scoped_array<gain_t> gbuf(new gain_t[to_read]);
boost::dynamic_pointer_cast<AudioPlaylist>(_playlist)->read (dst, sbuf.get(), gbuf.get(), start+_playlist_offset, to_read, _playlist_channel);
boost::dynamic_pointer_cast<AudioPlaylist>(_playlist)->read (dst, sbuf.get(), gbuf.get(), timepos_t (start)+_playlist_offset, timecnt_t (to_read), _playlist_channel);
if (to_zero) {
memset (dst+to_read, 0, sizeof (Sample) * to_zero);

View File

@ -314,7 +314,7 @@ AudioRegionImporter::prepare_region ()
// create region and update XML
boost::shared_ptr<Region> r = RegionFactory::create (source_list, xml_region);
if (session.config.get_glue_new_regions_to_bars_and_beats ()) {
r->set_position_lock_style (MusicTime);
r->set_position_time_domain (Temporal::BeatTime);
}
region.push_back (r);
if (*region.begin()) {

View File

@ -213,7 +213,7 @@ AudioTrack::export_stuff (BufferSet& buffers, samplepos_t start, samplecnt_t nfr
assert(buffers.count().n_audio() >= 1);
assert ((samplecnt_t) buffers.get_audio(0).capacity() >= nframes);
if (apl->read (buffers.get_audio(0).data(), mix_buffer.get(), gain_buffer.get(), start, nframes) != nframes) {
if (apl->read (buffers.get_audio(0).data(), mix_buffer.get(), gain_buffer.get(), timepos_t (start), timecnt_t (nframes)) != nframes) {
return -1;
}
@ -223,7 +223,7 @@ AudioTrack::export_stuff (BufferSet& buffers, samplepos_t start, samplecnt_t nfr
++bi;
for ( ; bi != buffers.audio_end(); ++bi, ++n) {
if (n < _disk_reader->output_streams().n_audio()) {
if (apl->read (bi->data(), mix_buffer.get(), gain_buffer.get(), start, nframes, n) != nframes) {
if (apl->read (bi->data(), mix_buffer.get(), gain_buffer.get(), timepos_t (start), timecnt_t (nframes), n) != nframes) {
return -1;
}
b = bi->data();
@ -402,14 +402,15 @@ AudioTrack::freeze_me (InterThreadInfo& itt)
PropertyList plist;
plist.add (Properties::start, 0);
plist.add (Properties::length, srcs[0]->length(srcs[0]->natural_position()));
plist.add (Properties::length, srcs[0]->length());
plist.add (Properties::name, region_name);
plist.add (Properties::whole_file, true);
boost::shared_ptr<Region> region (RegionFactory::create (srcs, plist, false));
new_playlist->set_orig_track_id (id());
new_playlist->add_region (region, _session.current_start_sample());
#warning NUTEMPO fixme this probably should not use samples unconditionally
new_playlist->add_region (region, timepos_t (_session.current_start_sample()));
new_playlist->set_frozen (true);
region->set_locked (true);

View File

@ -102,14 +102,14 @@ AudioAnalyser::reset ()
}
int
AudioAnalyser::analyse (const string& path, Readable* src, uint32_t channel)
AudioAnalyser::analyse (const string& path, AudioReadable* src, uint32_t channel)
{
stringstream outss;
Plugin::FeatureSet features;
int ret = -1;
bool done = false;
Sample* data = 0;
samplecnt_t len = src->readable_length();
samplecnt_t len = src->readable_length_samples();
samplepos_t pos = 0;
float* bufs[1] = { 0 };

View File

@ -85,10 +85,13 @@ namespace ARDOUR {
static void
reverse_curve (boost::shared_ptr<Evoral::ControlList> dst, boost::shared_ptr<const Evoral::ControlList> src)
{
size_t len = src->when(false);
const timepos_t end = src->when(false);
// TODO read-lock of src (!)
for (Evoral::ControlList::const_reverse_iterator it = src->rbegin(); it!=src->rend(); it++) {
dst->fast_simple_add (len - (*it)->when, (*it)->value);
/* ugh ... the double "distance" calls (with totally different
semantics ... horrible
*/
dst->fast_simple_add (timepos_t ((*it)->when.distance (end)), (*it)->value);
}
}
@ -108,17 +111,17 @@ static void
generate_db_fade (boost::shared_ptr<Evoral::ControlList> dst, double len, int num_steps, float dB_drop)
{
dst->clear ();
dst->fast_simple_add (0, 1);
dst->fast_simple_add (timepos_t (Temporal::AudioTime), 1);
//generate a fade-out curve by successively applying a gain drop
float fade_speed = dB_to_coefficient(dB_drop / (float) num_steps);
float coeff = GAIN_COEFF_UNITY;
for (int i = 1; i < (num_steps-1); i++) {
coeff *= fade_speed;
dst->fast_simple_add (len*(double)i/(double)num_steps, coeff);
dst->fast_simple_add (timepos_t (len*(double)i/(double)num_steps), coeff);
}
dst->fast_simple_add (len, GAIN_COEFF_SMALL);
dst->fast_simple_add (timepos_t (len), GAIN_COEFF_SMALL);
}
static void
@ -194,6 +197,7 @@ AudioRegion::register_properties ()
add_property (_envelope);
}
#warning NUTEMPO QUESTION what time domains should be used here?
#define AUDIOREGION_STATE_DEFAULT \
_envelope_active (Properties::envelope_active, false) \
, _default_fade_in (Properties::default_fade_in, true) \
@ -201,10 +205,10 @@ AudioRegion::register_properties ()
, _fade_in_active (Properties::fade_in_active, true) \
, _fade_out_active (Properties::fade_out_active, true) \
, _scale_amplitude (Properties::scale_amplitude, 1.0) \
, _fade_in (Properties::fade_in, boost::shared_ptr<AutomationList> (new AutomationList (Evoral::Parameter (FadeInAutomation)))) \
, _inverse_fade_in (Properties::inverse_fade_in, boost::shared_ptr<AutomationList> (new AutomationList (Evoral::Parameter (FadeInAutomation)))) \
, _fade_out (Properties::fade_out, boost::shared_ptr<AutomationList> (new AutomationList (Evoral::Parameter (FadeOutAutomation)))) \
, _inverse_fade_out (Properties::inverse_fade_out, boost::shared_ptr<AutomationList> (new AutomationList (Evoral::Parameter (FadeOutAutomation))))
, _fade_in (Properties::fade_in, boost::shared_ptr<AutomationList> (new AutomationList (Evoral::Parameter (FadeInAutomation), Temporal::AudioTime))) \
, _inverse_fade_in (Properties::inverse_fade_in, boost::shared_ptr<AutomationList> (new AutomationList (Evoral::Parameter (FadeInAutomation), Temporal::AudioTime))) \
, _fade_out (Properties::fade_out, boost::shared_ptr<AutomationList> (new AutomationList (Evoral::Parameter (FadeOutAutomation), Temporal::AudioTime))) \
, _inverse_fade_out (Properties::inverse_fade_out, boost::shared_ptr<AutomationList> (new AutomationList (Evoral::Parameter (FadeOutAutomation), Temporal::AudioTime)))
#define AUDIOREGION_COPY_STATE(other) \
_envelope_active (Properties::envelope_active, other->_envelope_active) \
@ -238,7 +242,7 @@ AudioRegion::init ()
AudioRegion::AudioRegion (Session& s, timecnt_t const & start, timecnt_t const & len, std::string name)
: Region (s, start, len, name, DataType::AUDIO)
, AUDIOREGION_STATE_DEFAULT
, _envelope (Properties::envelope, boost::shared_ptr<AutomationList> (new AutomationList (Evoral::Parameter(EnvelopeAutomation))))
, _envelope (Properties::envelope, boost::shared_ptr<AutomationList> (new AutomationList (Evoral::Parameter(EnvelopeAutomation), Temporal::AudioTime)))
, _automatable (s)
, _fade_in_suspended (0)
, _fade_out_suspended (0)
@ -251,7 +255,7 @@ AudioRegion::AudioRegion (Session& s, timecnt_t const & start, timecnt_t const
AudioRegion::AudioRegion (const SourceList& srcs)
: Region (srcs)
, AUDIOREGION_STATE_DEFAULT
, _envelope (Properties::envelope, boost::shared_ptr<AutomationList> (new AutomationList (Evoral::Parameter(EnvelopeAutomation))))
, _envelope (Properties::envelope, boost::shared_ptr<AutomationList> (new AutomationList (Evoral::Parameter(EnvelopeAutomation), Temporal::AudioTime)))
, _automatable(srcs[0]->session())
, _fade_in_suspended (0)
, _fade_out_suspended (0)
@ -266,7 +270,7 @@ AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other)
/* As far as I can see, the _envelope's times are relative to region position, and have nothing
* to do with sources (and hence _start). So when we copy the envelope, we just use the supplied offset.
*/
, _envelope (Properties::envelope, boost::shared_ptr<AutomationList> (new AutomationList (*other->_envelope.val(), 0, other->_length)))
, _envelope (Properties::envelope, boost::shared_ptr<AutomationList> (new AutomationList (*other->_envelope.val(), timepos_t (Temporal::AudioTime), timepos_t (other->_length))))
, _automatable (other->session())
, _fade_in_suspended (0)
, _fade_out_suspended (0)
@ -288,7 +292,7 @@ AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other, timecnt_t
/* As far as I can see, the _envelope's times are relative to region position, and have nothing
to do with sources (and hence _start). So when we copy the envelope, we just use the supplied offset.
*/
, _envelope (Properties::envelope, boost::shared_ptr<AutomationList> (new AutomationList (*other->_envelope.val(), offset.sample, other->_length)))
, _envelope (Properties::envelope, boost::shared_ptr<AutomationList> (new AutomationList (*other->_envelope.val(), timepos_t (offset.samples()), timepos_t (other->_length))))
, _automatable (other->session())
, _fade_in_suspended (0)
, _fade_out_suspended (0)
@ -326,7 +330,7 @@ AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other, const Sour
AudioRegion::AudioRegion (SourceList& srcs)
: Region (srcs)
, AUDIOREGION_STATE_DEFAULT
, _envelope (Properties::envelope, boost::shared_ptr<AutomationList> (new AutomationList(Evoral::Parameter(EnvelopeAutomation))))
, _envelope (Properties::envelope, boost::shared_ptr<AutomationList> (new AutomationList(Evoral::Parameter(EnvelopeAutomation), Temporal::AudioTime)))
, _automatable(srcs[0]->session())
, _fade_in_suspended (0)
, _fade_out_suspended (0)
@ -368,7 +372,7 @@ AudioRegion::post_set (const PropertyChange& /*ignored*/)
}
/* If _length changed, adjust our gain envelope accordingly */
_envelope->truncate_end (_length);
_envelope->truncate_end (timepos_t (_length.val()));
}
void
@ -454,7 +458,7 @@ samplecnt_t
AudioRegion::read (Sample* buf, samplepos_t pos, samplecnt_t cnt, int channel) const
{
/* raw read, no fades, no gain, nada */
return read_from_sources (_sources, _length, buf, _position + pos, cnt, channel);
return read_from_sources (_sources, _length.val().samples(), buf, _position.val().samples() + pos, cnt, channel);
}
samplecnt_t
@ -464,10 +468,7 @@ AudioRegion::master_read_at (Sample *buf, Sample* /*mixdown_buffer*/, float* /*g
/* do not read gain/scaling/fades and do not count this disk i/o in statistics */
assert (cnt >= 0);
return read_from_sources (
_master_sources, _master_sources.front()->length (_master_sources.front()->natural_position()),
buf, position, cnt, chan_n
);
return read_from_sources (_master_sources, _master_sources.front()->length ().samples(), buf, position, cnt, chan_n);
}
/** @param buf Buffer to mix data into.
@ -500,15 +501,17 @@ AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer,
/* WORK OUT WHERE TO GET DATA FROM */
samplecnt_t to_read;
const samplepos_t psamples = _position.val().samples();
const samplecnt_t lsamples = _length.val().samples();
assert (position >= _position);
sampleoffset_t const internal_offset = position - _position;
assert (position >= psamples);
sampleoffset_t const internal_offset = position - psamples;
if (internal_offset >= _length) {
if (internal_offset >= lsamples) {
return 0; /* read nothing */
}
if ((to_read = min (cnt, _length - internal_offset)) == 0) {
if ((to_read = min (cnt, lsamples - internal_offset)) == 0) {
return 0; /* read nothing */
}
@ -516,7 +519,7 @@ AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer,
if (!pl){
return 0;
}
/* COMPUTE DETAILS OF ANY FADES INVOLVED IN THIS READ */
/* Amount (length) of fade in that we are dealing with in this read */
@ -536,7 +539,7 @@ AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer,
if (_fade_in_active && _session.config.get_use_region_fades()) {
samplecnt_t fade_in_length = (samplecnt_t) _fade_in->when(false);
samplecnt_t fade_in_length = _fade_in->when(false).samples();
/* see if this read is within the fade in */
@ -568,8 +571,8 @@ AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer,
*
*/
fade_interval_start = max (internal_offset, _length - samplecnt_t (_fade_out->when(false)));
samplecnt_t fade_interval_end = min(internal_offset + to_read, _length.val());
fade_interval_start = max (internal_offset, lsamples - _fade_out->when(false).samples());
samplecnt_t fade_interval_end = min(internal_offset + to_read, lsamples);
if (fade_interval_end > fade_interval_start) {
/* (part of the) the fade out is in this buffer */
@ -584,14 +587,14 @@ AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer,
may need to mix with the existing data.
*/
if (read_from_sources (_sources, _length, mixdown_buffer, position, to_read, chan_n) != to_read) {
if (read_from_sources (_sources, lsamples, mixdown_buffer, psamples, to_read, chan_n) != to_read) {
return 0;
}
/* APPLY REGULAR GAIN CURVES AND SCALING TO mixdown_buffer */
if (envelope_active()) {
_envelope->curve().get_vector (internal_offset, internal_offset + to_read, gain_buffer, to_read);
_envelope->curve().get_vector (timepos_t (internal_offset), timepos_t (internal_offset + to_read), gain_buffer, to_read);
if (_scale_amplitude != 1.0f) {
for (samplecnt_t n = 0; n < to_read; ++n) {
@ -612,7 +615,7 @@ AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer,
* "buf" contains data from lower regions already. So this operation
* fades out the existing material.
*/
bool is_opaque = opaque();
if (fade_in_limit != 0) {
@ -624,7 +627,7 @@ AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer,
* power), so we have to fetch it.
*/
_inverse_fade_in->curve().get_vector (internal_offset, internal_offset + fade_in_limit, gain_buffer, fade_in_limit);
_inverse_fade_in->curve().get_vector (timepos_t (internal_offset), timepos_t (internal_offset + fade_in_limit), gain_buffer, fade_in_limit);
/* Fade the data from lower layers out */
for (samplecnt_t n = 0; n < fade_in_limit; ++n) {
@ -633,7 +636,7 @@ AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer,
/* refill gain buffer with the fade in */
_fade_in->curve().get_vector (internal_offset, internal_offset + fade_in_limit, gain_buffer, fade_in_limit);
_fade_in->curve().get_vector (timepos_t (internal_offset), timepos_t (internal_offset + fade_in_limit), gain_buffer, fade_in_limit);
} else {
@ -641,14 +644,14 @@ AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer,
* in) for the fade out of lower layers
*/
_fade_in->curve().get_vector (internal_offset, internal_offset + fade_in_limit, gain_buffer, fade_in_limit);
_fade_in->curve().get_vector (timepos_t (internal_offset), timepos_t (internal_offset + fade_in_limit), gain_buffer, fade_in_limit);
for (samplecnt_t n = 0; n < fade_in_limit; ++n) {
buf[n] *= 1 - gain_buffer[n];
}
}
} else {
_fade_in->curve().get_vector (internal_offset, internal_offset + fade_in_limit, gain_buffer, fade_in_limit);
_fade_in->curve().get_vector (timepos_t (internal_offset), timepos_t (internal_offset + fade_in_limit), gain_buffer, fade_in_limit);
}
/* Mix our newly-read data in, with the fade */
@ -659,12 +662,12 @@ AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer,
if (fade_out_limit != 0) {
samplecnt_t const curve_offset = fade_interval_start - (_length - _fade_out->when(false));
samplecnt_t const curve_offset = fade_interval_start - _fade_out->when(false).distance (timepos_t (_length)).samples();
if (is_opaque) {
if (_inverse_fade_out) {
_inverse_fade_out->curve().get_vector (curve_offset, curve_offset + fade_out_limit, gain_buffer, fade_out_limit);
_inverse_fade_out->curve().get_vector (timepos_t (curve_offset), timepos_t (curve_offset + fade_out_limit), gain_buffer, fade_out_limit);
/* Fade the data from lower levels in */
for (samplecnt_t n = 0, m = fade_out_offset; n < fade_out_limit; ++n, ++m) {
@ -673,7 +676,7 @@ AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer,
/* fetch the actual fade out */
_fade_out->curve().get_vector (curve_offset, curve_offset + fade_out_limit, gain_buffer, fade_out_limit);
_fade_out->curve().get_vector (timepos_t (curve_offset), timepos_t (curve_offset + fade_out_limit), gain_buffer, fade_out_limit);
} else {
@ -682,14 +685,14 @@ AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer,
* out) for the fade in of lower layers
*/
_fade_out->curve().get_vector (curve_offset, curve_offset + fade_out_limit, gain_buffer, fade_out_limit);
_fade_out->curve().get_vector (timepos_t (curve_offset), timepos_t (curve_offset + fade_out_limit), gain_buffer, fade_out_limit);
for (samplecnt_t n = 0, m = fade_out_offset; n < fade_out_limit; ++n, ++m) {
buf[m] *= 1 - gain_buffer[n];
}
}
} else {
_fade_out->curve().get_vector (curve_offset, curve_offset + fade_out_limit, gain_buffer, fade_out_limit);
_fade_out->curve().get_vector (timepos_t (curve_offset), timepos_t (curve_offset + fade_out_limit), gain_buffer, fade_out_limit);
}
/* Mix our newly-read data with whatever was already there,
@ -731,7 +734,7 @@ AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer,
samplecnt_t
AudioRegion::read_from_sources (SourceList const & srcs, samplecnt_t limit, Sample* buf, samplepos_t position, samplecnt_t cnt, uint32_t chan_n) const
{
sampleoffset_t const internal_offset = position - _position;
sampleoffset_t const internal_offset = position - _position.val().samples();
if (internal_offset >= limit) {
return 0;
}
@ -744,7 +747,7 @@ AudioRegion::read_from_sources (SourceList const & srcs, samplecnt_t limit, Samp
if (chan_n < n_channels()) {
boost::shared_ptr<AudioSource> src = boost::dynamic_pointer_cast<AudioSource> (srcs[chan_n]);
if (src->read (buf, _start + internal_offset, to_read) != to_read) {
if (src->read (buf, _start.val().samples() + internal_offset, to_read) != to_read) {
return 0; /* "read nothing" */
}
@ -761,7 +764,7 @@ AudioRegion::read_from_sources (SourceList const & srcs, samplecnt_t limit, Samp
uint32_t channel = chan_n % n_channels();
boost::shared_ptr<AudioSource> src = boost::dynamic_pointer_cast<AudioSource> (srcs[channel]);
if (src->read (buf, _start + internal_offset, to_read) != to_read) {
if (src->read (buf, _start.val().samples() + internal_offset, to_read) != to_read) {
return 0; /* "read nothing" */
}
@ -801,7 +804,7 @@ AudioRegion::state ()
if (_envelope->size() == 2 &&
_envelope->front()->value == GAIN_COEFF_UNITY &&
_envelope->back()->value==GAIN_COEFF_UNITY) {
if (_envelope->front()->when == 0 && _envelope->back()->when == _length) {
if (_envelope->front()->when == 0 && _envelope->back()->when == timepos_t (_length)) {
default_env = true;
}
}
@ -886,7 +889,7 @@ AudioRegion::_set_state (const XMLNode& node, int version, PropertyChange& what_
set_default_envelope ();
}
_envelope->truncate_end (_length);
_envelope->truncate_end (timepos_t (_length));
} else if (child->name() == "FadeIn") {
@ -966,20 +969,20 @@ AudioRegion::fade_range (samplepos_t start, samplepos_t end)
{
samplepos_t s, e;
switch (coverage (start, end)) {
case Evoral::OverlapStart:
trim_front(start);
s = _position;
switch (coverage (timepos_t (start), timepos_t (end))) {
case Temporal::OverlapStart:
trim_front (timepos_t (start));
s = _position.val().samples();
e = end;
set_fade_in (FadeConstantPower, e - s);
break;
case Evoral::OverlapEnd:
trim_end(end);
case Temporal::OverlapEnd:
trim_end(timepos_t (end));
s = start;
e = _position + _length;
e = (_position.val() + timepos_t (_length)).samples();
set_fade_out (FadeConstantPower, e - s);
break;
case Evoral::OverlapInternal:
case Temporal::OverlapInternal:
/* needs addressing, perhaps. Difficult to do if we can't
* control one edge of the fade relative to the relevant edge
* of the region, which we cannot - fades are currently assumed
@ -994,13 +997,13 @@ AudioRegion::fade_range (samplepos_t start, samplepos_t end)
void
AudioRegion::set_fade_in_shape (FadeShape shape)
{
set_fade_in (shape, (samplecnt_t) _fade_in->when(false));
set_fade_in (shape, _fade_in->when(false).samples());
}
void
AudioRegion::set_fade_out_shape (FadeShape shape)
{
set_fade_out (shape, (samplecnt_t) _fade_out->when(false));
set_fade_out (shape, _fade_out->when(false).samples());
}
void
@ -1018,9 +1021,9 @@ void
AudioRegion::set_fade_in (FadeShape shape, samplecnt_t len)
{
const ARDOUR::ParameterDescriptor desc(FadeInAutomation);
boost::shared_ptr<Evoral::ControlList> c1 (new Evoral::ControlList (FadeInAutomation, desc));
boost::shared_ptr<Evoral::ControlList> c2 (new Evoral::ControlList (FadeInAutomation, desc));
boost::shared_ptr<Evoral::ControlList> c3 (new Evoral::ControlList (FadeInAutomation, desc));
boost::shared_ptr<Evoral::ControlList> c1 (new Evoral::ControlList (FadeInAutomation, desc, Temporal::AudioTime));
boost::shared_ptr<Evoral::ControlList> c2 (new Evoral::ControlList (FadeInAutomation, desc, Temporal::AudioTime));
boost::shared_ptr<Evoral::ControlList> c3 (new Evoral::ControlList (FadeInAutomation, desc, Temporal::AudioTime));
_fade_in->freeze ();
_fade_in->clear ();
@ -1030,8 +1033,8 @@ AudioRegion::set_fade_in (FadeShape shape, samplecnt_t len)
switch (shape) {
case FadeLinear:
_fade_in->fast_simple_add (0.0, GAIN_COEFF_SMALL);
_fade_in->fast_simple_add (len, GAIN_COEFF_UNITY);
_fade_in->fast_simple_add (timepos_t (Temporal::AudioTime), GAIN_COEFF_SMALL);
_fade_in->fast_simple_add (timepos_t (len), GAIN_COEFF_UNITY);
reverse_curve (_inverse_fade_in.val(), _fade_in.val());
break;
@ -1052,26 +1055,26 @@ AudioRegion::set_fade_in (FadeShape shape, samplecnt_t len)
break;
case FadeConstantPower:
_fade_in->fast_simple_add (0.0, GAIN_COEFF_SMALL);
_fade_in->fast_simple_add (timepos_t (Temporal::AudioTime), GAIN_COEFF_SMALL);
for (int i = 1; i < num_steps; ++i) {
const float dist = i / (num_steps + 1.f);
_fade_in->fast_simple_add (len * dist, sin (dist * M_PI / 2.0));
_fade_in->fast_simple_add (timepos_t (len * dist), sin (dist * M_PI / 2.0));
}
_fade_in->fast_simple_add (len, GAIN_COEFF_UNITY);
_fade_in->fast_simple_add (timepos_t (len), GAIN_COEFF_UNITY);
reverse_curve (_inverse_fade_in.val(), _fade_in.val());
break;
case FadeSymmetric:
//start with a nearly linear cuve
_fade_in->fast_simple_add (0, 1);
_fade_in->fast_simple_add (0.5 * len, 0.6);
_fade_in->fast_simple_add (timepos_t (Temporal::AudioTime), 1);
_fade_in->fast_simple_add (timepos_t (0.5 * len), 0.6);
//now generate a fade-out curve by successively applying a gain drop
const double breakpoint = 0.7; //linear for first 70%
for (int i = 2; i < 9; ++i) {
const float coeff = (1.f - breakpoint) * powf (0.5, i);
_fade_in->fast_simple_add (len * (breakpoint + ((GAIN_COEFF_UNITY - breakpoint) * (double)i / 9.0)), coeff);
_fade_in->fast_simple_add (timepos_t (len * (breakpoint + ((GAIN_COEFF_UNITY - breakpoint) * (double)i / 9.0))), coeff);
}
_fade_in->fast_simple_add (len, GAIN_COEFF_SMALL);
_fade_in->fast_simple_add (timepos_t (len), GAIN_COEFF_SMALL);
reverse_curve (c3, _fade_in.val());
_fade_in->copy_events (*c3);
reverse_curve (_inverse_fade_in.val(), _fade_in.val());
@ -1101,8 +1104,8 @@ void
AudioRegion::set_fade_out (FadeShape shape, samplecnt_t len)
{
const ARDOUR::ParameterDescriptor desc(FadeOutAutomation);
boost::shared_ptr<Evoral::ControlList> c1 (new Evoral::ControlList (FadeOutAutomation, desc));
boost::shared_ptr<Evoral::ControlList> c2 (new Evoral::ControlList (FadeOutAutomation, desc));
boost::shared_ptr<Evoral::ControlList> c1 (new Evoral::ControlList (FadeOutAutomation, desc, Temporal::AudioTime));
boost::shared_ptr<Evoral::ControlList> c2 (new Evoral::ControlList (FadeOutAutomation, desc, Temporal::AudioTime));
_fade_out->freeze ();
_fade_out->clear ();
@ -1112,8 +1115,8 @@ AudioRegion::set_fade_out (FadeShape shape, samplecnt_t len)
switch (shape) {
case FadeLinear:
_fade_out->fast_simple_add (0.0, GAIN_COEFF_UNITY);
_fade_out->fast_simple_add (len, GAIN_COEFF_SMALL);
_fade_out->fast_simple_add (timepos_t (Temporal::AudioTime), GAIN_COEFF_UNITY);
_fade_out->fast_simple_add (timepos_t (len), GAIN_COEFF_SMALL);
reverse_curve (_inverse_fade_out.val(), _fade_out.val());
break;
@ -1132,26 +1135,26 @@ AudioRegion::set_fade_out (FadeShape shape, samplecnt_t len)
case FadeConstantPower:
//constant-power fades use a sin/cos relationship
//the cutoff is abrupt but it has the benefit of being symmetrical
_fade_out->fast_simple_add (0.0, GAIN_COEFF_UNITY);
_fade_out->fast_simple_add (timepos_t (Temporal::AudioTime), GAIN_COEFF_UNITY);
for (int i = 1; i < num_steps; ++i) {
const float dist = i / (num_steps + 1.f);
_fade_out->fast_simple_add (len * dist, cos (dist * M_PI / 2.0));
_fade_out->fast_simple_add (timepos_t (len * dist), cos (dist * M_PI / 2.0));
}
_fade_out->fast_simple_add (len, GAIN_COEFF_SMALL);
_fade_out->fast_simple_add (timepos_t (len), GAIN_COEFF_SMALL);
reverse_curve (_inverse_fade_out.val(), _fade_out.val());
break;
case FadeSymmetric:
//start with a nearly linear cuve
_fade_out->fast_simple_add (0, 1);
_fade_out->fast_simple_add (0.5 * len, 0.6);
_fade_out->fast_simple_add (timepos_t (Temporal::AudioTime), 1);
_fade_out->fast_simple_add (timepos_t (0.5 * len), 0.6);
//now generate a fade-out curve by successively applying a gain drop
const double breakpoint = 0.7; //linear for first 70%
for (int i = 2; i < 9; ++i) {
const float coeff = (1.f - breakpoint) * powf (0.5, i);
_fade_out->fast_simple_add (len * (breakpoint + ((GAIN_COEFF_UNITY - breakpoint) * (double)i / 9.0)), coeff);
_fade_out->fast_simple_add (timepos_t (len * (breakpoint + ((GAIN_COEFF_UNITY - breakpoint) * (double)i / 9.0))), coeff);
}
_fade_out->fast_simple_add (len, GAIN_COEFF_SMALL);
_fade_out->fast_simple_add (timepos_t (len), GAIN_COEFF_SMALL);
reverse_curve (_inverse_fade_out.val(), _fade_out.val());
break;
}
@ -1167,19 +1170,19 @@ AudioRegion::set_fade_out (FadeShape shape, samplecnt_t len)
void
AudioRegion::set_fade_in_length (samplecnt_t len)
{
if (len > _length) {
len = _length - 1;
if (len > length_samples()) {
len = length_samples() - 1;
}
if (len < 64) {
len = 64;
}
bool changed = _fade_in->extend_to (len);
bool changed = _fade_in->extend_to (timepos_t (len));
if (changed) {
if (_inverse_fade_in) {
_inverse_fade_in->extend_to (len);
_inverse_fade_in->extend_to (timepos_t (len));
}
_default_fade_in = false;
@ -1190,20 +1193,20 @@ AudioRegion::set_fade_in_length (samplecnt_t len)
void
AudioRegion::set_fade_out_length (samplecnt_t len)
{
if (len > _length) {
len = _length - 1;
if (len > length_samples()) {
len = length_samples() - 1;
}
if (len < 64) {
len = 64;
}
bool changed = _fade_out->extend_to (len);
bool changed = _fade_out->extend_to (timepos_t (len));
if (changed) {
if (_inverse_fade_out) {
_inverse_fade_out->extend_to (len);
_inverse_fade_out->extend_to (timepos_t (len));
}
_default_fade_out = false;
@ -1270,8 +1273,8 @@ AudioRegion::set_default_envelope ()
{
_envelope->freeze ();
_envelope->clear ();
_envelope->fast_simple_add (0, GAIN_COEFF_UNITY);
_envelope->fast_simple_add (_length, GAIN_COEFF_UNITY);
_envelope->fast_simple_add (timepos_t (Temporal::AudioTime), GAIN_COEFF_UNITY);
_envelope->fast_simple_add (timepos_t (_length), GAIN_COEFF_UNITY);
_envelope->thaw ();
}
@ -1283,7 +1286,7 @@ AudioRegion::recompute_at_end ()
*/
_envelope->freeze ();
_envelope->truncate_end (_length);
_envelope->truncate_end (timepos_t (_length));
_envelope->thaw ();
suspend_property_changes();
@ -1292,12 +1295,12 @@ AudioRegion::recompute_at_end ()
set_default_fade_out ();
_left_of_split = false;
} else if (_fade_out->when(false) > _length) {
_fade_out->extend_to (_length);
_fade_out->extend_to (timepos_t (_length));
send_change (PropertyChange (Properties::fade_out));
}
if (_fade_in->when(false) > _length) {
_fade_in->extend_to (_length);
_fade_in->extend_to (timepos_t (_length));
send_change (PropertyChange (Properties::fade_in));
}
@ -1317,12 +1320,12 @@ AudioRegion::recompute_at_start ()
set_default_fade_in ();
_right_of_split = false;
} else if (_fade_in->when(false) > _length) {
_fade_in->extend_to (_length);
_fade_in->extend_to (timepos_t (_length));
send_change (PropertyChange (Properties::fade_in));
}
if (_fade_out->when(false) > _length) {
_fade_out->extend_to (_length);
_fade_out->extend_to (timepos_t (_length));
send_change (PropertyChange (Properties::fade_out));
}
@ -1396,8 +1399,8 @@ AudioRegion::set_scale_amplitude (gain_t g)
double
AudioRegion::maximum_amplitude (Progress* p) const
{
samplepos_t fpos = _start;
samplepos_t const fend = _start + _length;
samplepos_t fpos = start_sample();;
samplepos_t const fend = start_sample() + length_samples();
double maxamp = 0;
samplecnt_t const blocksize = 64 * 1024;
@ -1422,7 +1425,7 @@ AudioRegion::maximum_amplitude (Progress* p) const
fpos += to_read;
if (p) {
p->set_progress (float (fpos - _start) / _length);
p->set_progress (float (fpos - start_sample()) / length_samples());
if (p->cancelled ()) {
return -1;
}
@ -1435,8 +1438,8 @@ AudioRegion::maximum_amplitude (Progress* p) const
double
AudioRegion::rms (Progress* p) const
{
samplepos_t fpos = _start;
samplepos_t const fend = _start + _length;
samplepos_t fpos = start_sample();
samplepos_t const fend = start_sample() + length_samples();
uint32_t const n_chan = n_channels ();
double rms = 0;
@ -1462,7 +1465,7 @@ AudioRegion::rms (Progress* p) const
total += to_read;
fpos += to_read;
if (p) {
p->set_progress (float (fpos - _start) / _length);
p->set_progress (float (fpos - start_sample()) / length_samples());
if (p->cancelled ()) {
return -1;
}
@ -1633,13 +1636,13 @@ AudioRegion::add_transient (samplepos_t where)
if (where < first_sample () || where >= last_sample ()) {
return;
}
where -= _position;
where -= position_sample();
if (!_valid_transients) {
_transient_user_start = _start;
_transient_user_start = start_sample();
_valid_transients = true;
}
sampleoffset_t offset = _transient_user_start - _start;
sampleoffset_t offset = _transient_user_start - start_sample();;
if (where < offset) {
if (offset <= 0) {
@ -1663,16 +1666,16 @@ AudioRegion::update_transient (samplepos_t old_position, samplepos_t new_positio
{
bool changed = false;
if (!_onsets.empty ()) {
const samplepos_t p = old_position - _position;
const samplepos_t p = old_position - position_sample();
AnalysisFeatureList::iterator x = std::find (_onsets.begin (), _onsets.end (), p);
if (x != _transients.end ()) {
(*x) = new_position - _position;
(*x) = new_position - position_sample();
changed = true;
}
}
if (_valid_transients) {
const sampleoffset_t offset = _position + _transient_user_start - _start;
const sampleoffset_t offset = position_sample() + _transient_user_start - start_sample();
const samplepos_t p = old_position - offset;
AnalysisFeatureList::iterator x = std::find (_user_transients.begin (), _user_transients.end (), p);
if (x != _transients.end ()) {
@ -1691,7 +1694,7 @@ AudioRegion::remove_transient (samplepos_t where)
{
bool changed = false;
if (!_onsets.empty ()) {
const samplepos_t p = where - _position;
const samplepos_t p = where - position_sample();
AnalysisFeatureList::iterator i = std::find (_onsets.begin (), _onsets.end (), p);
if (i != _onsets.end ()) {
_onsets.erase (i);
@ -1700,7 +1703,7 @@ AudioRegion::remove_transient (samplepos_t where)
}
if (_valid_transients) {
const samplepos_t p = where - (_position + _transient_user_start - _start);
const samplepos_t p = where - (position_sample() + _transient_user_start - start_sample());
AnalysisFeatureList::iterator i = std::find (_user_transients.begin (), _user_transients.end (), p);
if (i != _user_transients.end ()) {
_user_transients.erase (i);
@ -1751,11 +1754,11 @@ AudioRegion::build_transients ()
/* find the set of transients within the bounds of this region */
AnalysisFeatureList::iterator low = lower_bound ((*s)->transients.begin(),
(*s)->transients.end(),
_start);
start_sample());
AnalysisFeatureList::iterator high = upper_bound ((*s)->transients.begin(),
(*s)->transients.end(),
_start + _length);
start_sample() + length_samples());
/* and add them */
_transients.insert (_transients.end(), low, high);
@ -1765,11 +1768,11 @@ AudioRegion::build_transients ()
/* translate all transients to current position */
for (AnalysisFeatureList::iterator x = _transients.begin(); x != _transients.end(); ++x) {
(*x) -= _start;
(*x) -= start_sample();
}
_transient_analysis_start = _start;
_transient_analysis_end = _start + _length;
_transient_analysis_start = start_sample();
_transient_analysis_end = start_sample() + length_samples();
return;
}
@ -1816,8 +1819,8 @@ in this and future transient-detection operations.\n\
}
TransientDetector::cleanup_transients (_transients, pl->session().sample_rate(), 3.0);
_transient_analysis_start = _start;
_transient_analysis_end = _start + _length;
_transient_analysis_start = start_sample();
_transient_analysis_end = start_sample() + length_samples();
}
/* Transient analysis uses ::read() which is relative to _start,
@ -1846,21 +1849,21 @@ AudioRegion::get_transients (AnalysisFeatureList& results)
return;
}
Region::merge_features (results, _user_transients, _position + _transient_user_start - _start);
Region::merge_features (results, _user_transients, position_sample() + _transient_user_start - start_sample());
if (!_onsets.empty ()) {
// onsets are invalidated when start or length changes
merge_features (results, _onsets, _position);
merge_features (results, _onsets, position_sample());
return;
}
if ((_transient_analysis_start == _transient_analysis_end)
|| _transient_analysis_start > _start
|| _transient_analysis_end < _start + _length) {
|| _transient_analysis_start > start_sample()
|| _transient_analysis_end < start_sample() + length_samples()) {
build_transients ();
}
merge_features (results, _transients, _position + _transient_analysis_start - _start);
merge_features (results, _transients, position_sample() + _transient_analysis_start - start_sample());
}
/** Find areas of `silence' within a region.
@ -1880,13 +1883,13 @@ AudioRegion::find_silence (Sample threshold, samplecnt_t min_length, samplecnt_t
assert (fade_length >= 0);
assert (min_length > 0);
samplepos_t pos = _start;
samplepos_t const end = _start + _length;
samplepos_t pos = start_sample();
samplepos_t const end = start_sample() + length_samples();
AudioIntervalResult silent_periods;
bool in_silence = true;
sampleoffset_t silence_start = _start;
sampleoffset_t silence_start = start_sample();
while (pos < end && !itt.cancel) {
@ -1922,7 +1925,7 @@ AudioRegion::find_silence (Sample threshold, samplecnt_t min_length, samplecnt_t
}
pos += cur_samples;
itt.progress = (end - pos) / (double)_length;
itt.progress = (end - pos) / (double) length_samples();
if (cur_samples == 0) {
assert (pos >= end);
@ -1942,10 +1945,10 @@ AudioRegion::find_silence (Sample threshold, samplecnt_t min_length, samplecnt_t
return silent_periods;
}
Evoral::Range<samplepos_t>
Temporal::Range
AudioRegion::body_range () const
{
return Evoral::Range<samplepos_t> (first_sample() + _fade_in->when(false) + 1, last_sample() - _fade_out->when(false));
return Temporal::Range ((nt_position() + _fade_in->back()->when).increment(), nt_end().earlier (_fade_out->back()->when));
}
boost::shared_ptr<Region>
@ -1963,9 +1966,9 @@ AudioRegion::get_single_other_xfade_region (bool start) const
boost::shared_ptr<RegionList> rl;
if (start) {
rl = pl->regions_at (position());
rl = pl->regions_at (nt_position());
} else {
rl = pl->regions_at (last_sample());
rl = pl->regions_at (nt_last());
}
RegionList::iterator i;
@ -2005,7 +2008,7 @@ AudioRegion::verify_xfade_bounds (samplecnt_t len, bool start)
/* zero or > 2 regions here, don't care about len, but
it can't be longer than the region itself.
*/
return min (length(), len);
return min (length_samples(), len);
}
/* we overlap a single region. clamp the length of an xfade to
@ -2014,12 +2017,11 @@ AudioRegion::verify_xfade_bounds (samplecnt_t len, bool start)
*/
if (start) {
maxlen = other->latest_possible_sample() - position();
maxlen = other->latest_possible_sample() - position_sample();
} else {
maxlen = last_sample() - other->earliest_possible_position();
maxlen = last_sample() - other->earliest_possible_position().samples();
}
return min (length(), min (maxlen, len));
return min (length_samples(), min (maxlen, len));
}

View File

@ -81,7 +81,6 @@ bool AudioSource::_build_peakfiles = false;
AudioSource::AudioSource (Session& s, const string& name)
: Source (s, DataType::AUDIO, name)
, _length (0)
, _peak_byte_max (0)
, _peaks_built (false)
, _peakfile_fd (-1)
@ -98,7 +97,6 @@ AudioSource::AudioSource (Session& s, const string& name)
AudioSource::AudioSource (Session& s, const XMLNode& node)
: Source (s, node)
, _length (0)
, _peak_byte_max (0)
, _peaks_built (false)
, _peakfile_fd (-1)
@ -151,20 +149,8 @@ AudioSource::set_state (const XMLNode& node, int /*version*/)
return 0;
}
bool
AudioSource::empty () const
{
return _length == 0;
}
samplecnt_t
AudioSource::length (samplepos_t /*pos*/) const
{
return _length;
}
void
AudioSource::update_length (samplecnt_t len)
AudioSource::update_length (timecnt_t const & len)
{
if (len > _length) {
_length = len;
@ -271,7 +257,7 @@ AudioSource::initialize_peakfile (const string& audio_path, const bool in_sessio
/* we found it in the peaks dir, so check it out */
if (statbuf.st_size == 0 || (statbuf.st_size < (off_t) ((length(_natural_position) / _FPP) * sizeof (PeakData)))) {
if (statbuf.st_size == 0 || (statbuf.st_size < (off_t) ((length().samples() / _FPP) * sizeof (PeakData)))) {
DEBUG_TRACE(DEBUG::Peaks, string_compose("Peakfile %1 is empty\n", _peakpath));
_peaks_built = false;
} else {
@ -425,7 +411,7 @@ AudioSource::read_peaks_with_fpp (PeakData *peaks, samplecnt_t npeaks, samplepos
*
*/
const off_t expected_file_size = (_length / (double) samples_per_file_peak) * sizeof (PeakData);
const off_t expected_file_size = (_length.samples() / (double) samples_per_file_peak) * sizeof (PeakData);
if (statbuf.st_size < expected_file_size) {
warning << string_compose (_("peak file %1 is truncated from %2 to %3"), _peakpath, expected_file_size, statbuf.st_size) << endmsg;
@ -457,9 +443,9 @@ AudioSource::read_peaks_with_fpp (PeakData *peaks, samplecnt_t npeaks, samplepos
/* fix for near-end-of-file conditions */
if (cnt + start > _length) {
if (cnt + start > _length.samples()) {
// cerr << "too close to end @ " << _length << " given " << start << " + " << cnt << " (" << _length - start << ")" << endl;
cnt = std::max ((samplecnt_t)0, _length - start);
cnt = std::max ((samplecnt_t)0, _length.samples() - start);
read_npeaks = min ((samplecnt_t) floor (cnt / samples_per_visual_peak), npeaks);
zero_fill = npeaks - read_npeaks;
expected_peaks = (cnt / (double) samples_per_file_peak);
@ -704,9 +690,9 @@ AudioSource::read_peaks_with_fpp (PeakData *peaks, samplecnt_t npeaks, samplepos
if (i == samples_read) {
to_read = min (chunksize, (samplecnt_t)(_length - current_sample));
to_read = min (chunksize, (samplecnt_t)(_length.samples() - current_sample));
if (current_sample >= _length) {
if (current_sample >= _length.samples()) {
/* hmm, error condition - we've reached the end of the file
* without generating all the peak data. cook up a zero-filled
@ -719,7 +705,7 @@ AudioSource::read_peaks_with_fpp (PeakData *peaks, samplecnt_t npeaks, samplepos
} else {
to_read = min (chunksize, (_length - current_sample));
to_read = min (chunksize, (_length.samples() - current_sample));
if ((samples_read = read_unlocked (raw_staging.get(), current_sample, to_read)) == 0) {
@ -779,7 +765,7 @@ AudioSource::build_peaks_from_scratch ()
}
samplecnt_t current_sample = 0;
samplecnt_t cnt = _length;
samplecnt_t cnt = _length.samples();
_peaks_built = false;
boost::scoped_array<Sample> buf(new Sample[bufsize]);
@ -1112,7 +1098,7 @@ samplecnt_t
AudioSource::available_peaks (double zoom_factor) const
{
if (zoom_factor < _FPP) {
return length(_natural_position); // peak data will come from the audio file
return _length.samples(); // peak data will come from the audio file
}
/* peak data comes from peakfile, but the filesize might not represent

View File

@ -308,16 +308,17 @@ Auditioner::audition_region (boost::shared_ptr<Region> region)
unload_synth (true);
midi_region.reset();
_import_position = 0;
_import_position = timepos_t (Temporal::AudioTime);
/* copy it */
the_region = boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (region, false));
the_region->set_position (0);
the_region->set_position (timepos_t (Temporal::AudioTime));
_disk_reader->midi_playlist()->drop_regions ();
_disk_reader->audio_playlist()->drop_regions ();
_disk_reader->audio_playlist()->add_region (the_region, 0, 1);
_disk_reader->audio_playlist()->add_region (the_region, timepos_t (Temporal::AudioTime), 1);
ProcessorStreams ps;
{
@ -325,7 +326,7 @@ Auditioner::audition_region (boost::shared_ptr<Region> region)
if (configure_processors (&ps)) {
error << string_compose (_("Cannot setup auditioner processing flow for %1 channels"),
region->n_channels()) << endmsg;
region->sources().size()) << endmsg;
return;
}
}
@ -334,7 +335,7 @@ Auditioner::audition_region (boost::shared_ptr<Region> region)
_midi_audition = true;
the_region.reset();
_import_position = region->position();
_import_position = region->nt_position();
/* copy it */
midi_region = (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (region, false)));
@ -362,7 +363,7 @@ Auditioner::audition_region (boost::shared_ptr<Region> region)
if (configure_processors (&ps)) {
error << string_compose (_("Cannot setup auditioner processing flow for %1 channels"),
region->n_channels()) << endmsg;
region->sources().size()) << endmsg;
unload_synth (true);
return;
}
@ -380,13 +381,13 @@ Auditioner::audition_region (boost::shared_ptr<Region> region)
_seeking = false;
int dir;
samplecnt_t offset;
timepos_t offset;
if (_midi_audition) {
length = midi_region->length();
length = midi_region->nt_length();
offset = _import_position + midi_region->sync_offset (dir);
} else {
length = the_region->length();
length = the_region->nt_length();
offset = the_region->sync_offset (dir);
}
@ -402,7 +403,7 @@ Auditioner::audition_region (boost::shared_ptr<Region> region)
offset = 0;
}
_disk_reader->seek (offset, true);
_disk_reader->seek (offset.samples(), true);
if (_midi_audition) {
/* Fill MIDI buffers.
@ -415,7 +416,7 @@ Auditioner::audition_region (boost::shared_ptr<Region> region)
_disk_reader->overwrite_existing_buffers ();
}
current_sample = offset;
current_sample = offset.samples();
g_atomic_int_set (&_auditioning, 1);
}
@ -455,7 +456,7 @@ Auditioner::play_audition (samplecnt_t nframes)
if(!_seeking) {
/* process audio */
this_nframes = min (nframes, length - current_sample + _import_position);
this_nframes = min (nframes, length.samples() - current_sample + _import_position.samples());
if (this_nframes > 0 && 0 != (ret = roll (this_nframes, current_sample, current_sample + this_nframes, need_butler))) {
silence (nframes);
@ -475,7 +476,7 @@ Auditioner::play_audition (samplecnt_t nframes)
silence (nframes);
}
if (_seek_sample >= 0 && _seek_sample < length && !_seeking) {
if (_seek_sample >= 0 && _seek_sample < length.samples() && !_seeking) {
_queue_panic = true;
_seek_complete = false;
_seeking = true;
@ -483,10 +484,10 @@ Auditioner::play_audition (samplecnt_t nframes)
}
if (!_seeking) {
AuditionProgress(current_sample - _import_position, length); /* emit */
AuditionProgress(current_sample - _import_position.samples(), length.samples()); /* emit */
}
if (current_sample >= length + _import_position) {
if (current_sample >= (length + _import_position).samples()) {
_session.cancel_audition ();
unload_synth (false);
return 0;
@ -515,7 +516,7 @@ Auditioner::seek_to_sample (sampleoffset_t pos) {
void
Auditioner::seek_to_percent (float const pos) {
if (_seek_sample < 0 && !_seeking) {
_seek_sample = floorf(length * pos / 100.0);
_seek_sample = floorf(length.samples() * pos / 100.0);
}
}

View File

@ -22,6 +22,8 @@
*/
#include <cstdio>
#include <fstream>
#include <errno.h>
#include "pbd/gstdio_compat.h"
@ -29,6 +31,8 @@
#include "pbd/error.h"
#include "temporal/timeline.h"
#include "ardour/amp.h"
#include "ardour/automatable.h"
#include "ardour/event_type_map.h"
@ -116,9 +120,9 @@ Automatable::load_automation (const string& path)
fullpath += path;
}
FILE * in = g_fopen (fullpath.c_str (), "rb");
std::ifstream in (fullpath);
if (!in) {
if (in.bad()) {
warning << string_compose(_("cannot open %2 to load automation data (%3)")
, fullpath, strerror (errno)) << endmsg;
return 1;
@ -128,17 +132,14 @@ Automatable::load_automation (const string& path)
set<Evoral::Parameter> tosave;
controls().clear ();
while (!feof(in)) {
double when;
while (!in.eof()) {
Temporal::timepos_t when;
double value;
uint32_t port;
if (3 != fscanf (in, "%d %lf %lf", &port, &when, &value)) {
if (feof(in)) {
break;
}
goto bad;
}
in >> port; if (in.bad()) { goto bad; }
in >> when; if (in.bad()) { goto bad; }
in >> value; if (in.bad()) { goto bad; }
Evoral::Parameter param(PluginAutomation, 0, port);
/* FIXME: this is legacy and only used for plugin inserts? I think? */
@ -146,14 +147,12 @@ Automatable::load_automation (const string& path)
c->list()->add (when, value);
tosave.insert (param);
}
::fclose (in);
return 0;
bad:
error << string_compose(_("cannot load automation data from %2"), fullpath) << endmsg;
controls().clear ();
::fclose (in);
return -1;
}
@ -404,23 +403,24 @@ Automatable::non_realtime_locate (samplepos_t now)
* compare to compare to non_realtime_transport_stop()
*/
const bool list_did_write = !l->in_new_write_pass ();
c->stop_touch (-1); // time is irrelevant
l->stop_touch (-1);
#warning NUTEMPO check use of domain in arbitrary irrelevant time
c->stop_touch (timepos_t::zero (Temporal::AudioTime)); // time is irrelevant
l->stop_touch (timepos_t::zero (Temporal::AudioTime));
c->commit_transaction (list_did_write);
l->write_pass_finished (now, Config->get_automation_thinning_factor ());
l->write_pass_finished (timepos_t (now), Config->get_automation_thinning_factor ());
if (l->automation_state () == Write) {
l->set_automation_state (Touch);
}
if (l->automation_playback ()) {
c->set_value_unchecked (c->list ()->eval (now));
c->set_value_unchecked (c->list ()->eval (timepos_t (now)));
}
}
l->start_write_pass (now);
l->start_write_pass (timepos_t (now));
if (rolling && am_touching) {
c->start_touch (now);
c->start_touch (timepos_t (now));
}
}
}
@ -450,19 +450,19 @@ Automatable::non_realtime_transport_stop (samplepos_t now, bool /*flush_processo
*/
const bool list_did_write = !l->in_new_write_pass ();
c->stop_touch (now);
l->stop_touch (now);
c->stop_touch (timepos_t (now));
l->stop_touch (timepos_t (now));
c->commit_transaction (list_did_write);
l->write_pass_finished (now, Config->get_automation_thinning_factor ());
l->write_pass_finished (timepos_t (now), Config->get_automation_thinning_factor ());
if (l->automation_state () == Write) {
l->set_automation_state (Touch);
}
if (l->automation_playback ()) {
c->set_value_unchecked (c->list ()->eval (now));
c->set_value_unchecked (c->list ()->eval (timepos_t (now)));
}
}
}
@ -547,7 +547,7 @@ Automatable::control_factory(const Evoral::Parameter& param)
if (!Variant::type_is_numeric(desc.datatype)) {
make_list = false; // Can't automate non-numeric data yet
} else {
list = boost::shared_ptr<AutomationList>(new AutomationList(param, desc));
list = boost::shared_ptr<AutomationList>(new AutomationList(param, desc, Temporal::AudioTime));
}
control = new PluginInsert::PluginPropertyControl(pi, param, desc, list);
}
@ -593,7 +593,8 @@ Automatable::control_factory(const Evoral::Parameter& param)
}
if (make_list && !list) {
list = boost::shared_ptr<AutomationList>(new AutomationList(param, desc));
#warning NUTEMPO what time domain to use here?
list = boost::shared_ptr<AutomationList>(new AutomationList(param, desc, Temporal::AudioTime));
}
if (!control) {
@ -638,7 +639,7 @@ Automatable::clear_controls ()
}
bool
Automatable::find_next_event (double start, double end, Evoral::ControlEvent& next_event, bool only_active) const
Automatable::find_next_event (timepos_t const & start, timepos_t const & end, Evoral::ControlEvent& next_event, bool only_active) const
{
next_event.when = start <= end ? std::numeric_limits<double>::max() : 0;
@ -670,7 +671,7 @@ Automatable::find_next_event (double start, double end, Evoral::ControlEvent& ne
}
void
Automatable::find_next_ac_event (boost::shared_ptr<AutomationControl> c, double start, double end, Evoral::ControlEvent& next_event) const
Automatable::find_next_ac_event (boost::shared_ptr<AutomationControl> c, timepos_t const & start, timepos_t const & end, Evoral::ControlEvent& next_event) const
{
assert (start <= end);
@ -697,7 +698,7 @@ Automatable::find_next_ac_event (boost::shared_ptr<AutomationControl> c, double
}
void
Automatable::find_prev_ac_event (boost::shared_ptr<AutomationControl> c, double start, double end, Evoral::ControlEvent& next_event) const
Automatable::find_prev_ac_event (boost::shared_ptr<AutomationControl> c, timepos_t const & start, timepos_t const & end, Evoral::ControlEvent& next_event) const
{
assert (start > end);
boost::shared_ptr<SlavableAutomationControl> sc

View File

@ -100,7 +100,7 @@ double
AutomationControl::get_value() const
{
bool from_list = alist() && alist()->automation_playback();
return Control::get_double (from_list, _session.transport_sample());
return Control::get_double (from_list, timepos_t (_session.transport_sample()));
}
double
@ -128,7 +128,7 @@ AutomationControl::set_value (double val, PBD::Controllable::GroupControlDisposi
}
if (_list && !touching () && alist()->automation_state() == Latch && _session.transport_rolling ()) {
start_touch (_session.transport_sample ());
start_touch (timepos_t (_session.transport_sample ()));
}
/* enforce strict double/boolean value mapping */
@ -170,7 +170,7 @@ AutomationControl::automation_run (samplepos_t start, pframes_t nframes)
assert (_list);
bool valid = false;
double val = _list->rt_safe_eval (start, valid);
double val = _list->rt_safe_eval (timepos_t (start), valid);
if (!valid) {
return;
}
@ -216,7 +216,7 @@ AutomationControl::actually_set_value (double value, PBD::Controllable::GroupCon
to_list = false;
}
Control::set_double (value, pos, to_list);
Control::set_double (value, timepos_t (pos), to_list);
if (old_value != (float)value) {
#if 0
@ -254,9 +254,10 @@ AutomationControl::set_automation_state (AutoState as)
if (as == Write) {
AutomationWatch::instance().add_automation_watch (boost::dynamic_pointer_cast<AutomationControl>(shared_from_this()));
} else if (as & (Touch | Latch)) {
#warning NUTEMPO fixme timestamps here are always in samples ... should match list time domain
if (alist()->empty()) {
Control::set_double (val, _session.current_start_sample (), true);
Control::set_double (val, _session.current_end_sample (), true);
Control::set_double (val, timepos_t (_session.current_start_sample ()), true);
Control::set_double (val, timepos_t (_session.current_end_sample ()), true);
Changed (true, Controllable::NoGroup);
}
if (!touching()) {
@ -277,7 +278,7 @@ AutomationControl::set_automation_state (AutoState as)
}
void
AutomationControl::start_touch (double when)
AutomationControl::start_touch (timepos_t const & when)
{
if (!_list || touching ()) {
return;
@ -300,7 +301,7 @@ AutomationControl::start_touch (double when)
}
void
AutomationControl::stop_touch (double when)
AutomationControl::stop_touch (timepos_t const & when)
{
if (!_list || !touching ()) {
return;

View File

@ -28,6 +28,8 @@
#include <sstream>
#include <algorithm>
#include "temporal/types_convert.h"
#include "ardour/automation_list.h"
#include "ardour/beats_samples_converter.h"
#include "ardour/event_type_map.h"
@ -60,8 +62,8 @@ static void dumpit (const AutomationList& al, string prefix = "")
cerr << "\n";
}
#endif
AutomationList::AutomationList (const Evoral::Parameter& id, const Evoral::ParameterDescriptor& desc)
: ControlList(id, desc)
AutomationList::AutomationList (const Evoral::Parameter& id, const Evoral::ParameterDescriptor& desc, Temporal::TimeDomain time_domain)
: ControlList(id, desc, time_domain)
, _before (0)
{
_state = Off;
@ -74,8 +76,8 @@ AutomationList::AutomationList (const Evoral::Parameter& id, const Evoral::Param
AutomationListCreated(this);
}
AutomationList::AutomationList (const Evoral::Parameter& id)
: ControlList(id, ARDOUR::ParameterDescriptor(id))
AutomationList::AutomationList (const Evoral::Parameter& id, Temporal::TimeDomain time_domain)
: ControlList(id, ARDOUR::ParameterDescriptor(id), time_domain)
, _before (0)
{
_state = Off;
@ -102,7 +104,7 @@ AutomationList::AutomationList (const AutomationList& other)
AutomationListCreated(this);
}
AutomationList::AutomationList (const AutomationList& other, double start, double end)
AutomationList::AutomationList (const AutomationList& other, timepos_t const & start, timepos_t const & end)
: ControlList(other, start, end)
, _before (0)
{
@ -119,7 +121,7 @@ AutomationList::AutomationList (const AutomationList& other, double start, doubl
* in or below the AutomationList node. It is used if @param id is non-null.
*/
AutomationList::AutomationList (const XMLNode& node, Evoral::Parameter id)
: ControlList(id, ARDOUR::ParameterDescriptor(id))
: ControlList(id, ARDOUR::ParameterDescriptor(id), Temporal::AudioTime) /* domain may change in ::set_state */
, _before (0)
{
g_atomic_int_set (&_touching, 0);
@ -145,9 +147,10 @@ AutomationList::~AutomationList()
boost::shared_ptr<Evoral::ControlList>
AutomationList::create(const Evoral::Parameter& id,
const Evoral::ParameterDescriptor& desc)
const Evoral::ParameterDescriptor& desc,
Temporal::TimeDomain time_domain)
{
return boost::shared_ptr<Evoral::ControlList>(new AutomationList(id, desc));
return boost::shared_ptr<Evoral::ControlList>(new AutomationList(id, desc, time_domain));
}
void
@ -245,20 +248,20 @@ AutomationList::default_interpolation () const
}
void
AutomationList::start_write_pass (double when)
AutomationList::start_write_pass (timepos_t const & when)
{
snapshot_history (true);
ControlList::start_write_pass (when);
}
void
AutomationList::write_pass_finished (double when, double thinning_factor)
AutomationList::write_pass_finished (timepos_t const & when, double thinning_factor)
{
ControlList::write_pass_finished (when, thinning_factor);
}
void
AutomationList::start_touch (double when)
AutomationList::start_touch (timepos_t const & when)
{
if (_state == Touch) {
start_write_pass (when);
@ -268,7 +271,7 @@ AutomationList::start_touch (double when)
}
void
AutomationList::stop_touch (double)
AutomationList::stop_touch (timepos_t const & /* not used */)
{
if (g_atomic_int_get (&_touching) == 0) {
/* this touch has already been stopped (probably by Automatable::transport_stopped),
@ -315,26 +318,27 @@ AutomationList::thaw ()
}
bool
AutomationList::paste (const ControlList& alist, double pos, BeatsSamplesConverter const& bfc)
AutomationList::paste (const ControlList& alist, timepos_t const & pos, BeatsSamplesConverter const& bfc)
{
AutomationType src_type = (AutomationType)alist.parameter().type();
AutomationType dst_type = (AutomationType)_parameter.type();
if (parameter_is_midi (src_type) == parameter_is_midi (dst_type)) {
if (time_domain() == alist.time_domain()) {
return ControlList::paste (alist, pos);
}
bool to_sample = parameter_is_midi (src_type);
/* time domains differ - need to map the time of all points in alist
* into our time domain
*/
const bool to_sample = (time_domain() == Temporal::AudioTime);
ControlList cl (alist);
cl.clear ();
for (const_iterator i = alist.begin ();i != alist.end (); ++i) {
double when = (*i)->when;
if (to_sample) {
when = bfc.to (Temporal::Beats::from_double ((*i)->when));
cl.fast_simple_add (timepos_t ((*i)->when.samples()), (*i)->value);
} else {
when = bfc.from ((*i)->when).to_double ();
cl.fast_simple_add (timepos_t ((*i)->when.beats ()), (*i)->value);
}
cl.fast_simple_add (when, (*i)->value);
}
return ControlList::paste (cl, pos);
}
@ -359,6 +363,7 @@ AutomationList::state (bool save_auto_state, bool need_lock)
root->set_property ("automation-id", EventTypeMap::instance().to_symbol(_parameter));
root->set_property ("id", id());
root->set_property ("interpolation-style", _interpolation);
root->set_property ("time-domain", enum_2_string (time_domain()));
if (save_auto_state) {
/* never serialize state with Write enabled - too dangerous
@ -432,13 +437,13 @@ AutomationList::deserialize_events (const XMLNode& node)
std::string x_str;
std::string y_str;
double x;
timepos_t x;
double y;
bool ok = true;
while (str) {
str >> x_str;
if (!str || !PBD::string_to<double> (x_str, x)) {
if (!str || !PBD::string_to<timepos_t> (x_str, x)) {
break;
}
str >> y_str;
@ -469,6 +474,11 @@ AutomationList::set_state (const XMLNode& node, int version)
XMLNodeList nlist = node.children();
XMLNode* nsos;
XMLNodeIterator niter;
Temporal::TimeDomain time_domain;
if (node.get_property ("time-domain", time_domain)) {
set_time_domain (time_domain);
}
if (node.name() == X_("events")) {
/* partial state setting*/
@ -505,7 +515,7 @@ AutomationList::set_state (const XMLNode& node, int version)
}
y = std::min ((double)_desc.upper, std::max ((double)_desc.lower, y));
fast_simple_add (x, y);
fast_simple_add (timepos_t (x), y);
}
thaw ();

View File

@ -87,7 +87,8 @@ AutomationWatch::add_automation_watch (boost::shared_ptr<AutomationControl> ac)
DEBUG_TRACE (DEBUG::Automation, string_compose ("\ttransport is rolling @ %1, audible = %2so enter write pass\n",
_session->transport_speed(), _session->audible_sample()));
/* add a guard point since we are already moving */
ac->list()->set_in_write_pass (true, true, _session->audible_sample());
#warning NUTEMPO QUESTION should the time be in the domain of the list ?
ac->list()->set_in_write_pass (true, true, timepos_t (_session->audible_sample()));
}
/* we can't store shared_ptr<Destructible> in connections because it
@ -142,7 +143,7 @@ AutomationWatch::transport_stop_automation_watches (samplepos_t when)
}
for (AutomationWatches::iterator i = tmp.begin(); i != tmp.end(); ++i) {
(*i)->stop_touch (when);
(*i)->stop_touch (timepos_t (when));
}
}
@ -165,7 +166,7 @@ AutomationWatch::timer ()
if (sc) {
val = sc->reduce_by_masters (val, true);
}
(*aw)->list()->add (time, val, true);
(*aw)->list()->add (timepos_t (time), val, true);
}
}
} else if (time != _last_time) { //transport stopped or reversed. stop the automation pass and start a new one (for bonus points, someday store the previous pass in an undo record)
@ -175,7 +176,7 @@ AutomationWatch::timer ()
(*aw)->alist()->automation_write()));
(*aw)->list()->set_in_write_pass (false);
if ( (*aw)->alist()->automation_write() ) {
(*aw)->list()->set_in_write_pass (true, true, time);
(*aw)->list()->set_in_write_pass (true, true, timepos_t (time));
}
}
}

View File

@ -18,16 +18,17 @@
#include "pbd/stacktrace.h"
#include "temporal/tempo.h"
#include "ardour/beats_samples_converter.h"
#include "ardour/tempo.h"
namespace ARDOUR {
/** Takes a positive duration in quarter-note beats and considers it as a distance from the origin
* supplied to the constructor. Returns the equivalent number of samples,
* supplied to the constructor. Returns the equivalent number of samples,
* taking tempo changes into account.
*/
samplepos_t
samplecnt_t
BeatsSamplesConverter::to (Temporal::Beats beats) const
{
if (beats < Temporal::Beats()) {
@ -35,37 +36,17 @@ BeatsSamplesConverter::to (Temporal::Beats beats) const
PBD::stacktrace (std::cerr, 30);
return 0;
}
return _tempo_map.samplepos_plus_qn (_origin_b, beats) - _origin_b;
return _tempo_map.sample_quarters_delta_as_samples (_origin, beats) - _origin;
}
/** Takes a duration in samples and considers it as a distance from the origin
* supplied to the constructor. Returns the equivalent number of quarter-note beats,
/** Takes a positive duration in superclocks and considers it as a distance from the origin
* supplied to the constructor. Returns the equivalent number of quarter-note beats,
* taking tempo changes into account.
*
* Distance must be positive because we assume we are walking forward from our origin.
*/
Temporal::Beats
BeatsSamplesConverter::from (samplepos_t samples) const
BeatsSamplesConverter::from (samplecnt_t distance) const
{
return _tempo_map.framewalk_to_qn (_origin_b, samples);
return _tempo_map.sample_delta_as_quarters (_origin, distance);
}
/** As above, but with quarter-note beats in double instead (for GUI). */
samplepos_t
DoubleBeatsSamplesConverter::to (double beats) const
{
if (beats < 0.0) {
std::cerr << "negative beats passed to BFC: " << beats << std::endl;
PBD::stacktrace (std::cerr, 30);
return 0;
}
return _tempo_map.samplepos_plus_qn (_origin_b, Temporal::Beats(beats)) - _origin_b;
}
/** As above, but with quarter-note beats in double instead (for GUI). */
double
DoubleBeatsSamplesConverter::from (samplepos_t samples) const
{
return _tempo_map.framewalk_to_qn (_origin_b, samples).to_double();
}
} /* namespace ARDOUR */

View File

@ -56,7 +56,7 @@ bool
Convolution::add_impdata (
uint32_t c_in,
uint32_t c_out,
boost::shared_ptr<Readable> readable,
boost::shared_ptr<AudioReadable> readable,
float gain,
uint32_t pre_delay,
sampleoffset_t offset,
@ -66,7 +66,7 @@ Convolution::add_impdata (
if (_configured || c_in >= _n_inputs || c_out >= _n_outputs) {
return false;
}
if (!readable || readable->readable_length () <= offset || readable->n_channels () <= channel) {
if (!readable || readable->readable_length_samples () <= offset || readable->n_channels () <= channel) {
return false;
}
@ -104,7 +104,7 @@ Convolution::restart ()
_max_size = 0;
for (std::vector<ImpData>::const_iterator i = _impdata.begin (); i != _impdata.end (); ++i) {
_max_size = std::max (_max_size, (uint32_t)i->readable_length ());
_max_size = std::max (_max_size, (uint32_t)i->readable_length_samples ());
}
int rv = _convproc.configure (
@ -121,7 +121,7 @@ Convolution::restart ()
const float ir_gain = i->gain;
const uint32_t ir_delay = i->delay;
const uint32_t ir_len = i->readable_length ();
const uint32_t ir_len = i->readable_length_samples ();
while (true) {
float ir[8192];
@ -235,14 +235,14 @@ Convolver::Convolver (
{
_threaded = true;
std::vector<boost::shared_ptr<Readable> > readables = Readable::load (_session, path);
std::vector<boost::shared_ptr<AudioReadable> > readables = AudioReadable::load (_session, path);
if (readables.empty ()) {
PBD::error << string_compose (_("Convolver: IR \"%1\" no usable audio-channels sound."), path) << endmsg;
throw failed_constructor ();
}
if (readables[0]->readable_length () > 0x1000000 /*2^24*/) {
if (readables[0]->readable_length_samples () > 0x1000000 /*2^24*/) {
PBD::error << string_compose (_("Convolver: IR \"%1\" file too long."), path) << endmsg;
throw failed_constructor ();
}
@ -297,7 +297,7 @@ Convolver::Convolver (
io_i = (c / n_outputs ()) % n_inputs ();
}
boost::shared_ptr<Readable> r = readables[ir_c];
boost::shared_ptr<AudioReadable> r = readables[ir_c];
assert (r->n_channels () == 1);
const float chan_gain = _ir_settings.gain * _ir_settings.channel_gain[c];

View File

@ -349,14 +349,14 @@ DiskIOProcessor::ChannelInfo::~ChannelInfo ()
*/
void
DiskIOProcessor::get_location_times(const Location* location,
samplepos_t* start,
samplepos_t* end,
samplepos_t* length)
timepos_t* start,
timepos_t* end,
timecnt_t* length)
{
if (location) {
*start = location->start();
*end = location->end();
*length = *end - *start;
*length = location->length();
}
}

View File

@ -23,7 +23,7 @@
#include "pbd/memento_command.h"
#include "pbd/playback_buffer.h"
#include "evoral/Range.h"
#include "temporal/range.h"
#include "ardour/amp.h"
#include "ardour/audio_buffer.h"
@ -401,8 +401,9 @@ DiskReader::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp
samplepos_t ss = start_sample;
Location* loc = _loop_location;
if (loc) {
Evoral::Range<samplepos_t> loop_range (loc->start (), loc->end () - 1);
ss = loop_range.squish (playback_sample);
Temporal::Range loop_range (loc->start (), loc->end ());
ss = loop_range.squish (timepos_t (playback_sample)).samples();
playback_sample = ss;
}
if (ss != playback_sample) {
if (can_internal_playback_seek (ss - playback_sample)) {
@ -492,8 +493,8 @@ midi:
Location* loc = _loop_location;
if (loc) {
Evoral::Range<samplepos_t> loop_range (loc->start (), loc->end () - 1);
playback_sample = loop_range.squish (playback_sample);
Temporal::Range loop_range (loc->start (), loc->end ());
playback_sample = loop_range.squish (timepos_t (playback_sample)).samples();
}
if (_playlists[DataType::AUDIO]) {
@ -990,7 +991,7 @@ DiskReader::audio_read (Sample* sum_buffer,
{
samplecnt_t this_read = 0;
bool reloop = false;
samplepos_t loop_end = 0;
samplepos_t loop_end = 0;
samplepos_t loop_start = 0;
Location* loc = 0;
const samplecnt_t rcnt = cnt;
@ -1008,12 +1009,11 @@ DiskReader::audio_read (Sample* sum_buffer,
*/
if ((loc = _loop_location) != 0) {
loop_start = loc->start ();
loop_end = loc->end ();
loop_start = loc->start_sample ();
loop_end = loc->end_sample ();
/* Evoral::Range has inclusive range semantics. Ugh. Hence the -1 */
const Evoral::Range<samplepos_t> loop_range (loop_start, loop_end - 1);
start = loop_range.squish (start);
const Temporal::Range loop_range (loc->start(), loc->end());
start = loop_range.squish (timepos_t (start)).samples();
}
} else {
@ -1047,7 +1047,7 @@ DiskReader::audio_read (Sample* sum_buffer,
* useful after the return from AudioPlayback::read()
*/
if (audio_playlist ()->read (sum_buffer, mixdown_buffer, gain_buffer, start, this_read, channel) != this_read) {
if (audio_playlist ()->read (sum_buffer, mixdown_buffer, gain_buffer, timepos_t (start), timecnt_t::from_samples (this_read), channel) != this_read) {
error << string_compose (_("DiskReader %1: cannot read %2 from playlist at sample %3"), id (), this_read, start) << endmsg;
return 0;
}
@ -1066,9 +1066,9 @@ DiskReader::audio_read (Sample* sum_buffer,
loop_declick_out.run (sum_buffer, start, start + this_read);
break;
case XFadeLoop:
if (last_refill_loop_start != loc->start() || rci->pre_loop_buffer == 0) {
if (last_refill_loop_start != loop_start || rci->pre_loop_buffer == 0) {
setup_preloop_buffer ();
last_refill_loop_start = loc->start();
last_refill_loop_start = loop_start;
}
maybe_xfade_loop (sum_buffer, start, start + this_read, rci);
break;
@ -1345,7 +1345,7 @@ out:
}
void
DiskReader::playlist_ranges_moved (list<Evoral::RangeMove<samplepos_t> > const& movements_samples, bool from_undo_or_shift)
DiskReader::playlist_ranges_moved (list<Temporal::RangeMove> const& movements, bool from_undo_or_shift)
{
/* If we're coming from an undo, it will have handled
* automation undo (it must, since automation-follows-regions
@ -1364,14 +1364,6 @@ DiskReader::playlist_ranges_moved (list<Evoral::RangeMove<samplepos_t> > const&
return;
}
list<Evoral::RangeMove<double> > movements;
for (list<Evoral::RangeMove<samplepos_t> >::const_iterator i = movements_samples.begin ();
i != movements_samples.end ();
++i) {
movements.push_back (Evoral::RangeMove<double> (i->from, i->length, i->to));
}
/* move panner automation */
boost::shared_ptr<Pannable> pannable = _track.pannable ();
Evoral::ControlSet::Controls& c (pannable->controls ());
@ -1393,22 +1385,17 @@ DiskReader::playlist_ranges_moved (list<Evoral::RangeMove<samplepos_t> > const&
}
}
/* move processor automation */
_track.foreach_processor (boost::bind (&DiskReader::move_processor_automation, this, _1, movements_samples));
_track.foreach_processor (boost::bind (&DiskReader::move_processor_automation, this, _1, movements));
}
void
DiskReader::move_processor_automation (boost::weak_ptr<Processor> p, list<Evoral::RangeMove<samplepos_t> > const& movements_samples)
DiskReader::move_processor_automation (boost::weak_ptr<Processor> p, list<Temporal::RangeMove> const& movements)
{
boost::shared_ptr<Processor> processor (p.lock ());
if (!processor) {
return;
}
list<Evoral::RangeMove<double> > movements;
for (list<Evoral::RangeMove<samplepos_t> >::const_iterator i = movements_samples.begin (); i != movements_samples.end (); ++i) {
movements.push_back (Evoral::RangeMove<double> (i->from, i->length, i->to));
}
set<Evoral::Parameter> const a = processor->what_can_be_automated ();
for (set<Evoral::Parameter>::const_iterator i = a.begin (); i != a.end (); ++i) {
@ -1480,18 +1467,19 @@ DiskReader::get_midi_playback (MidiBuffer& dst, samplepos_t start_sample, sample
if (loc) {
/* Evoral::Range has inclusive range semantics. Ugh. Hence the -1 */
const Evoral::Range<samplepos_t> loop_range (loc->start (), loc->end () - 1);
samplepos_t effective_start = start_sample;
samplecnt_t cnt = nframes;
sampleoffset_t offset = 0;
const Temporal::Range loop_range (loc->start (), loc->end ());
samplepos_t effective_start = start_sample;
samplecnt_t cnt = nframes;
sampleoffset_t offset = 0;
const samplepos_t loop_end = loc->end_sample();
DEBUG_TRACE (DEBUG::MidiDiskIO, string_compose ("LOOP read, loop is %1..%2 range is %3..%4 nf %5\n", loc->start (), loc->end (), start_sample, end_sample, nframes));
do {
samplepos_t effective_end;
effective_start = loop_range.squish (effective_start);
effective_end = min (effective_start + cnt, loc->end ());
effective_start = loop_range.squish (timepos_t (effective_start)).samples();
effective_end = min (effective_start + cnt, loop_end);
assert (effective_end > effective_start);
const samplecnt_t this_read = effective_end - effective_start;
@ -1739,8 +1727,8 @@ DiskReader::Declicker::run (Sample* buf, samplepos_t read_start, samplepos_t rea
* see also DiskReader::maybe_xfade_loop()
*/
switch (Evoral::coverage (fade_start, fade_end, read_start, read_end)) {
case Evoral::OverlapInternal:
switch (Temporal::coverage_exclusive_ends (fade_start, fade_end, read_start, read_end)) {
case Temporal::OverlapInternal:
/* note: start and end points cannot coincide (see evoral/Range.h)
*
* read range is entirely within fade range
@ -1750,7 +1738,7 @@ DiskReader::Declicker::run (Sample* buf, samplepos_t read_start, samplepos_t rea
n = read_end - read_start;
break;
case Evoral::OverlapExternal:
case Temporal::OverlapExternal:
/* read range extends on either side of fade range
*
* External allows coincidental start & end points, so check for that
@ -1767,14 +1755,14 @@ DiskReader::Declicker::run (Sample* buf, samplepos_t read_start, samplepos_t rea
}
break;
case Evoral::OverlapStart:
case Temporal::OverlapStart:
/* read range starts before and ends within fade or at same end as fade */
n = fade_end - read_start;
vo = 0;
bo = fade_start - read_start;
break;
case Evoral::OverlapEnd:
case Temporal::OverlapEnd:
/* read range starts within fade range, but possibly at it's end, so check */
if (read_start == fade_end) {
/* nothing to do */
@ -1785,7 +1773,7 @@ DiskReader::Declicker::run (Sample* buf, samplepos_t read_start, samplepos_t rea
n = fade_end - read_start;
break;
case Evoral::OverlapNone:
case Temporal::OverlapNone:
/* no overlap ... nothing to do */
return;
}
@ -1818,8 +1806,8 @@ DiskReader::maybe_xfade_loop (Sample* buf, samplepos_t read_start, samplepos_t r
* see also DiskReader::Declicker::run()
*/
switch (Evoral::coverage (fade_start, fade_end, read_start, read_end)) {
case Evoral::OverlapInternal:
switch (Temporal::coverage_exclusive_ends (fade_start, fade_end, read_start, read_end)) {
case Temporal::OverlapInternal:
/* note: start and end points cannot coincide (see evoral/Range.h)
*
* read range is entirely within fade range
@ -1829,7 +1817,7 @@ DiskReader::maybe_xfade_loop (Sample* buf, samplepos_t read_start, samplepos_t r
n = read_end - read_start;
break;
case Evoral::OverlapExternal:
case Temporal::OverlapExternal:
/* read range extends on either side of fade range
*
* External allows coincidental start & end points, so check for that
@ -1846,14 +1834,14 @@ DiskReader::maybe_xfade_loop (Sample* buf, samplepos_t read_start, samplepos_t r
}
break;
case Evoral::OverlapStart:
case Temporal::OverlapStart:
/* read range starts before and ends within fade or at same end as fade */
n = read_end - fade_start;
vo = 0;
bo = fade_start - read_start;
break;
case Evoral::OverlapEnd:
case Temporal::OverlapEnd:
/* read range starts within fade range, but possibly at it's end, so check */
if (read_start == fade_end) {
/* nothing to do */
@ -1864,7 +1852,7 @@ DiskReader::maybe_xfade_loop (Sample* buf, samplepos_t read_start, samplepos_t r
n = fade_end - read_start;
break;
case Evoral::OverlapNone:
case Temporal::OverlapNone:
/* no overlap ... nothing to do */
return;
}
@ -1912,8 +1900,8 @@ void
DiskReader::reset_loop_declick (Location* loc, samplecnt_t sr)
{
if (loc) {
loop_declick_in.reset (loc->start (), loc->end (), true, sr);
loop_declick_out.reset (loc->start (), loc->end (), false, sr);
loop_declick_in.reset (loc->start_sample (), loc->end_sample (), true, sr);
loop_declick_out.reset (loc->start_sample (), loc->end_sample (), false, sr);
} else {
loop_declick_in.reset (0, 0, true, sr);
loop_declick_out.reset (0, 0, false, sr);
@ -1946,6 +1934,8 @@ DiskReader::setup_preloop_buffer ()
Location* loc = _loop_location;
boost::scoped_array<Sample> mix_buf (new Sample[loop_fade_length]);
boost::scoped_array<Sample> gain_buf (new Sample[loop_fade_length]);
const timepos_t read_start = timepos_t (loc->start_sample() - loop_declick_out.fade_length);
const timecnt_t read_cnt = timecnt_t (loop_declick_out.fade_length);
uint32_t channel = 0;
@ -1955,7 +1945,7 @@ DiskReader::setup_preloop_buffer ()
rci->resize_preloop (loop_fade_length);
if (loc->start () > loop_fade_length) {
audio_playlist ()->read (rci->pre_loop_buffer, mix_buf.get (), gain_buf.get (), loc->start () - loop_declick_out.fade_length, loop_declick_out.fade_length, channel);
audio_playlist ()->read (rci->pre_loop_buffer, mix_buf.get (), gain_buf.get (), read_start, read_cnt, channel);
} else {
memset (rci->pre_loop_buffer, 0, sizeof (Sample) * loop_fade_length);
}

View File

@ -169,12 +169,13 @@ DiskWriter::check_record_status (samplepos_t transport_sample, double speed, boo
Location* loc;
if (_session.config.get_punch_in () && 0 != (loc = _session.locations()->auto_punch_location ())) {
_capture_start_sample = loc->start ();
_capture_start_sample = loc->start_sample ();
} else if (_loop_location) {
_capture_start_sample = _loop_location->start ();
_capture_start_sample = _loop_location->start_sample ();
if (_last_possibly_recording & transport_rolling) {
_accumulated_capture_offset = _playback_offset + transport_sample - _session.transport_sample (); // + rec_offset;
}
} else {
_capture_start_sample = _session.transport_sample ();
}
@ -191,7 +192,7 @@ DiskWriter::check_record_status (samplepos_t transport_sample, double speed, boo
* We should allow to move it or at least allow to disable punch-out
* while rolling..
*/
_last_recordable_sample = loc->end ();
_last_recordable_sample = loc->end_sample ();
if (_alignment_style == ExistingMaterial) {
_last_recordable_sample += _capture_offset + _playback_offset;
}
@ -234,14 +235,14 @@ DiskWriter::check_record_status (samplepos_t transport_sample, double speed, boo
}
void
DiskWriter::calculate_record_range (Evoral::OverlapType ot, samplepos_t transport_sample, samplecnt_t nframes, samplecnt_t & rec_nframes, samplecnt_t & rec_offset)
DiskWriter::calculate_record_range (Temporal::OverlapType ot, samplepos_t transport_sample, samplecnt_t nframes, samplecnt_t & rec_nframes, samplecnt_t & rec_offset)
{
switch (ot) {
case Evoral::OverlapNone:
case Temporal::OverlapNone:
rec_nframes = 0;
break;
case Evoral::OverlapInternal:
case Temporal::OverlapInternal:
/* ---------- recrange
* |---| transrange
*/
@ -249,7 +250,7 @@ DiskWriter::calculate_record_range (Evoral::OverlapType ot, samplepos_t transpor
rec_offset = 0;
break;
case Evoral::OverlapStart:
case Temporal::OverlapStart:
/* |--------| recrange
* -----| transrange
*/
@ -259,7 +260,7 @@ DiskWriter::calculate_record_range (Evoral::OverlapType ot, samplepos_t transpor
}
break;
case Evoral::OverlapEnd:
case Temporal::OverlapEnd:
/* |--------| recrange
* |-------- transrange
*/
@ -267,7 +268,7 @@ DiskWriter::calculate_record_range (Evoral::OverlapType ot, samplepos_t transpor
rec_offset = 0;
break;
case Evoral::OverlapExternal:
case Temporal::OverlapExternal:
/* |--------| recrange
* -------------- transrange
*/
@ -394,7 +395,8 @@ void
DiskWriter::non_realtime_locate (samplepos_t position)
{
if (_midi_write_source) {
_midi_write_source->set_natural_position (position);
#warning NUTEMPO maybe fixme perhaps take sources time domain into account here e.g. beats
_midi_write_source->set_natural_position (timepos_t (position));
}
DiskIOProcessor::non_realtime_locate (position);
@ -430,14 +432,14 @@ DiskWriter::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp
bool re = record_enabled ();
bool punch_in = _session.config.get_punch_in () && _session.locations()->auto_punch_location ();
bool can_record = _session.actively_recording ();
can_record |= speed != 0 && _session.get_record_enabled () && punch_in && _session.transport_sample () <= _session.locations()->auto_punch_location ()->start ();
can_record |= speed != 0 && _session.get_record_enabled () && punch_in && _session.transport_sample () <= _session.locations()->auto_punch_location ()->start_sample ();
_need_butler = false;
const Location* const loop_loc = _loop_location;
samplepos_t loop_start = 0;
samplepos_t loop_end = 0;
samplepos_t loop_length = 0;
const Location* const loop_loc = _loop_location;
timepos_t loop_start;
timepos_t loop_end;
timecnt_t loop_length;
if (_transport_looped && _capture_captured == 0) {
_transport_looped = false;
@ -446,9 +448,9 @@ DiskWriter::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp
if (loop_loc) {
get_location_times (loop_loc, &loop_start, &loop_end, &loop_length);
if (_was_recording && _transport_looped && _capture_captured >= loop_length) {
samplecnt_t remain = _capture_captured - loop_length;
_capture_captured = loop_length;
if (_was_recording && _transport_looped && _capture_captured >= loop_length.samples()) {
samplecnt_t remain = _capture_captured - loop_length.samples();
_capture_captured = loop_length.samples();
loop (_transport_loop_sample);
_capture_captured = remain;
}
@ -481,7 +483,7 @@ DiskWriter::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp
if (nominally_recording || (re && _was_recording && _session.get_record_enabled() && punch_in)) {
Evoral::OverlapType ot = Evoral::coverage (_first_recordable_sample, _last_recordable_sample, start_sample, end_sample);
Temporal::OverlapType ot = Temporal::coverage_exclusive_ends (_first_recordable_sample, _last_recordable_sample, start_sample, end_sample);
// XXX should this be transport_sample + nframes - 1 ? coverage() expects its parameter ranges to include their end points
// XXX also, first_recordable_sample & last_recordable_sample may both be == max_samplepos: coverage() will return OverlapNone in that case. Is thak OK?
calculate_record_range (ot, start_sample, nframes, rec_nframes, rec_offset);
@ -498,9 +500,10 @@ DiskWriter::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp
at the loop start and can handle time wrapping around.
Otherwise, start the source right now as usual.
*/
_capture_captured = start_sample - loop_start + rec_offset;
_capture_start_sample = loop_start;
_first_recordable_sample = loop_start;
_capture_captured = start_sample - loop_start.samples() + rec_offset;
_capture_start_sample = loop_start.samples();
_first_recordable_sample = loop_start.samples();
if (_alignment_style == ExistingMaterial) {
_capture_captured -= _playback_offset + _capture_offset;
@ -521,7 +524,7 @@ DiskWriter::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp
if (_midi_write_source) {
assert (_capture_start_sample);
_midi_write_source->mark_write_starting_now (_capture_start_sample.value (), _capture_captured, loop_length);
_midi_write_source->mark_write_starting_now (_capture_start_sample, _capture_captured, loop_length.samples());
}
g_atomic_int_set (&_samples_pending_write, 0);
@ -629,7 +632,7 @@ DiskWriter::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp
reconstruct their actual time; future clever MIDI looping should
probably be implemented in the source instead of here.
*/
const samplecnt_t loop_offset = g_atomic_int_get (&_num_captured_loops) * loop_length;
const samplecnt_t loop_offset = g_atomic_int_get (&_num_captured_loops) * loop_length.samples();
const samplepos_t event_time = start_sample + loop_offset - _accumulated_capture_offset + ev.time();
if (event_time < 0 || event_time < _first_recordable_sample) {
/* Event out of range, skip */
@ -743,11 +746,11 @@ DiskWriter::finish_capture (boost::shared_ptr<ChannelList> c)
_xruns.clear ();
if (_loop_location) {
samplepos_t loop_start = 0;
samplepos_t loop_end = 0;
samplepos_t loop_length = 0;
timepos_t loop_start;
timepos_t loop_end;
timecnt_t loop_length;
get_location_times (_loop_location, &loop_start, &loop_end, &loop_length);
ci->loop_offset = g_atomic_int_get (&_num_captured_loops) * loop_length;
ci->loop_offset = g_atomic_int_get (&_num_captured_loops) * loop_length.samples();
} else {
ci->loop_offset = 0;
}
@ -1021,7 +1024,7 @@ DiskWriter::do_flush (RunContext ctxt, bool force_flush)
if ((total > _chunk_samples) || force_flush) {
Source::Lock lm(_midi_write_source->mutex());
if (_midi_write_source->midi_write (lm, *_midi_buf, get_capture_start_sample (0), to_write) != to_write) {
if (_midi_write_source->midi_write (lm, *_midi_buf, timepos_t (get_capture_start_sample (0)), timecnt_t (to_write)) != to_write) {
error << string_compose(_("MidiDiskstream %1: cannot write to disk"), id()) << endmsg;
return -1;
}
@ -1221,7 +1224,7 @@ DiskWriter::transport_stopped_wallclock (struct tm& when, time_t twhen, bool abo
Analyser::queue_source_for_analysis (as, true);
}
DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose ("newly captured source %1 length %2\n", as->path(), as->length (0)));
DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose ("newly captured source %1 length %2\n", as->path(), as->length ()));
}
if (_midi_write_source) {
@ -1238,7 +1241,7 @@ DiskWriter::transport_stopped_wallclock (struct tm& when, time_t twhen, bool abo
if (_midi_write_source) {
if (_midi_write_source->length (capture_info.front()->start) == 0) {
if (_midi_write_source->empty()) {
/* No data was recorded, so this capture will
effectively be aborted; do the same as we
do for an explicit abort.
@ -1260,27 +1263,17 @@ DiskWriter::transport_stopped_wallclock (struct tm& when, time_t twhen, bool abo
midi_srcs.push_back (_midi_write_source);
_midi_write_source->set_natural_position (capture_info.front()->start);
_midi_write_source->set_captured_for (_track.name ());
_midi_write_source->set_natural_position (timepos_t (capture_info.front()->start));
_midi_write_source->set_captured_for (_track.name());
Glib::DateTime tm (Glib::DateTime::create_now_local (mktime (&when)));
_midi_write_source->set_take_id (tm.format ("%F %H.%M.%S"));
/* set length in beats to entire capture length */
Temporal::Beats total_capture_beats;
for (vector<CaptureInfo*>::iterator ci = capture_info.begin(); ci != capture_info.end(); ++ci) {
BeatsSamplesConverter converter (_session.tempo_map(), (*ci)->start);
total_capture_beats += converter.from ((*ci)->samples);
}
_midi_write_source->set_length_beats (total_capture_beats);
/* flush to disk: this step differs from the audio path,
where all the data is already on disk.
*/
_midi_write_source->mark_midi_streaming_write_completed (source_lock, Evoral::Sequence<Temporal::Beats>::ResolveStuckNotes, total_capture_beats);
_midi_write_source->mark_midi_streaming_write_completed (source_lock, Evoral::Sequence<Temporal::Beats>::ResolveStuckNotes, timecnt_t (total_capture, timepos_t (capture_info.front()->start)).beats());
}
_last_capture_sources.insert (_last_capture_sources.end(), audio_srcs.begin(), audio_srcs.end());

View File

@ -42,7 +42,7 @@ EBUr128Analysis::~EBUr128Analysis()
}
int
EBUr128Analysis::run (Readable* src)
EBUr128Analysis::run (AudioReadable* src)
{
int ret = -1;
bool done = false;

View File

@ -29,8 +29,6 @@
#include "pbd/enumwriter.h"
#include "midi++/types.h"
#include "evoral/Range.h" // shouldn't Evoral have its own enum registration?
#include "ardour/delivery.h"
#include "ardour/disk_io.h"
#include "ardour/export_channel.h"
@ -146,7 +144,6 @@ setup_enum_writer ()
ScreenSaverMode _ScreenSaverMode;
Session::PostTransportWork _Session_PostTransportWork;
MTC_Status _MIDI_MTC_Status;
Evoral::OverlapType _OverlapType;
BufferingPreset _BufferingPreset;
AutoReturnTarget _AutoReturnTarget;
PresentationInfo::Flag _PresentationInfo_Flag;
@ -743,13 +740,6 @@ setup_enum_writer ()
REGISTER_ENUM(MusicTime);
REGISTER(_PositionLockStyle);
REGISTER_ENUM (Evoral::OverlapNone);
REGISTER_ENUM (Evoral::OverlapInternal);
REGISTER_ENUM (Evoral::OverlapStart);
REGISTER_ENUM (Evoral::OverlapEnd);
REGISTER_ENUM (Evoral::OverlapExternal);
REGISTER(_OverlapType);
REGISTER_ENUM (Small);
REGISTER_ENUM (Medium);
REGISTER_ENUM (Large);

View File

@ -174,7 +174,7 @@ RegionExportChannelFactory::RegionExportChannelFactory (Session * session, Audio
, type (type)
, samples_per_cycle (session->engine().samples_per_cycle ())
, buffers_up_to_date (false)
, region_start (region.position())
, region_start (region.position_sample())
, position (region_start)
{
switch (type) {

View File

@ -598,7 +598,7 @@ ExportHandler::export_cd_marker_file (ExportTimespanPtr timespan, ExportFormatSp
if ((*i)->is_mark()) {
/* Index within track */
status.index_position = (*i)->start() - timespan->get_start();
status.index_position = (*i)->start_sample() - timespan->get_start();
(this->*index_func) (status);
}
@ -608,7 +608,7 @@ ExportHandler::export_cd_marker_file (ExportTimespanPtr timespan, ExportFormatSp
/* A track, defined by a cd range marker or a cd location marker outside of a cd range */
status.track_position = last_end_time - timespan->get_start();
status.track_start_sample = (*i)->start() - timespan->get_start(); // everything before this is the pregap
status.track_start_sample = (*i)->start_sample() - timespan->get_start(); // everything before this is the pregap
status.track_duration = 0;
if ((*i)->is_mark()) {
@ -617,9 +617,9 @@ ExportHandler::export_cd_marker_file (ExportTimespanPtr timespan, ExportFormatSp
++nexti;
if (nexti != temp.end()) {
status.track_duration = (*nexti)->start() - last_end_time;
status.track_duration = (*nexti)->start_sample() - last_end_time;
last_end_time = (*nexti)->start();
last_end_time = (*nexti)->start_sample();
} else {
// this was the last marker, use timespan end
status.track_duration = timespan->get_end() - last_end_time;
@ -628,9 +628,9 @@ ExportHandler::export_cd_marker_file (ExportTimespanPtr timespan, ExportFormatSp
}
} else {
// range
status.track_duration = (*i)->end() - last_end_time;
status.track_duration = (*i)->end_sample() - last_end_time;
last_end_time = (*i)->end();
last_end_time = (*i)->end_sample();
}
(this->*track_func) (status);

View File

@ -363,7 +363,7 @@ ExportProfileManager::set_selection_range (samplepos_t start, samplepos_t end)
if (start || end) {
selection_range.reset (new Location (session));
selection_range->set_name (_("Selection"));
selection_range->set (start, end);
selection_range->set (timepos_t (start), timepos_t (end));
} else {
selection_range.reset();
}
@ -380,7 +380,7 @@ ExportProfileManager::set_single_range (samplepos_t start, samplepos_t end, stri
single_range.reset (new Location (session));
single_range->set_name (name);
single_range->set (start, end);
single_range->set (timepos_t (start), timepos_t (end));
update_ranges ();
@ -415,7 +415,7 @@ ExportProfileManager::init_timespans (XMLNodeList nodes)
ExportTimespanPtr timespan = handler->add_timespan();
timespan->set_name (session_range->name());
timespan->set_range_id (session_range->id().to_s());
timespan->set_range (session_range->start(), session_range->end());
timespan->set_range (session_range->start_sample(), session_range->end_sample());
state->timespans->push_back (timespan);
return false;
}
@ -450,7 +450,7 @@ ExportProfileManager::deserialize_timespan (XMLNode & root)
ExportTimespanPtr timespan = handler->add_timespan();
timespan->set_name (location->name());
timespan->set_range_id (location->id().to_s());
timespan->set_range (location->start(), location->end());
timespan->set_range (location->start_sample(), location->end_sample());
state->timespans->push_back (timespan);
}

View File

@ -43,9 +43,10 @@ int
Filter::make_new_sources (boost::shared_ptr<Region> region, SourceList& nsrcs, std::string suffix, bool use_session_sample_rate)
{
vector<string> names = region->master_source_names();
assert (region->n_channels() <= names.size());
const SourceList::size_type nsrc = region->sources().size();
assert (nsrc <= names.size());
for (uint32_t i = 0; i < region->n_channels(); ++i) {
for (SourceList::size_type i = 0; i < nsrc; ++i) {
string name = PBD::basename_nosuffix (names[i]);
@ -62,7 +63,7 @@ Filter::make_new_sources (boost::shared_ptr<Region> region, SourceList& nsrcs, s
const string path = (region->data_type() == DataType::MIDI)
? session.new_midi_source_path (name)
: session.new_audio_source_path (name, region->n_channels(), i, false);
: session.new_audio_source_path (name, nsrc, i, false);
if (path.empty()) {
error << string_compose (_("filter: error creating name for new file based on %1"), region->name())
@ -120,7 +121,7 @@ Filter::finish (boost::shared_ptr<Region> region, SourceList& nsrcs, string regi
boost::shared_ptr<SMFSource> smfs = boost::dynamic_pointer_cast<SMFSource>(*si);
if (smfs) {
smfs->set_natural_position (region->position_sample());
smfs->set_natural_position (region->nt_position());
smfs->flush ();
}
@ -138,7 +139,7 @@ Filter::finish (boost::shared_ptr<Region> region, SourceList& nsrcs, string regi
PropertyList plist;
plist.add (Properties::start, 0);
plist.add (Properties::start, std::numeric_limits<timecnt_t>::min());
plist.add (Properties::length, region->nt_length());
plist.add (Properties::name, region_name);
plist.add (Properties::whole_file, true);

View File

@ -63,7 +63,7 @@ static boost::shared_ptr<AutomationList> automation_list_new (Evoral::Parameter
case BusSendLevel:
/* fallthrough */
case TrimAutomation:
return boost::shared_ptr<AutomationList> (new AutomationList (param));
return boost::shared_ptr<AutomationList> (new AutomationList (param, Temporal::AudioTime));
case MainOutVolume:
/* not automatable */
break;
@ -112,10 +112,10 @@ bool
GainControl::get_masters_curve_locked (samplepos_t start, samplepos_t end, float* vec, samplecnt_t veclen) const
{
if (_masters.empty()) {
return list()->curve().rt_safe_get_vector (start, end, vec, veclen);
return list()->curve().rt_safe_get_vector (timepos_t (start), timepos_t (end), vec, veclen);
}
for (samplecnt_t i = 0; i < veclen; ++i) {
vec[i] = 1.f;
}
return SlavableAutomationControl::masters_curve_multiply (start, end, vec, veclen);
return SlavableAutomationControl::masters_curve_multiply (timepos_t (start), timepos_t (end), vec, veclen);
}

View File

@ -539,6 +539,8 @@ ARDOUR::init (bool try_optimization, const char* localedir, bool with_gui)
if (!PBD::init ())
return false;
Temporal::init ();
#if ENABLE_NLS
(void)bindtextdomain (PACKAGE, localedir);
(void)bind_textdomain_codeset (PACKAGE, "UTF-8");

View File

@ -231,7 +231,7 @@ create_mono_sources_for_writing (const vector<string>& new_paths,
boost::shared_ptr<AudioFileSource> afs;
if ((afs = boost::dynamic_pointer_cast<AudioFileSource>(source)) != 0) {
afs->set_natural_position (natural_position);
afs->set_natural_position (timepos_t (natural_position));
}
}
return true;
@ -462,8 +462,7 @@ write_midi_data_to_new_files (Evoral::SMF* source, ImportStatus& status,
const samplepos_t pos = 0;
const Temporal::Beats length_beats = Temporal::Beats::ticks_at_rate(t, source->ppqn());
BeatsSamplesConverter converter(smfs->session().tempo_map(), pos);
smfs->update_length(pos + converter.to(length_beats.round_up_to_beat()));
smfs->update_length (timecnt_t (length_beats.round_up_to_beat(), timepos_t(Temporal::BeatTime)));
smfs->mark_streaming_write_completed (source_lock);
if (status.cancel) {
@ -618,7 +617,7 @@ Session::import_files (ImportStatus& status)
for (Sources::iterator x = all_new_sources.begin(); x != all_new_sources.end(); ) {
if ((afs = boost::dynamic_pointer_cast<AudioFileSource>(*x)) != 0) {
afs->update_header((*x)->natural_position(), *now, xnow);
afs->update_header((*x)->natural_position().samples(), *now, xnow);
afs->done_with_peakfile_writes ();
/* now that there is data there, requeue the file for analysis */

View File

@ -75,7 +75,7 @@ struct PlaylistState {
};
bool
Session::import_sndfile_as_region (string path, SrcQuality quality, samplepos_t& pos, SourceList& sources, ImportStatus& status, uint32_t current, uint32_t total)
Session::import_sndfile_as_region (string path, SrcQuality quality, timepos_t& pos, SourceList& sources, ImportStatus& status, uint32_t current, uint32_t total)
{
/* Import the source */
status.paths.clear();
@ -113,7 +113,7 @@ Session::import_sndfile_as_region (string path, SrcQuality quality, samplepos_t&
string region_name;
bool use_timestamp;
use_timestamp = (pos == -1);
use_timestamp = (pos == timepos_t::max (Temporal::AudioTime));
/* take all the sources we have and package them up as a region */
@ -127,8 +127,8 @@ Session::import_sndfile_as_region (string path, SrcQuality quality, samplepos_t&
PropertyList plist;
plist.add (ARDOUR::Properties::start, 0);
plist.add (ARDOUR::Properties::length, sources[0]->length (pos));
plist.add (ARDOUR::Properties::start, timepos_t (0));
plist.add (ARDOUR::Properties::length, timecnt_t (sources[0]->length (), pos));
plist.add (ARDOUR::Properties::name, region_name);
plist.add (ARDOUR::Properties::layer, 0);
plist.add (ARDOUR::Properties::whole_file, true);
@ -164,11 +164,11 @@ Session::import_sndfile_as_region (string path, SrcQuality quality, samplepos_t&
if (as->natural_position() != 0) {
pos = as->natural_position();
} else {
pos = 0;
pos = timepos_t (pos.time_domain ());
}
} else {
/* should really get first position in MIDI file, but for now, use 0 */
pos = 0;
pos = timepos_t (pos.time_domain());
}
}
}
@ -187,7 +187,8 @@ Session::import_pt_sources (PTFFormat& ptf, ImportStatus& status)
string fullpath;
bool ok = false;
bool onefailed = false;
samplepos_t pos = -1;
timepos_t pos = timepos_t::max (Temporal::AudioTime);
uint32_t srate = sample_rate ();
vector<PTFFormat::wav_t>::const_iterator w;
uint32_t wth = 0;
@ -376,12 +377,42 @@ Session::import_pt_rest (PTFFormat& ptf)
/* Matched a ptf active region to an ardour region */
boost::shared_ptr<Region> r = RegionFactory::region_by_id (p->id);
DEBUG_TRACE (DEBUG::FileUtils, string_compose ("\twav(%1) reg(%2) tr(%3)\n", a->reg.wave.filename.c_str (), a->reg.index, a->index));
vector<struct ptflookup>::iterator lookuptr = usedtracks.begin ();
vector<struct ptflookup>::iterator found;
if ((found = std::find (lookuptr, usedtracks.end (), utr)) != usedtracks.end ()) {
DEBUG_TRACE (DEBUG::FileUtils, string_compose ("\twav(%1) reg(%2) ptf_tr(%3) ard_tr(%4)\n", a->reg.wave.filename.c_str (), a->reg.index, found->index1, found->index2));
/* Use existing playlists */
boost::shared_ptr<Playlist> playlist = playlists[a->index].playlist;
boost::shared_ptr<Region> copy (RegionFactory::create (r, true));
playlist->add_region (copy, a->reg.startpos);
/* Use existing track if possible */
existing_track = get_nth_audio_track (found->index2 + 1);
if (!existing_track) {
list<boost::shared_ptr<AudioTrack> > at (new_audio_track (1, 2, 0, 1, a->name.c_str(), PresentationInfo::max_order, Normal));
if (at.empty ()) {
return;
}
existing_track = at.back ();
}
/* Put on existing track */
boost::shared_ptr<Playlist> playlist = existing_track->playlist ();
boost::shared_ptr<Region> copy (RegionFactory::create (r, true));
playlist->clear_changes ();
playlist->add_region (copy, timepos_t (a->reg.startpos));
//add_command (new StatefulDiffCommand (playlist));
} else {
/* Put on a new track */
DEBUG_TRACE (DEBUG::FileUtils, string_compose ("\twav(%1) reg(%2) new_tr(%3)\n", a->reg.wave.filename.c_str (), a->reg.index, nth));
list<boost::shared_ptr<AudioTrack> > at (new_audio_track (1, 2, 0, 1, a->name.c_str(), PresentationInfo::max_order, Normal));
if (at.empty ()) {
return;
}
existing_track = at.back ();
boost::shared_ptr<Playlist> playlist = existing_track->playlist();
boost::shared_ptr<Region> copy (RegionFactory::create (r, true));
playlist->clear_changes ();
playlist->add_region (copy, timepos_t (a->reg.startpos));
//add_command (new StatefulDiffCommand (playlist));
nth++;
usedtracks.push_back (utr);
}
}
}
}
@ -442,9 +473,9 @@ no_audio_tracks:
plist.add (ARDOUR::Properties::name, PBD::basename_nosuffix (src->name ()));
//printf(" : %d - trackname: (%s)\n", a->index, src->name ().c_str ());
boost::shared_ptr<Region> region = (RegionFactory::create (src, plist));
/* sets beat position */
region->set_position (pos.sample, pos.division);
midi_track->playlist ()->add_region (region, pos.sample, 1.0, false, pos.division);
/* sets position */
region->set_position (timepos_t (pos.sample));
midi_track->playlist ()->add_region (region, timepos_t (pos.sample), 1.0, false);
boost::shared_ptr<MidiRegion> mr = boost::dynamic_pointer_cast<MidiRegion>(region);
boost::shared_ptr<MidiModel> mm = mr->midi_source (0)->model ();
@ -461,6 +492,6 @@ no_audio_tracks:
mm->apply_command (this, midicmd);
boost::shared_ptr<Region> copy (RegionFactory::create (mr, true));
playlist->clear_changes ();
playlist->add_region (copy, f);
playlist->add_region (copy, timepos_t (f));
}
}

View File

@ -53,6 +53,7 @@ namespace PBD {
using namespace std;
using namespace ARDOUR;
using namespace PBD;
using namespace Temporal;
PBD::Signal0<void> Location::scene_changed;
PBD::Signal1<void,Location*> Location::name_changed;
@ -60,39 +61,32 @@ PBD::Signal1<void,Location*> Location::end_changed;
PBD::Signal1<void,Location*> Location::start_changed;
PBD::Signal1<void,Location*> Location::flags_changed;
PBD::Signal1<void,Location*> Location::lock_changed;
PBD::Signal1<void,Location*> Location::position_lock_style_changed;
PBD::Signal1<void,Location*> Location::changed;
Location::Location (Session& s)
: SessionHandleRef (s)
, _start (0)
, _start_beat (0.0)
, _end (0)
, _end_beat (0.0)
, _flags (Flags (0))
, _locked (false)
, _position_lock_style (AudioTime)
, _timestamp (time (0))
{
assert (_start >= 0);
assert (_end >= 0);
}
/** Construct a new Location, giving it the position lock style determined by glue-new-markers-to-bars-and-beats */
Location::Location (Session& s, samplepos_t sample_start, samplepos_t sample_end, const std::string &name, Flags bits, const uint32_t sub_num)
Location::Location (Session& s, timepos_t const & start, timepos_t const & end, const std::string &name, Flags bits)
: SessionHandleRef (s)
, _name (name)
, _start (sample_start)
, _end (sample_end)
, _start (start)
, _end (end)
, _flags (bits)
, _locked (false)
, _position_lock_style (s.config.get_glue_new_markers_to_bars_and_beats() ? MusicTime : AudioTime)
, _timestamp (time (0))
{
recompute_beat_from_samples (sub_num);
assert (_start >= 0);
assert (_end >= 0);
#warning NUTEMPO FIXME drop this and ensure that timepos start/end use correct domain in caller for this constructor
if (s.config.get_glue_new_markers_to_bars_and_beats()) {
set_position_time_domain (Temporal::BeatTime);
} else {
set_position_time_domain (Temporal::AudioTime);
}
}
Location::Location (const Location& other)
@ -100,39 +94,32 @@ Location::Location (const Location& other)
, StatefulDestructible()
, _name (other._name)
, _start (other._start)
, _start_beat (other._start_beat)
, _end (other._end)
, _end_beat (other._end_beat)
, _flags (other._flags)
, _position_lock_style (other._position_lock_style)
, _timestamp (time (0))
{
/* copy is not locked even if original was */
_locked = false;
assert (_start >= 0);
assert (_end >= 0);
/* scene change is NOT COPIED */
}
Location::Location (Session& s, const XMLNode& node)
: SessionHandleRef (s)
, _flags (Flags (0))
, _position_lock_style (AudioTime)
, _timestamp (time (0))
{
/* Note: _position_lock_style is initialised above in case set_state doesn't set it
(for 2.X session file compatibility).
*/
//_start.set_time_domain (AudioTime);
//_end.set_time_domain (AudioTime);
/* Note: _position_time_domain is initialised above in case set_state
* doesn't set it
*/
if (set_state (node, Stateful::loading_state_version)) {
throw failed_constructor ();
}
assert (_start >= 0);
assert (_end >= 0);
}
bool
@ -141,10 +128,7 @@ Location::operator== (const Location& other)
if (_name != other._name ||
_start != other._start ||
_end != other._end ||
_start_beat != other._start_beat ||
_end_beat != other._end_beat ||
_flags != other._flags ||
_position_lock_style != other._position_lock_style) {
_flags != other._flags) {
return false;
}
return true;
@ -159,11 +143,8 @@ Location::operator= (const Location& other)
_name = other._name;
_start = other._start;
_start_beat = other._start_beat;
_end = other._end;
_end_beat = other._end_beat;
_flags = other._flags;
_position_lock_style = other._position_lock_style;
/* XXX need to copy scene change */
@ -173,9 +154,6 @@ Location::operator= (const Location& other)
/* "changed" not emitted on purpose */
assert (_start >= 0);
assert (_end >= 0);
return this;
}
@ -194,14 +172,10 @@ Location::set_name (const std::string& str)
/** Set start position.
* @param s New start.
* @param force true to force setting, even if the given new start is after the current end.
* @param allow_beat_recompute True to recompute BEAT start time from the new given start time.
*/
int
Location::set_start (samplepos_t s, bool force, bool allow_beat_recompute, const uint32_t sub_num)
Location::set_start (Temporal::timepos_t const & s, bool force)
{
if (s < 0) {
return -1;
}
if (_locked) {
return -1;
@ -217,9 +191,6 @@ Location::set_start (samplepos_t s, bool force, bool allow_beat_recompute, const
if (_start != s) {
_start = s;
_end = s;
if (allow_beat_recompute) {
recompute_beat_from_samples (sub_num);
}
start_changed (this); /* EMIT SIGNAL */
StartChanged (); /* EMIT SIGNAL */
@ -235,51 +206,42 @@ Location::set_start (samplepos_t s, bool force, bool allow_beat_recompute, const
scene_changed (); /* EMIT SIGNAL */
}
assert (_start >= 0);
assert (_end >= 0);
assert (s.zero() || s.positive());
return 0;
} else if (!force) {
/* range locations must exceed a minimum duration */
if (_end - s < Config->get_range_location_minimum()) {
if (s.distance (_end) < Config->get_range_location_minimum()) {
return -1;
}
}
if (s != _start) {
samplepos_t const old = _start;
Temporal::timepos_t const old = _start;
_start = s;
if (allow_beat_recompute) {
recompute_beat_from_samples (sub_num);
}
start_changed (this); /* EMIT SIGNAL */
StartChanged (); /* EMIT SIGNAL */
if (is_session_range ()) {
Session::StartTimeChanged (old); /* EMIT SIGNAL */
AudioFileSource::set_header_position_offset (s);
Session::StartTimeChanged (old.samples()); /* emit signal */
AudioFileSource::set_header_position_offset (s.samples());
}
}
assert (_start >= 0);
assert (_start.positive() || _start.zero());
return 0;
}
/** Set end position.
* @param s New end.
/** set end position.
* @param s new end.
* @param force true to force setting, even if the given new end is before the current start.
* @param allow_beat_recompute True to recompute BEAT end time from the new given end time.
*/
int
Location::set_end (samplepos_t e, bool force, bool allow_beat_recompute, const uint32_t sub_num)
Location::set_end (Temporal::timepos_t const & e, bool force)
{
if (e < 0) {
return -1;
}
if (_locked) {
return -1;
}
@ -294,13 +256,10 @@ Location::set_end (samplepos_t e, bool force, bool allow_beat_recompute, const u
if (_start != e) {
_start = e;
_end = e;
if (allow_beat_recompute) {
recompute_beat_from_samples (sub_num);
}
//start_changed (this); /* EMIT SIGNAL */
//StartChanged (); /* EMIT SIGNAL */
end_changed (this); /* EMIT SIGNAL */
EndChanged (); /* EMIT SIGNAL */
//start_changed (this); /* emit signal */
//startchanged (); /* emit signal */
end_changed (this); /* emit signal */
EndChanged (); /* emit signal */
}
assert (_start >= 0);
@ -309,40 +268,32 @@ Location::set_end (samplepos_t e, bool force, bool allow_beat_recompute, const u
return 0;
} else if (!force) {
/* range locations must exceed a minimum duration */
if (e - _start < Config->get_range_location_minimum()) {
if (_start.distance (e) < Config->get_range_location_minimum()) {
return -1;
}
}
if (e != _end) {
samplepos_t const old = _end;
timepos_t const old = _end;
_end = e;
if (allow_beat_recompute) {
recompute_beat_from_samples (sub_num);
}
end_changed(this); /* EMIT SIGNAL */
EndChanged(); /* EMIT SIGNAL */
if (is_session_range()) {
Session::EndTimeChanged (old); /* EMIT SIGNAL */
Session::EndTimeChanged (old.samples()); /* EMIT SIGNAL */
}
}
assert (_end >= 0);
assert (_end.positive() || _end.zero());
return 0;
}
int
Location::set (samplepos_t s, samplepos_t e, bool allow_beat_recompute, const uint32_t sub_num)
Location::set (Temporal::timepos_t const & s, Temporal::timepos_t const & e)
{
if (s < 0 || e < 0) {
return -1;
}
/* check validity */
if (((is_auto_punch() || is_auto_loop()) && s >= e) || (!is_mark() && s > e)) {
return -1;
@ -356,11 +307,6 @@ Location::set (samplepos_t s, samplepos_t e, bool allow_beat_recompute, const ui
if (_start != s) {
_start = s;
_end = s;
if (allow_beat_recompute) {
recompute_beat_from_samples (sub_num);
}
start_change = true;
end_change = true;
}
@ -371,45 +317,35 @@ Location::set (samplepos_t s, samplepos_t e, bool allow_beat_recompute, const ui
} else {
/* range locations must exceed a minimum duration */
if (e - s < Config->get_range_location_minimum()) {
if (s.distance (e) < Config->get_range_location_minimum()) {
return -1;
}
if (s != _start) {
samplepos_t const old = _start;
Temporal::timepos_t const old = _start;
_start = s;
if (allow_beat_recompute) {
recompute_beat_from_samples (sub_num);
}
start_change = true;
if (is_session_range ()) {
Session::StartTimeChanged (old); /* EMIT SIGNAL */
AudioFileSource::set_header_position_offset (s);
Session::StartTimeChanged (old.samples()); /* EMIT SIGNAL */
AudioFileSource::set_header_position_offset (s.samples());
}
}
if (e != _end) {
samplepos_t const old = _end;
Temporal::timepos_t const old = _end;
_end = e;
if (allow_beat_recompute) {
recompute_beat_from_samples (sub_num);
}
end_change = true;
if (is_session_range()) {
Session::EndTimeChanged (old); /* EMIT SIGNAL */
Session::EndTimeChanged (old.samples()); /* EMIT SIGNAL */
}
}
assert (_end >= 0);
assert (e.positive() || e.zero());
}
if (start_change && end_change) {
@ -427,20 +363,16 @@ Location::set (samplepos_t s, samplepos_t e, bool allow_beat_recompute, const ui
}
int
Location::move_to (samplepos_t pos, const uint32_t sub_num)
Location::move_to (Temporal::timepos_t const & pos)
{
if (pos < 0) {
return -1;
}
if (_locked) {
return -1;
}
if (_start != pos) {
const timecnt_t len = _start.distance (_end);
_start = pos;
_end = _start + length();
recompute_beat_from_samples (sub_num);
_end = pos + len;
changed (this); /* EMIT SIGNAL */
Changed (); /* EMIT SIGNAL */
@ -496,7 +428,7 @@ Location::set_is_clock_origin (bool yn, void*)
void
Location::set_skip (bool yn)
{
if (is_range_marker() && length() > 0) {
if (is_range_marker() && length_samples() > 0) {
if (set_flag_internal (yn, IsSkip)) {
flags_changed (this);
FlagsChanged ();
@ -507,7 +439,7 @@ Location::set_skip (bool yn)
void
Location::set_skipping (bool yn)
{
if (is_range_marker() && is_skip() && length() > 0) {
if (is_range_marker() && is_skip() && length_samples() > 0) {
if (set_flag_internal (yn, IsSkipping)) {
flags_changed (this);
FlagsChanged ();
@ -598,13 +530,8 @@ Location::get_state ()
node->set_property ("name", name());
node->set_property ("start", start());
node->set_property ("end", end());
if (position_lock_style() == MusicTime) {
node->set_property ("start-beat", _start_beat);
node->set_property ("end-beat", _end_beat);
}
node->set_property ("flags", _flags);
node->set_property ("locked", _locked);
node->set_property ("position-lock-style", _position_lock_style);
node->set_property ("timestamp", _timestamp);
if (_scene_change) {
node->add_child_nocopy (_scene_change->get_state());
@ -690,67 +617,38 @@ Location::set_state (const XMLNode& node, int version)
cd_info[cd_name] = cd_value;
}
node.get_property ("position-lock-style", _position_lock_style);
XMLNode* scene_child = find_named_node (node, SceneChange::xml_node_name);
if (scene_child) {
_scene_change = SceneChange::factory (*scene_child, version);
}
if (position_lock_style() == AudioTime) {
recompute_beat_from_samples (0);
} else{
/* music */
if (!node.get_property ("start-beat", _start_beat) ||
!node.get_property ("end-beat", _end_beat)) {
recompute_beat_from_samples (0);
}
}
changed (this); /* EMIT SIGNAL */
Changed (); /* EMIT SIGNAL */
assert (_start >= 0);
assert (_end >= 0);
assert (_start.positive() || _start.zero());
assert (_end.positive() || _end.zero());
return 0;
}
void
Location::set_position_lock_style (PositionLockStyle ps)
Location::set_position_time_domain (TimeDomain domain)
{
if (_position_lock_style == ps) {
if (_start.time_domain() == domain) {
return;
}
_position_lock_style = ps;
if (ps == MusicTime) {
recompute_beat_from_samples (0);
if (domain == Temporal::BeatTime) {
_start = timepos_t (_start.beats());
_end = timepos_t (_end.beats());
} else {
_start = timepos_t (_start.samples());
_end = timepos_t (_end.samples());
}
position_lock_style_changed (this); /* EMIT SIGNAL */
PositionLockStyleChanged (); /* EMIT SIGNAL */
}
void
Location::recompute_beat_from_samples (const uint32_t sub_num)
{
_start_beat = _session.tempo_map().exact_beat_at_sample (_start, sub_num);
_end_beat = _session.tempo_map().exact_beat_at_sample (_end, sub_num);
}
void
Location::recompute_samples_from_beat ()
{
if (_position_lock_style != MusicTime) {
return;
}
TempoMap& map (_session.tempo_map());
set (map.sample_at_beat (_start_beat), map.sample_at_beat (_end_beat), false);
position_time_domain_changed (this); /* EMIT SIGNAL */
TimeDomainChanged (); /* EMIT SIGNAL */
}
void
@ -1184,11 +1082,10 @@ Locations::set_state (const XMLNode& node, int version)
Location* session_range_location = 0;
if (version < 3000) {
session_range_location = new Location (_session, 0, 0, _("session"), Location::IsSessionRange, 0);
session_range_location = new Location (_session, timepos_t (Temporal::AudioTime), timepos_t (Temporal::AudioTime), _("session"), Location::IsSessionRange);
new_locations.push_back (session_range_location);
}
XMLNodeConstIterator niter;
for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
@ -1358,10 +1255,10 @@ Locations::mark_at (samplepos_t pos, samplecnt_t slop) const
for (LocationList::const_iterator i = locations.begin(); i != locations.end(); ++i) {
if ((*i)->is_mark()) {
if (pos > (*i)->start()) {
delta = pos - (*i)->start();
if (pos > (*i)->start_sample()) {
delta = pos - (*i)->start_sample();
} else {
delta = (*i)->start() - pos;
delta = (*i)->start_sample() - pos;
}
if (slop == 0 && delta == 0) {
@ -1388,10 +1285,11 @@ Locations::first_mark_after (samplepos_t sample, bool include_special_ranges)
{
Glib::Threads::RWLock::ReaderLock lm (_lock);
for (LocationList::iterator i = locations.begin(); i != locations.end(); ++i) {
locs.push_back (make_pair ((*i)->start(), (*i)));
locs.push_back (make_pair ((*i)->start_sample(), (*i)));
if (!(*i)->is_mark()) {
locs.push_back (make_pair ((*i)->end(), (*i)));
locs.push_back (make_pair ((*i)->end_sample(), (*i)));
}
}
}
@ -1419,14 +1317,14 @@ Locations::first_mark_after (samplepos_t sample, bool include_special_ranges)
/** Look for the `marks' (either locations which are marks, or start/end points of range markers) either
* side of a sample. Note that if sample is exactly on a `mark', that mark will not be considered for returning
* as before/after.
* @param sample Frame to look for.
* @param before Filled in with the position of the last `mark' before `sample' (or max_samplepos if none exists)
* @param after Filled in with the position of the next `mark' after `sample' (or max_samplepos if none exists)
* @param pos position to be used
* @param before Filled in with the position of the last `mark' before `pos' (or max_timepos if none exists)
* @param after Filled in with the position of the next `mark' after `pos' (or max_timepos if none exists)
*/
void
Locations::marks_either_side (samplepos_t const sample, samplepos_t& before, samplepos_t& after) const
Locations::marks_either_side (timepos_t const & pos, timepos_t& before, timepos_t& after) const
{
before = after = max_samplepos;
before = after = std::numeric_limits<timepos_t>::max();
LocationList locs;
@ -1437,7 +1335,7 @@ Locations::marks_either_side (samplepos_t const sample, samplepos_t& before, sam
/* Get a list of positions; don't store any that are exactly on our requested position */
std::list<samplepos_t> positions;
std::list<timepos_t> positions;
for (LocationList::const_iterator i = locs.begin(); i != locs.end(); ++i) {
if (((*i)->is_auto_loop() || (*i)->is_auto_punch()) || (*i)->is_xrun()) {
@ -1446,14 +1344,14 @@ Locations::marks_either_side (samplepos_t const sample, samplepos_t& before, sam
if (!(*i)->is_hidden()) {
if ((*i)->is_mark ()) {
if ((*i)->start() != sample) {
if ((*i)->start() != pos) {
positions.push_back ((*i)->start ());
}
} else {
if ((*i)->start() != sample) {
if ((*i)->start() != pos) {
positions.push_back ((*i)->start ());
}
if ((*i)->end() != sample) {
if ((*i)->end() != pos) {
positions.push_back ((*i)->end ());
}
}
@ -1466,8 +1364,9 @@ Locations::marks_either_side (samplepos_t const sample, samplepos_t& before, sam
positions.sort ();
std::list<samplepos_t>::iterator i = positions.begin ();
while (i != positions.end () && *i < sample) {
std::list<timepos_t>::iterator i = positions.begin ();
while (i != positions.end () && *i < pos) {
++i;
}
@ -1567,7 +1466,7 @@ Locations::get_location_by_id(PBD::ID id)
}
void
Locations::find_all_between (samplepos_t start, samplepos_t end, LocationList& ll, Location::Flags flags)
Locations::find_all_between (timepos_t const & start, timepos_t const & end, LocationList& ll, Location::Flags flags)
{
Glib::Threads::RWLock::ReaderLock lm (_lock);
for (LocationList::const_iterator i = locations.begin(); i != locations.end(); ++i) {

View File

@ -913,7 +913,7 @@ LuaAPI::Vamp::initialize ()
}
int
LuaAPI::Vamp::analyze (boost::shared_ptr<ARDOUR::Readable> r, uint32_t channel, luabridge::LuaRef cb)
LuaAPI::Vamp::analyze (boost::shared_ptr<ARDOUR::AudioReadable> r, uint32_t channel, luabridge::LuaRef cb)
{
if (!_initialized) {
if (!initialize ()) {
@ -926,7 +926,7 @@ LuaAPI::Vamp::analyze (boost::shared_ptr<ARDOUR::Readable> r, uint32_t channel,
float* data = new float[_bufsize];
float* bufs[1] = { data };
samplecnt_t len = r->readable_length();
samplecnt_t len = r->readable_length_samples();
samplepos_t pos = 0;
int rv = 0;
@ -1003,9 +1003,9 @@ LuaAPI::Rubberband::Rubberband (boost::shared_ptr<AudioRegion> r, bool percussiv
, _cb (0)
{
_n_channels = r->n_channels ();
_read_len = r->length () / (double)r->stretch ();
_read_start = r->ancestral_start () + samplecnt_t (r->start () / (double)r->stretch ());
_read_offset = _read_start - r->start () + r->position ();
_read_len = r->length_samples () / (double)r->stretch ();
_read_start = r->ancestral_start_sample () + samplecnt_t (r->start_sample () / (double)r->stretch ());
_read_offset = _read_start - r->start_sample () + r->position_sample ();
}
LuaAPI::Rubberband::~Rubberband ()
@ -1052,13 +1052,13 @@ LuaAPI::Rubberband::read (Sample* buf, samplepos_t pos, samplecnt_t cnt, int cha
static void null_deleter (LuaAPI::Rubberband*) {}
boost::shared_ptr<Readable>
boost::shared_ptr<AudioReadable>
LuaAPI::Rubberband::readable ()
{
if (!_self) {
_self = boost::shared_ptr<Rubberband> (this, &null_deleter);
}
return boost::dynamic_pointer_cast<Readable> (_self);
return boost::dynamic_pointer_cast<AudioReadable> (_self);
}
bool
@ -1205,7 +1205,7 @@ LuaAPI::Rubberband::finalize ()
boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (*i);
assert (afs);
afs->done_with_peakfile_writes ();
afs->update_header (_region->position (), *now, xnow);
afs->update_header (_region->position_sample (), *now, xnow);
afs->mark_immutable ();
Analyser::queue_source_for_analysis (*i, false);
sl.push_back (*i);
@ -1216,10 +1216,10 @@ LuaAPI::Rubberband::finalize ()
PropertyList plist;
plist.add (Properties::start, 0);
plist.add (Properties::length, _region->length ());
plist.add (Properties::length, _region->length_samples ());
plist.add (Properties::name, region_name);
plist.add (Properties::whole_file, true);
plist.add (Properties::position, _region->position ());
plist.add (Properties::position, _region->position_sample ());
boost::shared_ptr<Region> r = RegionFactory::create (sl, plist);
boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion> (r);
@ -1231,9 +1231,9 @@ LuaAPI::Rubberband::finalize ()
ar->set_fade_out (_region->fade_out ());
*(ar->envelope ()) = *(_region->envelope ());
ar->set_ancestral_data (_read_start, _read_len, _stretch_ratio, _pitch_ratio);
ar->set_ancestral_data (timecnt_t (_read_start), timecnt_t (_read_len), _stretch_ratio, _pitch_ratio);
ar->set_master_sources (_region->master_sources ());
ar->set_length (ar->length () * _stretch_ratio, 0); // XXX
ar->set_length (ar->nt_length () * _stretch_ratio); // XXX
if (_stretch_ratio != 1.0) {
// TODO: apply mapping
ar->envelope ()->x_scale (_stretch_ratio);

View File

@ -26,10 +26,10 @@
#include "pbd/openuri.h"
#include "temporal/bbt_time.h"
#include "temporal/range.h"
#include "evoral/Control.h"
#include "evoral/ControlList.h"
#include "evoral/Range.h"
#include "ardour/amp.h"
#include "ardour/async_midi_port.h"
@ -199,7 +199,6 @@ CLASSKEYS(Selectable*);
CLASSKEYS(std::list<Selectable*>);
CLASSKEYS(ARDOUR::AudioEngine);
CLASSKEYS(ARDOUR::BeatsSamplesConverter);
CLASSKEYS(ARDOUR::BufferSet);
CLASSKEYS(ARDOUR::ChanCount);
CLASSKEYS(ARDOUR::ChanMapping);
@ -254,7 +253,7 @@ CLASSKEYS(std::list<Evoral::ControlEvent*>);
CLASSKEYS(std::vector<ARDOUR::Plugin::PresetRecord>);
CLASSKEYS(std::vector<boost::shared_ptr<ARDOUR::Processor> >);
CLASSKEYS(std::vector<boost::shared_ptr<ARDOUR::Source> >);
CLASSKEYS(std::vector<boost::shared_ptr<ARDOUR::Readable> >);
CLASSKEYS(std::vector<boost::shared_ptr<ARDOUR::AudioReadable> >);
CLASSKEYS(std::vector<Evoral::Parameter>);
CLASSKEYS(std::list<boost::shared_ptr<ARDOUR::PluginInfo> >); // PluginInfoList
@ -281,7 +280,7 @@ CLASSKEYS(boost::shared_ptr<ARDOUR::MidiRegion>);
CLASSKEYS(boost::shared_ptr<ARDOUR::MidiSource>);
CLASSKEYS(boost::shared_ptr<ARDOUR::PluginInfo>);
CLASSKEYS(boost::shared_ptr<ARDOUR::Processor>);
CLASSKEYS(boost::shared_ptr<ARDOUR::Readable>);
CLASSKEYS(boost::shared_ptr<ARDOUR::AudioReadable>);
CLASSKEYS(boost::shared_ptr<ARDOUR::Region>);
CLASSKEYS(boost::shared_ptr<ARDOUR::SessionPlaylists>);
CLASSKEYS(boost::shared_ptr<Evoral::ControlList>);
@ -582,7 +581,7 @@ LuaBindings::common (lua_State* L)
.addFunction ("set_interpolation", &Evoral::ControlList::set_interpolation)
.addFunction ("truncate_end", &Evoral::ControlList::truncate_end)
.addFunction ("truncate_start", &Evoral::ControlList::truncate_start)
.addFunction ("clear", (void (Evoral::ControlList::*)(double, double))&Evoral::ControlList::clear)
.addFunction ("clear", (void (Evoral::ControlList::*)(timepos_t const &, timepos_t const &))&Evoral::ControlList::clear)
.addFunction ("clear_list", (void (Evoral::ControlList::*)())&Evoral::ControlList::clear)
.addFunction ("in_write_pass", &Evoral::ControlList::in_write_pass)
.addFunction ("events", &Evoral::ControlList::events)
@ -605,10 +604,11 @@ LuaBindings::common (lua_State* L)
.addData ("logarithmic", &Evoral::ParameterDescriptor::logarithmic)
.endClass ()
.beginClass <Evoral::Range<samplepos_t> > ("Range")
.addConstructor <void (*) (samplepos_t, samplepos_t)> ()
.addData ("from", &Evoral::Range<samplepos_t>::from)
.addData ("to", &Evoral::Range<samplepos_t>::to)
.beginClass <Temporal::Range> ("Range")
.addConstructor <void (*) (timepos_t, timepos_t)> ()
.addFunction ("start", &Temporal::Range::start)
/* "end is a reserved Lua word */
.addFunction ("_end", &Temporal::Range::end)
.endClass ()
.deriveWSPtrClass <Evoral::Sequence<Temporal::Beats>, Evoral::ControlSet> ("Sequence")
@ -771,20 +771,13 @@ LuaBindings::common (lua_State* L)
.beginClass <Progress> ("Progress")
.endClass ()
.beginClass <MusicSample> ("MusicSample")
.addConstructor <void (*) (samplepos_t, int32_t)> ()
.addFunction ("set", &MusicSample::set)
.addData ("sample", &MusicSample::sample)
.addData ("division", &MusicSample::division)
.endClass ()
.beginClass <AudioRange> ("AudioRange")
.addConstructor <void (*) (samplepos_t, samplepos_t, uint32_t)> ()
.addFunction ("length", &AudioRange::length)
.addFunction ("equal", &AudioRange::equal)
.addData ("start", &AudioRange::start)
.addData ("_end", &AudioRange::end) // XXX "end" is a lua reserved word
.addData ("id", &AudioRange::id)
.beginClass <TimelineRange> ("TimelineRange")
.addConstructor <void (*) (timepos_t, timepos_t, uint32_t)> ()
.addFunction ("length", &TimelineRange::length)
.addFunction ("equal", &TimelineRange::equal)
.addFunction ("start", &TimelineRange::start)
.addFunction ("_end", &TimelineRange::end) // XXX "end" is a lua reserved word
.addData ("id", &TimelineRange::id)
.endClass ()
.beginWSPtrClass <PluginInfo> ("PluginInfo")
@ -1166,7 +1159,7 @@ LuaBindings::common (lua_State* L)
.addFunction ("lower_region", &Playlist::lower_region)
.addFunction ("raise_region_to_top", &Playlist::raise_region_to_top)
.addFunction ("lower_region_to_bottom", &Playlist::lower_region_to_bottom)
.addFunction ("duplicate", (void (Playlist::*)(boost::shared_ptr<Region>, samplepos_t, samplecnt_t, float))&Playlist::duplicate)
.addFunction ("duplicate", (void (Playlist::*)(boost::shared_ptr<Region>, timepos_t &, timecnt_t const &, float))&Playlist::duplicate)
.addFunction ("duplicate_until", &Playlist::duplicate_until)
.addFunction ("duplicate_range", &Playlist::duplicate_range)
.addFunction ("combine", &Playlist::combine)
@ -1178,7 +1171,7 @@ LuaBindings::common (lua_State* L)
.addFunction ("split_region", &Playlist::split_region)
.addFunction ("get_orig_track_id", &Playlist::get_orig_track_id)
//.addFunction ("split", &Playlist::split) // XXX needs MusicSample
.addFunction ("cut", (boost::shared_ptr<Playlist> (Playlist::*)(std::list<AudioRange>&, bool))&Playlist::cut)
.addFunction ("cut", (boost::shared_ptr<Playlist> (Playlist::*)(std::list<TimelineRange>&, bool))&Playlist::cut)
#if 0
.addFunction ("copy", &Playlist::copy)
.addFunction ("paste", &Playlist::paste)
@ -1239,28 +1232,27 @@ LuaBindings::common (lua_State* L)
.addFunction ("write_immediate_event", &MidiTrack::write_immediate_event)
.endClass ()
.beginWSPtrClass <Readable> ("Readable")
.addFunction ("read", &Readable::read)
.addFunction ("readable_length", &Readable::readable_length)
.addFunction ("n_channels", &Readable::n_channels)
.addStaticFunction ("load", &Readable::load)
.beginWSPtrClass <AudioReadable> ("Readable")
.addFunction ("read", &AudioReadable::read)
.addFunction ("readable_length", &AudioReadable::readable_length_samples)
.addFunction ("n_channels", &AudioReadable::n_channels)
.addStaticFunction ("load", &AudioReadable::load)
.endClass ()
.deriveWSPtrClass <AudioRom, Readable> ("AudioRom")
.deriveWSPtrClass <AudioRom, AudioReadable> ("AudioRom")
.addStaticFunction ("new_rom", &AudioRom::new_rom)
.endClass ()
.deriveWSPtrClass <Region, SessionObject> ("Region")
.addCast<Readable> ("to_readable")
.addCast<MidiRegion> ("to_midiregion")
.addCast<AudioRegion> ("to_audioregion")
.addFunction ("playlist", &Region::playlist)
.addFunction ("set_name", &Region::set_name)
/* properties */
.addFunction ("position", &Region::position)
.addFunction ("start", &Region::start)
.addFunction ("length", &Region::length)
.addFunction ("position", &Region::nt_position)
.addFunction ("start", &Region::nt_start)
.addFunction ("length", &Region::nt_length)
.addFunction ("layer", &Region::layer)
.addFunction ("data_type", &Region::data_type)
.addFunction ("stretch", &Region::stretch)
@ -1280,7 +1272,7 @@ LuaBindings::common (lua_State* L)
.addFunction ("sync_marked", &Region::sync_marked)
.addFunction ("external", &Region::external)
.addFunction ("import", &Region::import)
.addFunction ("covers", &Region::covers)
.addFunction ("covers", (bool (Region::*)(timepos_t const &) const) &Region::covers)
.addFunction ("at_natural_position", &Region::at_natural_position)
.addFunction ("is_compound", &Region::is_compound)
.addFunction ("captured_xruns", &Region::captured_xruns)
@ -1298,7 +1290,6 @@ LuaBindings::common (lua_State* L)
.addFunction ("move_start", &Region::move_start)
.addFunction ("master_sources", &Region::master_sources)
.addFunction ("master_source_names", &Region::master_source_names)
.addFunction ("n_channels", &Region::n_channels)
.addFunction ("trim_front", &Region::trim_front)
.addFunction ("trim_end", &Region::trim_end)
.addFunction ("trim_to", &Region::trim_to)
@ -1310,7 +1301,6 @@ 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 ("quarter_note", &Region::quarter_note)
.addFunction ("set_hidden", &Region::set_hidden)
.addFunction ("set_muted", &Region::set_muted)
.addFunction ("set_opaque", &Region::set_opaque)
@ -1325,11 +1315,11 @@ LuaBindings::common (lua_State* L)
.addFunction ("do_export", &MidiRegion::do_export)
.addFunction ("midi_source", &MidiRegion::midi_source)
.addFunction ("model", (boost::shared_ptr<MidiModel> (MidiRegion::*)())&MidiRegion::model)
.addFunction ("start_beats", &MidiRegion::start_beats)
.addFunction ("length_beats", &MidiRegion::length_beats)
.endClass ()
.deriveWSPtrClass <AudioRegion, Region> ("AudioRegion")
.addCast<AudioReadable> ("to_readable")
.addFunction ("n_channels", &AudioRegion::n_channels)
.addFunction ("audio_source", &AudioRegion::audio_source)
.addFunction ("set_scale_amplitude", &AudioRegion::set_scale_amplitude)
.addFunction ("scale_amplitude", &AudioRegion::scale_amplitude)
@ -1383,8 +1373,8 @@ LuaBindings::common (lua_State* L)
.endClass ()
.deriveWSPtrClass <AudioSource, Source> ("AudioSource")
.addCast<Readable> ("to_readable")
.addFunction ("readable_length", &AudioSource::readable_length)
.addCast<AudioReadable> ("to_readable")
.addFunction ("readable_length", &AudioSource::readable_length_samples)
.addFunction ("n_channels", &AudioSource::n_channels)
.addFunction ("empty", &Source::empty)
.addFunction ("length", &Source::length)
@ -1745,7 +1735,7 @@ LuaBindings::common (lua_State* L)
.endClass ()
.deriveWSPtrClass <AudioSource, Source> ("AudioSource")
.addFunction ("readable_length", &AudioSource::readable_length)
.addFunction ("readable_length", &AudioSource::readable_length_samples)
.addFunction ("n_channels", &AudioSource::n_channels)
.endClass ()
@ -1795,8 +1785,8 @@ LuaBindings::common (lua_State* L)
.beginStdVector <boost::shared_ptr<Source> > ("SourceList")
.endClass ()
// typedef std::vector<boost::shared_ptr<Readable> >
.beginStdVector <boost::shared_ptr<Readable> > ("ReadableList")
// typedef std::vector<boost::shared_ptr<AudioReadable> >
.beginStdVector <boost::shared_ptr<AudioReadable> > ("ReadableList")
.endClass ()
// from SessionPlaylists: std::vector<boost::shared_ptr<Playlist > >
@ -1844,17 +1834,12 @@ LuaBindings::common (lua_State* L)
.beginConstStdList <boost::shared_ptr<Port> > ("PortList")
.endClass ()
// used by Playlist::cut/copy
.beginConstStdList <AudioRange> ("AudioRangeList")
.endClass ()
.beginConstStdCPtrList <Location> ("LocationList")
.endClass ()
.beginConstStdVector <Evoral::Parameter> ("ParameterList")
.endClass ()
// std::list<boost::shared_ptr<AutomationControl> > ControlList
.beginStdList <boost::shared_ptr<AutomationControl> > ("ControlList")
.endClass ()
@ -1897,12 +1882,6 @@ LuaBindings::common (lua_State* L)
.addFunction ("samples_per_grid", &Meter::samples_per_grid)
.endClass ()
.beginClass <BeatsSamplesConverter> ("BeatsSamplesConverter")
.addConstructor <void (*) (const TempoMap&, samplepos_t)> ()
.addFunction ("to", &BeatsSamplesConverter::to)
.addFunction ("from", &BeatsSamplesConverter::from)
.endClass ()
.beginClass <TempoMap> ("TempoMap")
.addFunction ("add_tempo", &TempoMap::add_tempo)
.addFunction ("add_meter", &TempoMap::add_meter)
@ -2666,7 +2645,7 @@ LuaBindings::common (lua_State* L)
.addFunction ("set_strech_and_pitch", &ARDOUR::LuaAPI::Rubberband::set_strech_and_pitch)
.addFunction ("set_mapping", &ARDOUR::LuaAPI::Rubberband::set_mapping)
.addFunction ("process", &ARDOUR::LuaAPI::Rubberband::process)
.addFunction ("readable_length", &ARDOUR::LuaAPI::Rubberband::readable_length)
.addFunction ("readable_length", &ARDOUR::LuaAPI::Rubberband::readable_length_samples)
.addFunction ("n_channels", &ARDOUR::LuaAPI::Rubberband::n_channels)
.addFunction ("readable", &ARDOUR::LuaAPI::Rubberband::readable)
.endClass ()

View File

@ -2934,9 +2934,9 @@ LV2Plugin::connect_and_run(BufferSet& bufs,
assert (start + samples - _current_latency >= 0);
if (c->guard) {
c->guard = false;
c->ac->list()->add (when, v, true, true);
c->ac->list()->add (timepos_t (when), v, true, true);
} else {
c->ac->set_double (v, when, true);
c->ac->set_double (v, timepos_t (when), true);
}
}
}
@ -2993,7 +2993,7 @@ LV2Plugin::connect_and_run(BufferSet& bufs,
AutomationCtrlPtr c = get_automation_control (p);
DEBUG_TRACE(DEBUG::LV2Automate, string_compose ("Start Touch p: %1\n", p));
if (c) {
c->ac->start_touch (std::max ((samplepos_t)0, start - _current_latency));
c->ac->start_touch (timepos_t (std::max ((samplepos_t)0, start - _current_latency)));
c->guard = true;
}
}
@ -3008,7 +3008,7 @@ LV2Plugin::connect_and_run(BufferSet& bufs,
AutomationCtrlPtr c = get_automation_control (p);
DEBUG_TRACE(DEBUG::LV2Automate, string_compose ("End Touch p: %1\n", p));
if (c) {
c->ac->stop_touch (std::max ((samplepos_t)0, start - _current_latency));
c->ac->stop_touch (timepos_t (std::max ((samplepos_t)0, start - _current_latency)));
}
}
}

View File

@ -1472,16 +1472,16 @@ MidiModel::resolve_overlaps_unlocked (const NotePtr note, void* arg)
TimeType sb = (*i)->time();
TimeType eb = (*i)->end_time();
OverlapType overlap = OverlapNone;
Temporal::OverlapType overlap = Temporal::OverlapNone;
if ((sb > sa) && (eb <= ea)) {
overlap = OverlapInternal;
overlap = Temporal::OverlapInternal;
} else if ((eb > sa) && (eb <= ea)) {
overlap = OverlapStart;
overlap = Temporal::OverlapStart;
} else if ((sb > sa) && (sb < ea)) {
overlap = OverlapEnd;
overlap = Temporal::OverlapEnd;
} else if ((sa >= sb) && (sa <= eb) && (ea <= eb)) {
overlap = OverlapExternal;
overlap = Temporal::OverlapExternal;
} else {
/* no overlap */
continue;
@ -1497,7 +1497,7 @@ MidiModel::resolve_overlaps_unlocked (const NotePtr note, void* arg)
}
switch (overlap) {
case OverlapStart:
case Temporal::OverlapStart:
cerr << "OverlapStart\n";
/* existing note covers start of new note */
switch (insert_merge_policy()) {
@ -1530,7 +1530,7 @@ MidiModel::resolve_overlaps_unlocked (const NotePtr note, void* arg)
}
break;
case OverlapEnd:
case Temporal::OverlapEnd:
cerr << "OverlapEnd\n";
/* existing note covers end of new note */
switch (insert_merge_policy()) {
@ -1566,7 +1566,7 @@ MidiModel::resolve_overlaps_unlocked (const NotePtr note, void* arg)
}
break;
case OverlapExternal:
case Temporal::OverlapExternal:
cerr << "OverlapExt\n";
/* existing note overlaps all the new note */
switch (insert_merge_policy()) {
@ -1585,7 +1585,7 @@ MidiModel::resolve_overlaps_unlocked (const NotePtr note, void* arg)
}
break;
case OverlapInternal:
case Temporal::OverlapInternal:
cerr << "OverlapInt\n";
/* new note fully overlaps an existing note */
switch (insert_merge_policy()) {
@ -1784,7 +1784,7 @@ MidiModel::insert_silence_at_start (TimeType t)
for (Controls::iterator i = controls().begin(); i != controls().end(); ++i) {
boost::shared_ptr<AutomationControl> ac = boost::dynamic_pointer_cast<AutomationControl> (i->second);
XMLNode& before = ac->alist()->get_state ();
i->second->list()->shift (0, t.to_double());
i->second->list()->shift (timepos_t::zero (i->second->list()->time_domain()), timecnt_t (t));
XMLNode& after = ac->alist()->get_state ();
s->session().add_command (new MementoCommand<AutomationList> (new MidiAutomationListBinder (s, i->first), &before, &after));
}
@ -1801,7 +1801,7 @@ MidiModel::insert_silence_at_start (TimeType t)
apply_command_as_subcommand (s->session(), c);
}
ContentsShifted (t.to_double());
ContentsShifted (timecnt_t (t));
}
void

View File

@ -78,8 +78,8 @@ MidiPlaylist::MidiPlaylist (boost::shared_ptr<const MidiPlaylist> other, string
}
MidiPlaylist::MidiPlaylist (boost::shared_ptr<const MidiPlaylist> other,
samplepos_t start,
samplecnt_t dur,
timepos_t const & start,
timepos_t const & dur,
string name,
bool hidden)
: Playlist (other, start, dur, name, hidden)
@ -149,9 +149,9 @@ MidiPlaylist::dump () const
for (RegionList::const_iterator i = regions.begin(); i != regions.end(); ++i) {
r = *i;
cerr << " " << r->name() << " @ " << r << " ["
<< r->start() << "+" << r->length()
<< r->nt_start() << "+" << r->nt_length()
<< "] at "
<< r->position()
<< r->nt_position()
<< " on layer "
<< r->layer ()
<< endl;
@ -196,14 +196,14 @@ MidiPlaylist::destroy_region (boost::shared_ptr<Region> region)
return changed;
}
void
MidiPlaylist::_split_region (boost::shared_ptr<Region> region, const MusicSample& playlist_position, ThawList& thawlist)
MidiPlaylist::_split_region (boost::shared_ptr<Region> region, timepos_t const & playlist_position, Thawlist& thawlist)
{
if (!region->covers (playlist_position.sample)) {
if (!region->covers (playlist_position)) {
return;
}
if (region->position() == playlist_position.sample ||
region->last_sample() == playlist_position.sample) {
if (region->nt_position() == playlist_position ||
region->nt_last() == playlist_position) {
return;
}
@ -218,18 +218,16 @@ MidiPlaylist::_split_region (boost::shared_ptr<Region> region, const MusicSample
string before_name;
string after_name;
const double before_qn = _session.tempo_map().exact_qn_at_sample (playlist_position.sample, playlist_position.division) - region->quarter_note();
const double after_qn = mr->length_beats() - before_qn;
MusicSample before (playlist_position.sample - region->position(), playlist_position.division);
MusicSample after (region->length() - before.sample, playlist_position.division);
const timecnt_t before = region->nt_position().distance (playlist_position);
const timecnt_t after = region->nt_length() - before;
RegionFactory::region_name (before_name, region->name(), false);
{
PropertyList plist;
plist.add (Properties::length, before.sample);
plist.add (Properties::length_beats, before_qn);
plist.add (Properties::length, before);
plist.add (Properties::name, before_name);
plist.add (Properties::left_of_split, true);
plist.add (Properties::layering_index, region->layering_index ());
@ -239,7 +237,7 @@ MidiPlaylist::_split_region (boost::shared_ptr<Region> region, const MusicSample
since it supplies that offset to the Region constructor, which
is necessary to get audio region gain envelopes right.
*/
left = RegionFactory::create (region, MusicSample (0, 0), plist, true, &thawlist);
left = RegionFactory::create (region, plist, true, &thawlist);
}
RegionFactory::region_name (after_name, region->name(), false);
@ -247,8 +245,7 @@ MidiPlaylist::_split_region (boost::shared_ptr<Region> region, const MusicSample
{
PropertyList plist;
plist.add (Properties::length, after.sample);
plist.add (Properties::length_beats, after_qn);
plist.add (Properties::length, after);
plist.add (Properties::name, after_name);
plist.add (Properties::right_of_split, true);
plist.add (Properties::layering_index, region->layering_index ());
@ -258,8 +255,8 @@ MidiPlaylist::_split_region (boost::shared_ptr<Region> region, const MusicSample
right = RegionFactory::create (region, before, plist, true, &thawlist);
}
add_region_internal (left, region->position(), thawlist, 0, region->quarter_note(), true);
add_region_internal (right, region->position() + before.sample, thawlist, before.division, region->quarter_note() + before_qn, true);
add_region_internal (left, region->nt_position(), thawlist);
add_region_internal (right, region->nt_position() + before, thawlist);
remove_region_internal (region, thawlist);
}

View File

@ -1,204 +0,0 @@
/*
* Copyright (C) 2011-2015 David Robillard <d@drobilla.net>
* Copyright (C) 2011-2017 Paul Davis <paul@linuxaudiosystems.com>
* Copyright (C) 2014-2019 Robin Gareus <robin@gareus.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifdef WAF_BUILD
#include "libardour-config.h"
#endif
#include "pbd/error.h"
#include "ardour/midi_playlist.h"
#include "ardour/midi_playlist_source.h"
#include "pbd/i18n.h"
using namespace std;
using namespace ARDOUR;
using namespace PBD;
namespace ARDOUR {
class MidiStateTracker;
class Session;
template <typename T> class MidiRingBuffer;
}
namespace Evoral {
template <typename T> class EventSink;
template <typename Time> class Event;
}
/*******************************************************************************
As of May 2011, it appears too complex to support compound regions for MIDI
because of the need to be able to edit the data represented by the region. It
seems that it would be a better idea to render the consituent regions into a
new MIDI file and create a new region based on that, an operation we have been
calling "consolidate"
This code has been in place as a stub in case anyone gets any brilliant ideas
on other ways to approach this issue.
********************************************************************************/
MidiPlaylistSource::MidiPlaylistSource (Session& s, const ID& orig, const std::string& name, boost::shared_ptr<MidiPlaylist> p,
uint32_t /*chn*/, sampleoffset_t begin, samplecnt_t len, Source::Flag flags)
: Source (s, DataType::MIDI, name)
, MidiSource (s, name, flags)
, PlaylistSource (s, orig, name, p, DataType::MIDI, begin, len, flags)
{
}
MidiPlaylistSource::MidiPlaylistSource (Session& s, const XMLNode& node)
: Source (s, node)
, MidiSource (s, node)
, PlaylistSource (s, node)
{
/* PlaylistSources are never writable, renameable or removable */
_flags = Flag (_flags & ~(Writable|CanRename|Removable|RemovableIfEmpty|RemoveAtDestroy));
/* ancestors have already called ::set_state() in their XML-based
constructors.
*/
if (set_state (node, Stateful::loading_state_version, false)) {
throw failed_constructor ();
}
}
MidiPlaylistSource::~MidiPlaylistSource ()
{
}
XMLNode&
MidiPlaylistSource::get_state ()
{
XMLNode& node (MidiSource::get_state ());
/* merge PlaylistSource state */
PlaylistSource::add_state (node);
return node;
}
int
MidiPlaylistSource::set_state (const XMLNode& node, int version)
{
return set_state (node, version, true);
}
int
MidiPlaylistSource::set_state (const XMLNode& node, int version, bool with_descendants)
{
if (with_descendants) {
if (Source::set_state (node, version) ||
MidiSource::set_state (node, version) ||
PlaylistSource::set_state (node, version)) {
return -1;
}
}
return 0;
}
samplecnt_t
MidiPlaylistSource::length (samplepos_t) const
{
pair<samplepos_t,samplepos_t> extent = _playlist->get_extent();
return extent.second - extent.first;
}
samplecnt_t
MidiPlaylistSource::read_unlocked (const Lock& lock,
Evoral::EventSink<samplepos_t>& dst,
samplepos_t /*position*/,
samplepos_t start,
samplecnt_t cnt,
Evoral::Range<samplepos_t>* loop_range,
MidiStateTracker*,
MidiChannelFilter*) const
{
boost::shared_ptr<MidiPlaylist> mp = boost::dynamic_pointer_cast<MidiPlaylist> (_playlist);
if (!mp) {
return 0;
}
/* XXX paul says on Oct 26 2019:
rgareus: so to clarify now that i have better perspective: the API i want to get rid of is MidiPlaylist::read() ; everything that used it (i.e. the DiskReader) should use MidiPlaylist::rendered()->read()
rgareus: but a "read" operation is also a "write" operation: you have to put the data somewhere
rgareus: the only other user of MidiPlaylist::read() was MidiPlaylistSource (unsurprisingly), which as I noted is not even (really) used
rgareus: ::rendered() returns a ptr-to-RT_MidiBuffer, which has a read method which expects to write into a MidiBuffer, using push_back()
rgareus: but MidiPlaylistSource::read() is given an EventSink<samplepos_t> as the destination, and this does not (currently) have ::push_back(), only ::write() (which is willing to deal with inserts rather than appends)
rgareus: so, this is the API "mess" I'm trying to clean up. simple solution: since we don't use MidiPlaylistSource just comment out the line and forget about it for now, then remove MidiPlaylist::read() and move on
This represents that decision, for now.
*/
return cnt; // mp->read (dst, start, cnt, loop_range);
}
samplecnt_t
MidiPlaylistSource::write_unlocked (const Lock&,
MidiRingBuffer<samplepos_t>&,
samplepos_t,
samplecnt_t)
{
fatal << string_compose (_("programming error: %1"), "MidiPlaylistSource::write_unlocked() called - should be impossible") << endmsg;
abort(); /*NOTREACHED*/
return 0;
}
void
MidiPlaylistSource::append_event_beats(const Glib::Threads::Mutex::Lock& /*lock*/, const Evoral::Event<Temporal::Beats>& /*ev*/)
{
fatal << string_compose (_("programming error: %1"), "MidiPlaylistSource::append_event_beats() called - should be impossible") << endmsg;
abort(); /*NOTREACHED*/
}
void
MidiPlaylistSource::append_event_samples(const Glib::Threads::Mutex::Lock& /*lock*/, const Evoral::Event<samplepos_t>& /* ev */, samplepos_t /*source_start*/)
{
fatal << string_compose (_("programming error: %1"), "MidiPlaylistSource::append_event_samples() called - should be impossible") << endmsg;
abort(); /*NOTREACHED*/
}
void
MidiPlaylistSource::load_model (const Glib::Threads::Mutex::Lock&, bool)
{
/* nothing to do */
}
void
MidiPlaylistSource::destroy_model (const Glib::Threads::Mutex::Lock&)
{
/* nothing to do */
}
void
MidiPlaylistSource::flush_midi (const Lock& lock)
{
}
bool
MidiPlaylistSource::empty () const
{
return !_playlist || _playlist->empty();
}

View File

@ -60,18 +60,9 @@ using namespace std;
using namespace ARDOUR;
using namespace PBD;
namespace ARDOUR {
namespace Properties {
PBD::PropertyDescriptor<double> start_beats;
PBD::PropertyDescriptor<double> length_beats;
}
}
/* Basic MidiRegion constructor (many channels) */
MidiRegion::MidiRegion (const SourceList& srcs)
: Region (srcs)
, _start_beats (Properties::start_beats, 0.0)
, _length_beats (Properties::length_beats, midi_source(0)->length_beats().to_double())
, _ignore_shift (false)
{
midi_source(0)->ModelChanged.connect_same_thread (_source_connection, boost::bind (&MidiRegion::model_changed, this));
@ -82,8 +73,6 @@ MidiRegion::MidiRegion (const SourceList& srcs)
MidiRegion::MidiRegion (boost::shared_ptr<const MidiRegion> other)
: Region (other)
, _start_beats (Properties::start_beats, other->_start_beats)
, _length_beats (Properties::length_beats, other->_length_beats)
, _ignore_shift (false)
{
assert(_name.val().find("/") == string::npos);
@ -94,8 +83,6 @@ 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, timecnt_t const & offset)
: Region (other, offset)
, _start_beats (Properties::start_beats, other->_start_beats)
, _length_beats (Properties::length_beats, other->_length_beats)
, _ignore_shift (false)
{
@ -118,17 +105,13 @@ MidiRegion::do_export (string path) const
/* caller must check for pre-existing file */
assert (!path.empty());
assert (!Glib::file_test (path, Glib::FILE_TEST_EXISTS));
newsrc = boost::dynamic_pointer_cast<MidiSource>(SourceFactory::createWritable(DataType::MIDI, _session, path, _session.sample_rate()));
BeatsSamplesConverter bfc (_session.tempo_map(), _position);
Temporal::Beats const bbegin = bfc.from (_start);
Temporal::Beats const bend = bfc.from (_start + _length);
newsrc = boost::dynamic_pointer_cast<MidiSource>(SourceFactory::createWritable(DataType::MIDI, _session, path, false, _session.sample_rate()));
{
/* Lock our source since we'll be reading from it. write_to() will
take a lock on newsrc. */
Source::Lock lm (midi_source(0)->mutex());
if (midi_source(0)->export_write_to (lm, newsrc, bbegin, bend)) {
if (midi_source(0)->export_write_to (lm, newsrc, _start.val().beats(), _start.val().beats() + _length.val().beats())) {
return false;
}
}
@ -155,9 +138,8 @@ MidiRegion::clone (string path) const
boost::shared_ptr<MidiRegion>
MidiRegion::clone (boost::shared_ptr<MidiSource> newsrc, ThawList* tl) const
{
BeatsSamplesConverter bfc (_session.tempo_map(), _position);
Temporal::Beats const bbegin = bfc.from (_start);
Temporal::Beats const bend = bfc.from (_start + _length);
Temporal::Beats const bbegin = _start.val().beats ();
Temporal::Beats const bend = _start.val().beats() + _length.val().beats();
{
boost::shared_ptr<MidiSource> ms = midi_source(0);
@ -181,215 +163,80 @@ MidiRegion::clone (boost::shared_ptr<MidiSource> newsrc, ThawList* tl) const
plist.add (Properties::name, PBD::basename_nosuffix (newsrc->name()));
plist.add (Properties::whole_file, true);
plist.add (Properties::start, _start);
plist.add (Properties::start_beats, _start_beats);
plist.add (Properties::length, _length);
plist.add (Properties::position, _position);
plist.add (Properties::beat, _beat);
plist.add (Properties::length_beats, _length_beats);
plist.add (Properties::layer, 0);
boost::shared_ptr<MidiRegion> ret (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (newsrc, plist, true, tl)));
ret->set_quarter_note (quarter_note());
return ret;
}
void
MidiRegion::post_set (const PropertyChange& pc)
{
Region::post_set (pc);
if (pc.contains (Properties::length) && !pc.contains (Properties::length_beats)) {
/* we're called by Stateful::set_values() which sends a change
only if the value is different from _current.
session load means we can clobber length_beats here in error (not all properties differ from current),
so disallow (this has been set from XML state anyway).
*/
if (!_session.loading()) {
update_length_beats (0);
}
}
if (pc.contains (Properties::start) && !pc.contains (Properties::start_beats)) {
set_start_beats_from_start_samples ();
}
}
void
MidiRegion::set_start_beats_from_start_samples ()
{
if (position_lock_style() == AudioTime) {
_start_beats = quarter_note() - _session.tempo_map().quarter_note_at_sample (_position - _start);
}
}
void
MidiRegion::set_length_internal (samplecnt_t len, const int32_t sub_num)
{
Region::set_length_internal (len, sub_num);
update_length_beats (sub_num);
}
void
MidiRegion::update_after_tempo_map_change (bool /* send */)
{
boost::shared_ptr<Playlist> pl (playlist());
if (!pl) {
return;
}
const samplepos_t old_pos = _position;
const samplepos_t old_length = _length;
const samplepos_t old_start = _start;
PropertyChange s_and_l;
if (position_lock_style() == AudioTime) {
recompute_position_from_lock_style (0);
/*
set _start to new position in tempo map.
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 (?).
We could arguably use _start to set _start_beats here,
resulting in viewport-like behaviour (the contents maintain
their musical position while the region is stationary).
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().samples_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_sample (_position + _length) - quarter_note();
s_and_l.add (Properties::start);
s_and_l.add (Properties::length_beats);
send_change (s_and_l);
return;
}
Region::update_after_tempo_map_change (false);
/* _start has now been updated. */
_length = max ((samplecnt_t) 1, _session.tempo_map().samples_between_quarter_notes (quarter_note(), quarter_note() + _length_beats));
if (old_start != _start) {
s_and_l.add (Properties::start);
}
if (old_length != _length) {
s_and_l.add (Properties::length);
}
if (old_pos != _position) {
s_and_l.add (Properties::position);
}
send_change (s_and_l);
}
void
MidiRegion::update_length_beats (const int32_t sub_num)
{
_length_beats = _session.tempo_map().exact_qn_at_sample (_position + _length, sub_num) - quarter_note();
}
void
MidiRegion::set_position_internal (timepos_t const & pos, bool allow_bbt_recompute, const int32_t sub_num)
{
Region::set_position_internal (pos, allow_bbt_recompute, sub_num);
/* don't clobber _start _length and _length_beats if session loading.*/
if (_session.loading()) {
return;
}
/* set _start to new position in tempo map */
_start = _session.tempo_map().samples_between_quarter_notes (quarter_note() - start_beats(), quarter_note());
/* in construction from src */
if (_length_beats == 0.0) {
update_length_beats (sub_num);
}
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).
*/
Region::set_length_internal (_session.tempo_map().samples_between_quarter_notes (quarter_note(), quarter_note() + length_beats()), sub_num);
}
}
samplecnt_t
timecnt_t
MidiRegion::read_at (Evoral::EventSink<samplepos_t>& out,
samplepos_t position,
samplecnt_t dur,
Evoral::Range<samplepos_t>* loop_range,
MidiCursor& cursor,
uint32_t chan_n,
NoteMode mode,
MidiStateTracker* tracker,
MidiChannelFilter* filter) const
timepos_t const & position,
timecnt_t const & dur,
Temporal::Range* loop_range,
MidiCursor& cursor,
uint32_t chan_n,
NoteMode mode,
MidiStateTracker* tracker,
MidiChannelFilter* filter) const
{
return _read_at (_sources, out, position, dur, loop_range, cursor, chan_n, mode, tracker, filter);
}
samplecnt_t
timecnt_t
MidiRegion::master_read_at (MidiRingBuffer<samplepos_t>& out,
samplepos_t position,
samplecnt_t dur,
Evoral::Range<samplepos_t>* loop_range,
MidiCursor& cursor,
uint32_t chan_n,
NoteMode mode) const
timepos_t const & position,
timecnt_t const & dur,
Temporal::Range* loop_range,
MidiCursor& cursor,
uint32_t chan_n,
NoteMode mode) const
{
return _read_at (_master_sources, out, position, dur, loop_range, cursor, chan_n, mode); /* no tracker */
}
samplecnt_t
timecnt_t
MidiRegion::_read_at (const SourceList& /*srcs*/,
Evoral::EventSink<samplepos_t>& dst,
samplepos_t position,
samplecnt_t dur,
Evoral::Range<samplepos_t>* loop_range,
MidiCursor& cursor,
uint32_t chan_n,
NoteMode mode,
MidiStateTracker* tracker,
MidiChannelFilter* filter) const
timepos_t const & position,
timecnt_t const & xdur,
Temporal::Range* loop_range,
MidiCursor& cursor,
uint32_t chan_n,
NoteMode mode,
MidiStateTracker* tracker,
MidiChannelFilter* filter) const
{
sampleoffset_t internal_offset = 0;
samplecnt_t to_read = 0;
timecnt_t dur (xdur);
timecnt_t internal_offset;
timecnt_t to_read;
/* precondition: caller has verified that we cover the desired section */
assert(chan_n == 0);
if (muted()) {
return 0; /* read nothing */
return timecnt_t(); /* read nothing */
}
if (position < _position) {
/* we are starting the read from before the start of the region */
internal_offset = 0;
dur -= _position - position;
dur -= position.distance (_position);
} else {
/* we are starting the read from after the start of the region */
internal_offset = position - _position;
internal_offset = _position.val().distance (position);
}
if (internal_offset >= _length) {
return 0; /* read nothing */
return timecnt_t(); /* read nothing */
}
if ((to_read = min (dur, _length - internal_offset)) == 0) {
return 0; /* read nothing */
return timecnt_t(); /* read nothing */
}
boost::shared_ptr<MidiSource> src = midi_source(chan_n);
@ -416,18 +263,16 @@ MidiRegion::_read_at (const SourceList& /*srcs*/,
if (src->midi_read (
lm, // source lock
dst, // destination buffer
_position - _start, // start position of the source in session samples
_start + internal_offset, // where to start reading in the source
_position.val().earlier (_start.val()), // start position of the source on timeline
_start.val() + internal_offset, // where to start reading in the source
to_read, // read duration in samples
loop_range,
cursor,
tracker,
filter,
_filtered_parameters,
quarter_note(),
_start_beats
_filtered_parameters
) != to_read) {
return 0; /* "read nothing" */
return timecnt_t(); /* "read nothing" */
}
return to_read;
@ -440,7 +285,7 @@ MidiRegion::render (Evoral::EventSink<samplepos_t>& dst,
NoteMode mode,
MidiChannelFilter* filter) const
{
sampleoffset_t internal_offset = 0;
timecnt_t internal_offset;
/* precondition: caller has verified that we cover the desired section */
@ -453,12 +298,12 @@ MidiRegion::render (Evoral::EventSink<samplepos_t>& dst,
/* dump pulls from zero to infinity ... */
if (_position) {
if (!_position.val().zero()) {
/* we are starting the read from before the start of the region */
internal_offset = 0;
} else {
/* we are starting the read from after the start of the region */
internal_offset = -_position;
internal_offset = timecnt_t (-_position.val());
}
if (internal_offset >= _length) {
@ -492,22 +337,21 @@ MidiRegion::render (Evoral::EventSink<samplepos_t>& dst,
src->midi_read (
lm, // source lock
dst, // destination buffer
_position - _start, // start position of the source in session samples
_start + internal_offset, // where to start reading in the source
this->source_position(), // start position of the source in session samples
this->nt_start() + internal_offset, // where to start reading in the source
_length, // length to read
0,
cursor,
&tracker,
filter,
_filtered_parameters,
quarter_note(),
_start_beats);
_filtered_parameters);
/* resolve any notes that were "cut off" by the end of the region. The
* Note-Off's get inserted at the end of the region
*/
tracker.resolve_notes (dst, (_position - _start) + (_start + internal_offset + _length));
const timepos_t end = source_position() + nt_start() + internal_offset + nt_length();
tracker.resolve_notes (dst, end.samples());
return 0;
}
@ -639,7 +483,7 @@ MidiRegion::model_contents_changed ()
}
void
MidiRegion::model_shifted (double qn_distance)
MidiRegion::model_shifted (timecnt_t distance)
{
if (!model()) {
return;
@ -647,11 +491,8 @@ MidiRegion::model_shifted (double qn_distance)
if (!_ignore_shift) {
PropertyChange what_changed;
_start_beats += qn_distance;
samplepos_t const new_start = _session.tempo_map().samples_between_quarter_notes (_quarter_note - _start_beats, _quarter_note);
_start = new_start;
_start += distance;
what_changed.add (Properties::start);
what_changed.add (Properties::start_beats);
what_changed.add (Properties::contents);
send_change (what_changed);
} else {
@ -690,90 +531,11 @@ MidiRegion::model_automation_state_changed (Evoral::Parameter const & p)
void
MidiRegion::fix_negative_start ()
{
BeatsSamplesConverter c (_session.tempo_map(), _position);
_ignore_shift = true;
model()->insert_silence_at_start (Temporal::Beats (- _start_beats));
model()->insert_silence_at_start (-_start.val().beats());
_start = 0;
_start_beats = 0.0;
}
void
MidiRegion::set_start_internal (samplecnt_t s, const int32_t sub_num)
{
Region::set_start_internal (s, sub_num);
set_start_beats_from_start_samples ();
}
void
MidiRegion::trim_to_internal (timepos_t const & position, samplecnt_t length, const int32_t sub_num)
{
if (locked()) {
return;
}
PropertyChange what_changed;
/* 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
* 2. we call set_position_internal; position is set and length in samples re-computed using
* length in beats from (1) but at the new position, which is wrong if the region
* straddles a tempo/meter change.
*/
if (_position != position) {
const double pos_qn = _session.tempo_map().exact_qn_at_sample (position, sub_num);
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);
samplepos_t new_start = _session.tempo_map().samples_between_quarter_notes (pos_qn - new_start_qn, pos_qn);
if (!verify_start_and_length (new_start, length)) {
return;
}
_start_beats = new_start_qn;
what_changed.add (Properties::start_beats);
set_start_internal (new_start, sub_num);
what_changed.add (Properties::start);
}
if (_length != length) {
if (!verify_start_and_length (_start, length)) {
return;
}
set_length_internal (length, sub_num);
what_changed.add (Properties::length);
what_changed.add (Properties::length_beats);
}
set_whole_file (false);
PropertyChange start_and_length;
start_and_length.add (Properties::start);
start_and_length.add (Properties::length);
if (what_changed.contains (start_and_length)) {
first_edit ();
}
if (!what_changed.empty()) {
send_change (what_changed);
}
_start = timecnt_t::zero_at (_start.val().time_domain(), nt_position());
}
bool

View File

@ -87,7 +87,7 @@ MIDISceneChanger::gather (const Locations::LocationList& locations)
have_seen_bank_changes = true;
}
scenes.insert (std::make_pair ((*l)->start(), msc));
scenes.insert (std::make_pair ((*l)->start_sample(), msc));
}
}
}
@ -314,7 +314,7 @@ MIDISceneChanger::program_change_input (MIDI::Parser& parser, MIDI::byte program
return;
}
loc = new Location (_session, time, time, new_name, Location::IsMark, 0);
loc = new Location (_session, timepos_t (time), timepos_t (time), new_name, Location::IsMark);
new_mark = true;
}
@ -356,7 +356,7 @@ MIDISceneChanger::jump_to (int bank, int program)
{
const Locations::LocationList& locations (_session.locations()->list());
boost::shared_ptr<SceneChange> sc;
samplepos_t where = max_samplepos;
timepos_t where = timepos_t::max (Temporal::AudioTime);
for (Locations::LocationList::const_iterator l = locations.begin(); l != locations.end(); ++l) {
@ -370,7 +370,7 @@ MIDISceneChanger::jump_to (int bank, int program)
}
}
if (where != max_samplepos) {
_session.request_locate (where);
if (where != timepos_t::max (Temporal::AudioTime)) {
_session.request_locate (where.samples());
}
}

View File

@ -168,65 +168,36 @@ MidiSource::set_state (const XMLNode& node, int /*version*/)
return 0;
}
bool
MidiSource::empty () const
{
return !_length_beats;
}
samplecnt_t
MidiSource::length (samplepos_t pos) const
{
if (!_length_beats) {
return 0;
}
BeatsSamplesConverter converter(_session.tempo_map(), pos);
return converter.to(_length_beats);
}
void
MidiSource::update_length (samplecnt_t)
{
// You're not the boss of me!
}
void
MidiSource::invalidate (const Lock& lock)
{
Invalidated(_session.transport_rolling());
}
samplecnt_t
timecnt_t
MidiSource::midi_read (const Lock& lm,
Evoral::EventSink<samplepos_t>& dst,
samplepos_t source_start,
samplepos_t start,
samplecnt_t cnt,
Evoral::Range<samplepos_t>* loop_range,
timepos_t const & source_start,
timecnt_t const & start,
timecnt_t const & cnt,
Temporal::Range* loop_range,
MidiCursor& cursor,
MidiStateTracker* tracker,
MidiChannelFilter* filter,
const std::set<Evoral::Parameter>& filtered,
const double pos_beats,
const double start_beats) const
const std::set<Evoral::Parameter>& filtered)
{
BeatsSamplesConverter converter(_session.tempo_map(), source_start);
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",
source_start, start, cnt, tracker, name()));
if (!_model) {
return read_unlocked (lm, dst, source_start, start, cnt, loop_range, tracker, filter);
return timecnt_t (read_unlocked (lm, dst, source_start, start, cnt, loop_range, tracker, filter), start.position());
}
// Find appropriate model iterator
Evoral::Sequence<Temporal::Beats>::const_iterator& i = cursor.iter;
const bool linear_read = cursor.last_read_end != 0 && start == cursor.last_read_end;
if (!linear_read || !i.valid()) {
if (!linear_read || !cursor.iter.valid()) {
/* Cached iterator is invalid, search for the first event past start.
Note that multiple tracks can use a MidiSource simultaneously, so
all playback state must be in parameters (the cursor) and must not
@ -234,64 +205,76 @@ MidiSource::midi_read (const Lock& lm,
See http://tracker.ardour.org/view.php?id=6541
*/
cursor.connect(Invalidated);
cursor.iter = _model->begin(converter.from(start), false, filtered, &cursor.active_notes);
cursor.iter = _model->begin (start.beats(), false, filtered, &cursor.active_notes);
cursor.active_notes.clear();
}
cursor.last_read_end = start + cnt;
// Find appropriate model iterator
Evoral::Sequence<Temporal::Beats>::const_iterator& i = cursor.iter;
// Copy events in [start, start + cnt) into dst
const Temporal::Beats source_start_beats = source_start.beats();
const Temporal::Beats region_start_beats = start.beats();
const Temporal::Beats cnt_beats = cnt.beats ();
const Temporal::Beats end = source_start_beats + region_start_beats + cnt_beats;
const Temporal::Beats session_source_start = (source_start + start).beats();
for (; i != _model->end(); ++i) {
// Offset by source start to convert event time to session time
samplepos_t time_samples = _session.tempo_map().sample_at_quarter_note (i->time().to_double() + start_qn);
const Temporal::Beats session_event_beats = source_start_beats + i->time();
if (time_samples < start + source_start) {
if (session_event_beats < session_source_start) {
/* event too early */
DEBUG_TRACE (DEBUG::MidiSourceIO, string_compose ("%1: skip event, too early @ %2 for %3\n", _name, session_event_beats, session_source_start));
continue;
} else if (time_samples >= start + cnt + source_start) {
} else if (session_event_beats >= end) {
DEBUG_TRACE (DEBUG::MidiSourceIO,
string_compose ("%1: reached end with event @ %2 vs. %3\n",
_name, time_samples, start+cnt));
DEBUG_TRACE (DEBUG::MidiSourceIO, string_compose ("%1: reached end (%2) with event @ %3\n", _name, end, session_event_beats));
break;
} else {
/* in range */
timepos_t seb = timepos_t (session_event_beats);
samplepos_t time_samples = seb.samples();
if (loop_range) {
time_samples = loop_range->squish (time_samples);
time_samples = loop_range->squish (seb).samples();
}
const uint8_t status = i->buffer()[0];
const bool is_channel_event = (0x80 <= (status & 0xF0)) && (status <= 0xE0);
if (filter && is_channel_event) {
/* Copy event so the filter can modify the channel. I'm not
sure if this is necessary here (channels are mapped later in
buffers anyway), but it preserves existing behaviour without
destroying events in the model during read. */
* sure if this is necessary here (channels are mapped later in
* buffers anyway), but it preserves existing behaviour without
* destroying events in the model during read.
*/
Evoral::Event<Temporal::Beats> ev(*i, true);
if (!filter->filter(ev.buffer(), ev.size())) {
dst.write (time_samples, ev.event_type(), ev.size(), ev.buffer());
} else {
DEBUG_TRACE (DEBUG::MidiSourceIO,
string_compose ("%1: filter event @ %2 type %3 size %4\n",
_name, time_samples, i->event_type(), i->size()));
DEBUG_TRACE (DEBUG::MidiSourceIO, string_compose ("%1: filter event @ %2 type %3 size %4\n", _name, time_samples, i->event_type(), i->size()));
}
} else {
dst.write (time_samples, i->event_type(), i->size(), i->buffer());
}
#ifndef NDEBUG
if (DEBUG_ENABLED(DEBUG::MidiSourceIO)) {
DEBUG_STR_DECL(a);
DEBUG_STR_APPEND(a, string_compose ("%1 added event @ %2 sz %3 within %4 .. %5 ",
_name, time_samples, i->size(),
start + source_start, start + cnt + source_start));
DEBUG_STR_APPEND(a, string_compose ("%1 added event @ %2 (%3) sz %4 within %5 .. %6 ", _name, time_samples, session_event_beats, i->size(), source_start + start, end));
for (size_t n=0; n < i->size(); ++n) {
DEBUG_STR_APPEND(a,hex);
DEBUG_STR_APPEND(a,"0x");
@ -312,18 +295,18 @@ MidiSource::midi_read (const Lock& lm,
return cnt;
}
samplecnt_t
timecnt_t
MidiSource::midi_write (const Lock& lm,
MidiRingBuffer<samplepos_t>& source,
samplepos_t source_start,
samplecnt_t cnt)
timepos_t const & source_start,
timecnt_t const & cnt)
{
const samplecnt_t ret = write_unlocked (lm, source, source_start, cnt);
const timecnt_t ret = write_unlocked (lm, source, source_start, cnt);
if (cnt == max_samplecnt) {
if (cnt == std::numeric_limits<timecnt_t>::max()) {
invalidate(lm);
} else {
_capture_length += cnt;
_capture_length += cnt.samples();
}
return ret;
@ -356,13 +339,15 @@ MidiSource::mark_write_starting_now (samplecnt_t position,
because it is not RT-safe.
*/
set_natural_position (position);
#warning NUTEMPO QUESTION should the time domain here reflect some setting for this source?
set_natural_position (timepos_t (position));
_capture_length = capture_length;
_capture_loop_length = loop_length;
TempoMap& map (_session.tempo_map());
BeatsSamplesConverter converter(map, position);
_length_beats = converter.from(capture_length);
#warning NUTEMPO FIXME needs session to use tempo map
//TempoMap& map (_session.tempo_map());
//BeatsSamplesConverter converter(map, position);
//_length_beats = converter.from(capture_length);
}
void

View File

@ -55,21 +55,7 @@ MidiStretch::run (boost::shared_ptr<Region> r, Progress*)
return -1;
}
const TempoMap& tmap (session.tempo_map ());
/* Fraction is based on sample-time, while MIDI source
* is always using music-time. This matters in case there is
* a tempo-ramp. So we need to scale the ratio to music-time */
const double mtfrac =
tmap.framewalk_to_qn (region->position (), region->length () * _request.time_fraction).to_double ()
/
tmap.framewalk_to_qn (region->position (), region->length ()).to_double ();
/* the name doesn't need to be super-precise, but allow for 2 fractional
* digits just to disambiguate close but not identical stretches.
*/
snprintf (suffix, sizeof (suffix), "@%d", (int) floor (mtfrac * 100.0f));
snprintf (suffix, sizeof (suffix), "@%d", (int) floor ((_request.time_fraction.numerator()/ (double) _request.time_fraction.denominator()) * 100.0f));
string new_name = region->name();
string::size_type at = new_name.find ('@');
@ -107,9 +93,6 @@ MidiStretch::run (boost::shared_ptr<Region> r, Progress*)
boost::shared_ptr<MidiModel> new_model = new_src->model();
new_model->start_write();
const double r_start = tmap.quarter_notes_between_samples (region->position () - region->start (), region->position ());
const double r_end = r_start + tmap.quarter_notes_between_samples (region->position (), region->position () + region->length ());
#ifdef DEBUG_MIDI_STRETCH
printf ("stretch start: %f end: %f [* %f] * %f\n", r_start, r_end, _request.time_fraction, mtfrac);
#endif
@ -119,26 +102,7 @@ MidiStretch::run (boost::shared_ptr<Region> r, Progress*)
*/
for (Evoral::Sequence<MidiModel::TimeType>::const_iterator i = old_model->begin (MidiModel::TimeType(), true); i != old_model->end(); ++i) {
if (i->time() < r_start) {
#ifdef DEBUG_MIDI_STRETCH
cout << "SKIP EARLY EVENT " << i->time() << "\n";
#endif
continue;
}
if (i->time() > r_end) {
#ifdef DEBUG_MIDI_STRETCH
cout << "SKIP LATE EVENT " << i->time() << "\n";
continue;
#else
break;
#endif
}
#ifdef DEBUG_MIDI_STRETCH
cout << "STRETCH " << i->time() << " OFFSET FROM START @ " << r_start << " = " << (i->time() - r_start) << " TO " << (i->time() - r_start) * mtfrac << "\n";
#endif
const MidiModel::TimeType new_time = (i->time() - r_start) * mtfrac;
const MidiModel::TimeType new_time = i->time().operator* (_request.time_fraction);
// FIXME: double copy
Evoral::Event<MidiModel::TimeType> ev(*i, true);
@ -154,9 +118,8 @@ MidiStretch::run (boost::shared_ptr<Region> r, Progress*)
const int ret = finish (region, nsrcs, new_name);
/* non-musical */
results[0]->set_start(0);
results[0]->set_position (r->position ()); // force updates the region's quarter-note position
results[0]->set_length((samplecnt_t) floor (r->length() * _request.time_fraction), 0);
#warning NUTEMPO FIXME do we still need this?
results[0]->set_length (r->nt_length().operator* ( _request.time_fraction));
return ret;
}

View File

@ -370,8 +370,8 @@ MidiTrack::update_controls (BufferSet const& bufs)
const Evoral::Parameter param = midi_parameter(ev.buffer(), ev.size());
const boost::shared_ptr<AutomationControl> control = automation_control (param);
if (control) {
double old = control->get_double (false, 0);
control->set_double (ev.value(), 0, false);
double old = control->get_double (false, timepos_t::zero (true));
control->set_double (ev.value(), timepos_t::zero (false), false);
if (old != ev.value()) {
control->Changed (false, Controllable::NoGroup);
}
@ -406,9 +406,11 @@ MidiTrack::realtime_locate (bool for_loop_end)
}
void
MidiTrack::non_realtime_locate (samplepos_t pos)
MidiTrack::non_realtime_locate (samplepos_t spos)
{
Track::non_realtime_locate(pos);
timepos_t pos (spos);
Track::non_realtime_locate (spos);
boost::shared_ptr<MidiPlaylist> playlist = _disk_writer->midi_playlist();
if (!playlist) {
@ -416,7 +418,7 @@ MidiTrack::non_realtime_locate (samplepos_t pos)
}
/* Get the top unmuted region at this position. */
boost::shared_ptr<MidiRegion> region = boost::dynamic_pointer_cast<MidiRegion>(playlist->top_unmuted_region_at(pos));
boost::shared_ptr<MidiRegion> region = boost::dynamic_pointer_cast<MidiRegion> (playlist->top_unmuted_region_at (pos));
if (!region) {
return;
@ -433,8 +435,7 @@ MidiTrack::non_realtime_locate (samplepos_t pos)
}
/* Update track controllers based on its "automation". */
const samplepos_t origin = region->position() - region->start();
BeatsSamplesConverter bfc(_session.tempo_map(), origin);
const timepos_t pos_beats = timepos_t (region->source_position().distance (pos).beats ()); /* relative to source start */
for (Controls::const_iterator c = _controls.begin(); c != _controls.end(); ++c) {
@ -450,7 +451,7 @@ MidiTrack::non_realtime_locate (samplepos_t pos)
if ((tcontrol = boost::dynamic_pointer_cast<MidiTrack::MidiControl>(c->second)) &&
(rcontrol = region->control(tcontrol->parameter()))) {
const Temporal::Beats pos_beats = bfc.from(pos - origin);
if (rcontrol->list()->size() > 0) {
tcontrol->set_value(rcontrol->list()->eval(pos_beats), Controllable::NoGroup);
}

View File

@ -26,7 +26,7 @@ using namespace PBD;
MonitorControl::MonitorControl (Session& session, std::string const & name, Monitorable& m)
: SlavableAutomationControl (session, MonitoringAutomation, ParameterDescriptor (MonitoringAutomation),
boost::shared_ptr<AutomationList>(new AutomationList(Evoral::Parameter(MonitoringAutomation))),
boost::shared_ptr<AutomationList>(new AutomationList(Evoral::Parameter(MonitoringAutomation), Temporal::AudioTime)),
name)
, _monitorable (m)

View File

@ -29,9 +29,10 @@ using namespace ARDOUR;
using namespace std;
#warning NUTEMPO QUESTION what time domain shoudl this really use?
MuteControl::MuteControl (Session& session, std::string const & name, Muteable& m)
: SlavableAutomationControl (session, MuteAutomation, ParameterDescriptor (MuteAutomation),
boost::shared_ptr<AutomationList> (new AutomationList (Evoral::Parameter (MuteAutomation))),
boost::shared_ptr<AutomationList> (new AutomationList (Evoral::Parameter (MuteAutomation), Temporal::AudioTime)),
name)
, _muteable (m)
{
@ -189,7 +190,7 @@ MuteControl::automation_run (samplepos_t start, pframes_t len)
bool mute = false;
if (list() && automation_playback()) {
mute = list()->rt_safe_eval (start, valid) >= 0.5;
mute = list()->rt_safe_eval (timepos_t (start), valid) >= 0.5;
}
if (!valid) {

View File

@ -48,7 +48,7 @@ OnsetDetector::operational_identifier()
}
int
OnsetDetector::run (const std::string& path, Readable* src, uint32_t channel, AnalysisFeatureList& results)
OnsetDetector::run (const std::string& path, AudioReadable* src, uint32_t channel, AnalysisFeatureList& results)
{
current_results = &results;
int ret = analyse (path, src, channel);

View File

@ -151,7 +151,7 @@ Pannable::set_automation_state (AutoState state)
}
void
Pannable::start_touch (double when)
Pannable::start_touch (timepos_t const & when)
{
const Controls& c (controls());
@ -165,7 +165,7 @@ Pannable::start_touch (double when)
}
void
Pannable::stop_touch (double when)
Pannable::stop_touch (timepos_t const & when)
{
const Controls& c (controls());

View File

@ -27,7 +27,7 @@ using namespace ARDOUR;
PhaseControl::PhaseControl (Session& session, std::string const & name)
: AutomationControl (session, PhaseAutomation, ParameterDescriptor (PhaseAutomation),
boost::shared_ptr<AutomationList>(new AutomationList(Evoral::Parameter(PhaseAutomation))),
boost::shared_ptr<AutomationList>(new AutomationList(Evoral::Parameter(PhaseAutomation), Temporal::AudioTime)),
name)
{
}

File diff suppressed because it is too large Load Diff

View File

@ -110,7 +110,7 @@ PlaylistFactory::create (boost::shared_ptr<const Playlist> old, string name, boo
}
boost::shared_ptr<Playlist>
PlaylistFactory::create (boost::shared_ptr<const Playlist> old, samplepos_t start, samplecnt_t cnt, string name, bool hidden)
PlaylistFactory::create (boost::shared_ptr<const Playlist> old, timepos_t const & start, timepos_t const & cnt, string name, bool hidden)
{
boost::shared_ptr<Playlist> pl;
boost::shared_ptr<const AudioPlaylist> apl;

Some files were not shown because too many files have changed in this diff Show More