libardour: conversion to use timeline types (mega-commit)
This commit is contained in:
parent
bca8e2e8cc
commit
eae9d276fe
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
);
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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&);
|
||||
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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>);
|
||||
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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>);
|
||||
|
|
|
@ -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; }
|
||||
|
||||
|
|
|
@ -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__ */
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)
|
||||
{}
|
||||
|
|
|
@ -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); }
|
||||
|
||||
|
|
|
@ -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__ */
|
||||
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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&);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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 ();
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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__ */
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -50,6 +50,11 @@ class XMLNode;
|
|||
|
||||
namespace ARDOUR {
|
||||
|
||||
enum PositionLockStyle {
|
||||
AudioTime,
|
||||
MusicTime
|
||||
};
|
||||
|
||||
class Meter;
|
||||
class TempoMap;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 };
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -42,7 +42,7 @@ EBUr128Analysis::~EBUr128Analysis()
|
|||
}
|
||||
|
||||
int
|
||||
EBUr128Analysis::run (Readable* src)
|
||||
EBUr128Analysis::run (AudioReadable* src)
|
||||
{
|
||||
int ret = -1;
|
||||
bool done = false;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 ()
|
||||
|
|
|
@ -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)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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());
|
||||
|
||||
|
|
|
@ -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
|
@ -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
Loading…
Reference in New Issue
Block a user