summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2008-11-11 14:12:08 +0000
committerPaul Davis <paul@linuxaudiosystems.com>2008-11-11 14:12:08 +0000
commita4d46fb4ef88a548a6470417c7dfd88db2cab119 (patch)
tree335fd6a391691f4bbc3ec1dea28ce0785669816e
parent7324e4cbe781a63fd886bf32e50db60c9546b4b9 (diff)
new region constructor for use by audiofilters (almost does a pure copy of the region, but sets start & sync_position appropriately, and uses new sources); fix up reverse bugs introduced in the last 36hrs; fix up setting of sync_position after split and so forth
git-svn-id: svn://localhost/ardour2/branches/2.0-ongoing@4140 d708f5d6-7413-0410-9779-e7cbd77b26cf
-rw-r--r--libs/ardour/ardour/audioregion.h1
-rw-r--r--libs/ardour/ardour/region.h6
-rw-r--r--libs/ardour/ardour/region_factory.h5
-rw-r--r--libs/ardour/audiofilter.cc29
-rw-r--r--libs/ardour/audioregion.cc60
-rw-r--r--libs/ardour/region.cc96
-rw-r--r--libs/ardour/region_factory.cc31
-rw-r--r--libs/ardour/reverse.cc7
-rw-r--r--libs/ardour/sndfilesource.cc9
9 files changed, 200 insertions, 44 deletions
diff --git a/libs/ardour/ardour/audioregion.h b/libs/ardour/ardour/audioregion.h
index 4d4d8eecd8..2174fb9228 100644
--- a/libs/ardour/ardour/audioregion.h
+++ b/libs/ardour/ardour/audioregion.h
@@ -169,6 +169,7 @@ class AudioRegion : public Region
AudioRegion (boost::shared_ptr<AudioSource>, nframes_t start, nframes_t length, const string& name, layer_t = 0, Region::Flag flags = Region::DefaultFlags);
AudioRegion (const SourceList &, nframes_t start, nframes_t length, const string& name, layer_t = 0, Region::Flag flags = Region::DefaultFlags);
AudioRegion (boost::shared_ptr<const AudioRegion>, nframes_t start, nframes_t length, const string& name, layer_t = 0, Region::Flag flags = Region::DefaultFlags);
+ AudioRegion (boost::shared_ptr<const AudioRegion>, const SourceList&, nframes_t length, const string& name, layer_t = 0, Region::Flag flags = Region::DefaultFlags);
AudioRegion (boost::shared_ptr<const AudioRegion>);
AudioRegion (boost::shared_ptr<AudioSource>, const XMLNode&);
AudioRegion (SourceList &, const XMLNode&);
diff --git a/libs/ardour/ardour/region.h b/libs/ardour/ardour/region.h
index e4d913082e..bffd13ae1d 100644
--- a/libs/ardour/ardour/region.h
+++ b/libs/ardour/ardour/region.h
@@ -110,8 +110,9 @@ class Region : public PBD::StatefulDestructible, public Readable, public boost::
nframes_t sync_offset(int& dir) const;
nframes_t sync_position() const;
+ nframes_t sync_point () const;
- nframes_t adjust_to_sync (nframes_t);
+ nframes_t adjust_to_sync (nframes_t) const;
/* first_frame() is an alias; last_frame() just hides some math */
@@ -212,10 +213,13 @@ class Region : public PBD::StatefulDestructible, public Readable, public boost::
Region (nframes_t start, nframes_t length,
const string& name, layer_t = 0, Flag flags = DefaultFlags);
Region (boost::shared_ptr<const Region>, nframes_t start, nframes_t length, const string& name, layer_t = 0, Flag flags = DefaultFlags);
+ Region (boost::shared_ptr<const Region>, nframes_t length, const string& name, layer_t = 0, Flag flags = DefaultFlags);
Region (boost::shared_ptr<const Region>);
Region (const XMLNode&);
protected:
+ void copy_stuff (boost::shared_ptr<const Region>, nframes_t start, nframes_t length, const string& name, layer_t, Flag flags);
+
XMLNode& get_short_state (); /* used only by Session */
void send_change (Change);
diff --git a/libs/ardour/ardour/region_factory.h b/libs/ardour/ardour/region_factory.h
index ada5afcd9c..640be4bdf4 100644
--- a/libs/ardour/ardour/region_factory.h
+++ b/libs/ardour/ardour/region_factory.h
@@ -49,11 +49,12 @@ class RegionFactory {
*/
static boost::shared_ptr<Region> create (boost::shared_ptr<Region>, nframes_t start,
- nframes_t length, std::string name,
+ nframes_t length, const std::string& name,
layer_t = 0, Region::Flag flags = Region::DefaultFlags, bool announce = true);
static boost::shared_ptr<Region> create (boost::shared_ptr<AudioRegion>, nframes_t start,
- nframes_t length, std::string name,
+ nframes_t length, const std::string& name,
layer_t = 0, Region::Flag flags = Region::DefaultFlags, bool announce = true);
+ static boost::shared_ptr<Region> create (boost::shared_ptr<Region>, const SourceList&, const string& name, layer_t = 0, Region::Flag flags = Region::DefaultFlags, bool announce = true);
static boost::shared_ptr<Region> create (boost::shared_ptr<Source>, nframes_t start, nframes_t length, const string& name, layer_t = 0, Region::Flag flags = Region::DefaultFlags, bool announce = true);
static boost::shared_ptr<Region> create (const SourceList &, nframes_t start, nframes_t length, const string& name, layer_t = 0, Region::Flag flags = Region::DefaultFlags, bool announce = true);
static boost::shared_ptr<Region> create (Session&, XMLNode&, bool);
diff --git a/libs/ardour/audiofilter.cc b/libs/ardour/audiofilter.cc
index 04eea471ec..a85ce16821 100644
--- a/libs/ardour/audiofilter.cc
+++ b/libs/ardour/audiofilter.cc
@@ -113,6 +113,24 @@ AudioFilter::finish (boost::shared_ptr<AudioRegion> region, SourceList& nsrcs, s
}
}
+
+ /* make a new whole-file region that copies almost everything from the old one, but
+ uses the new sources (and new length and name)
+ */
+
+ boost::shared_ptr<AudioRegion> ar;
+ boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(nsrcs.front());
+
+ string whole_file_region_name = region_name_from_path (afs->path(), true);
+
+ ar = boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create
+ (nsrcs, 0, nsrcs.front()->length(), whole_file_region_name, 0,
+ Region::Flag (Region::WholeFile|Region::DefaultFlags)));
+
+ /* now make a copy of the region that copies almost everything from the old one, but
+ uses the new sources (and new length and name)
+ */
+
/* create a new region */
if (region_name.empty()) {
@@ -121,13 +139,14 @@ AudioFilter::finish (boost::shared_ptr<AudioRegion> region, SourceList& nsrcs, s
results.clear ();
- boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion> (
- RegionFactory::create (nsrcs, 0, nsrcs.front()->length(), region_name, 0,
- Region::Flag (Region::WholeFile|Region::DefaultFlags)));
+ ar = boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create
+ (region, nsrcs, region_name, 0, region->flags()));
- /* reset relevant stuff */
+ /* if we changed the length, fix up the envelope */
- ar->copy_settings (region);
+ if (region->length() != ar->length()) {
+ ar->envelope().extend_to (ar->length());
+ }
results.push_back (ar);
diff --git a/libs/ardour/audioregion.cc b/libs/ardour/audioregion.cc
index e5b22a7cde..287d9dbe46 100644
--- a/libs/ardour/audioregion.cc
+++ b/libs/ardour/audioregion.cc
@@ -250,6 +250,38 @@ AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other)
listen_to_my_sources ();
}
+AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other, const SourceList& srcs,
+ nframes_t length, const string& name, layer_t layer, Flag flags)
+ : Region (other, length, name, layer, flags),
+ _fade_in (other->_fade_in),
+ _fade_out (other->_fade_out),
+ _envelope (other->_envelope)
+
+{
+ /* make-a-sort-of-copy-with-different-sources constructor (used by audio filter) */
+
+ set<boost::shared_ptr<AudioSource> > unique_srcs;
+
+ for (SourceList::const_iterator i=srcs.begin(); i != srcs.end(); ++i) {
+ sources.push_back (*i);
+ master_sources.push_back (*i);
+ (*i)->GoingAway.connect (mem_fun (*this, &AudioRegion::source_deleted));
+
+ boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> ((*i));
+ if (afs) {
+ afs->HeaderPositionOffsetChanged.connect (mem_fun (*this, &AudioRegion::source_offset_changed));
+ }
+ }
+
+ _scale_amplitude = other->_scale_amplitude;
+
+ _fade_in_disabled = 0;
+ _fade_out_disabled = 0;
+
+ listen_to_my_curves ();
+ listen_to_my_sources ();
+}
+
AudioRegion::AudioRegion (boost::shared_ptr<AudioSource> src, const XMLNode& node)
: Region (node),
_fade_in (0.0, 2.0, 1.0, false),
@@ -349,22 +381,6 @@ AudioRegion::listen_to_my_curves ()
_fade_out.StateChanged.connect (mem_fun (*this, &AudioRegion::fade_out_changed));
}
-void
-AudioRegion::copy_settings (boost::shared_ptr<const AudioRegion> other)
-{
- _fade_in = other->_fade_in;
- _fade_out = other->_fade_out;
- _envelope = other->_envelope;
- _flags = other->_flags;
- _scale_amplitude = other->_scale_amplitude;
- _fade_in_disabled = other->_fade_in_disabled;
- _fade_out_disabled = other->_fade_out_disabled;
-
- if (_length != other->length()) {
- _envelope.extend_to (_length);
- }
-}
-
bool
AudioRegion::verify_length (nframes_t& len)
{
@@ -475,25 +491,25 @@ AudioRegion::read_peaks (PeakData *buf, nframes_t npeaks, nframes_t offset, nfra
}
nframes64_t
-AudioRegion::read (Sample* buf, nframes64_t position, nframes64_t cnt, int channel) const
+AudioRegion::read (Sample* buf, nframes64_t timeline_position, nframes64_t cnt, int channel) const
{
/* raw read, no fades, no gain, nada */
- return _read_at (sources, _length, buf, 0, 0, _position + position, cnt, channel, 0, 0, ReadOps (0));
+ return _read_at (sources, _length, buf, 0, 0, _position + timeline_position, cnt, channel, 0, 0, ReadOps (0));
}
nframes64_t
-AudioRegion::read_with_ops (Sample* buf, nframes64_t position, nframes64_t cnt, int channel, ReadOps rops) const
+AudioRegion::read_with_ops (Sample* buf, nframes64_t file_position, nframes64_t cnt, int channel, ReadOps rops) const
{
- return _read_at (sources, _length, buf, 0, 0, _position + position, cnt, channel, 0, 0, rops);
+ return _read_at (sources, _length, buf, 0, 0, file_position, cnt, channel, 0, 0, rops);
}
nframes_t
-AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, nframes_t position,
+AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, nframes_t file_position,
nframes_t cnt,
uint32_t chan_n, nframes_t read_frames, nframes_t skip_frames) const
{
/* regular diskstream/butler read complete with fades etc */
- return _read_at (sources, _length, buf, mixdown_buffer, gain_buffer, position, cnt, chan_n, read_frames, skip_frames, ReadOps (~0));
+ return _read_at (sources, _length, buf, mixdown_buffer, gain_buffer, file_position, cnt, chan_n, read_frames, skip_frames, ReadOps (~0));
}
nframes_t
diff --git a/libs/ardour/region.cc b/libs/ardour/region.cc
index 1e6fd5daa7..37b10d6752 100644
--- a/libs/ardour/region.cc
+++ b/libs/ardour/region.cc
@@ -36,6 +36,7 @@
#include <ardour/session.h>
#include <ardour/tempo.h>
#include <ardour/region_factory.h>
+#include <ardour/profile.h>
#include "i18n.h"
@@ -82,19 +83,100 @@ Region::Region (boost::shared_ptr<const Region> other, nframes_t offset, nframes
{
/* create a new Region from part of an existing one */
+ _start = other->_start + offset;
+
+ copy_stuff (other, offset, length, name, layer, flags);
+
+ /* if the other region had a distinct sync point
+ set, then continue to use it as best we can.
+ otherwise, reset sync point back to start.
+ */
+
+ if (other->flags() & SyncMarked) {
+ if (other->_sync_position < _start) {
+ _flags = Flag (_flags & ~SyncMarked);
+ _sync_position = _start;
+ } else {
+ _sync_position = other->_sync_position;
+ }
+ } else {
+ _flags = Flag (_flags & ~SyncMarked);
+ _sync_position = _start;
+ }
+
+ if (Profile->get_sae()) {
+ /* reset sync point to start if its ended up
+ outside region bounds.
+ */
+
+ if (_sync_position < _start || _sync_position >= _start + _length) {
+ _flags = Flag (_flags & ~SyncMarked);
+ _sync_position = _start;
+ }
+ }
+
+}
+
+Region::Region (boost::shared_ptr<const Region> other, nframes_t length, const string& name, layer_t layer, Flag flags)
+{
+ /* create a new Region exactly like another but starting at 0 in its sources */
+
+ _start = 0;
+ copy_stuff (other, 0, length, name, layer, flags);
+
+ /* sync pos is relative to start of file. our start-in-file is now zero,
+ so set our sync position to whatever the the difference between
+ _start and _sync_pos was in the other region.
+
+ result is that our new sync pos points to the same point in our source(s)
+ as the sync in the other region did in its source(s).
+
+ since we start at zero in our source(s), it is not possible to use a sync point that
+ is before the start. reset it to _start if that was true in the other region.
+ */
+
+ if (other->flags() & SyncMarked) {
+ if (other->_start < other->_sync_position) {
+ /* sync pos was after the start point of the other region */
+ _sync_position = other->_sync_position - other->_start;
+ } else {
+ /* sync pos was before the start point of the other region. not possible here. */
+ _flags = Flag (_flags & ~SyncMarked);
+ _sync_position = _start;
+ }
+ } else {
+ _flags = Flag (_flags & ~SyncMarked);
+ _sync_position = _start;
+ }
+
+ if (Profile->get_sae()) {
+ /* reset sync point to start if its ended up
+ outside region bounds.
+ */
+
+ if (_sync_position < _start || _sync_position >= _start + _length) {
+ _flags = Flag (_flags & ~SyncMarked);
+ _sync_position = _start;
+ }
+ }
+
+ /* reset a couple of things that copy_stuff() gets wrong in this particular case */
+
+ _positional_lock_style = other->_positional_lock_style;
+ _first_edit = other->_first_edit;
+}
+
+void
+Region::copy_stuff (boost::shared_ptr<const Region> other, nframes_t offset, nframes_t length, const string& name, layer_t layer, Flag flags)
+{
_frozen = 0;
pending_changed = Change (0);
_read_data_count = 0;
valid_transients = false;
- _start = other->_start + offset;
- if (other->_sync_position < offset) {
- _sync_position = other->_sync_position;
- } else {
- _sync_position = _start;
- }
_length = length;
_last_length = length;
+ _sync_position = other->_sync_position;
_ancestral_start = other->_ancestral_start;
_ancestral_length = other->_ancestral_length;
_stretch = other->_stretch;
@@ -765,7 +847,7 @@ Region::sync_offset (int& dir) const
}
nframes_t
-Region::adjust_to_sync (nframes_t pos)
+Region::adjust_to_sync (nframes_t pos) const
{
int sync_dir;
nframes_t offset = sync_offset (sync_dir);
diff --git a/libs/ardour/region_factory.cc b/libs/ardour/region_factory.cc
index 79192f05c5..2f3d694287 100644
--- a/libs/ardour/region_factory.cc
+++ b/libs/ardour/region_factory.cc
@@ -35,7 +35,7 @@ sigc::signal<void,boost::shared_ptr<Region> > RegionFactory::CheckNewRegion;
boost::shared_ptr<Region>
RegionFactory::create (boost::shared_ptr<Region> region, nframes_t start,
- nframes_t length, std::string name,
+ nframes_t length, const std::string& name,
layer_t layer, Region::Flag flags, bool announce)
{
boost::shared_ptr<const AudioRegion> other;
@@ -75,13 +75,40 @@ RegionFactory::create (boost::shared_ptr<const Region> region)
boost::shared_ptr<Region>
RegionFactory::create (boost::shared_ptr<AudioRegion> region, nframes_t start,
- nframes_t length, std::string name,
+ nframes_t length, const std::string& name,
layer_t layer, Region::Flag flags, bool announce)
{
return create (boost::static_pointer_cast<Region> (region), start, length, name, layer, flags, announce);
}
boost::shared_ptr<Region>
+RegionFactory::create (boost::shared_ptr<Region> region, const SourceList& srcs,
+ const std::string& name, layer_t layer, Region::Flag flags, bool announce)
+
+{
+ boost::shared_ptr<const AudioRegion> other;
+
+ /* used by AudioFilter when constructing a new region that is intended to have nearly
+ identical settings to an original, but using different sources.
+ */
+
+ if ((other = boost::dynamic_pointer_cast<AudioRegion>(region)) != 0) {
+ AudioRegion* ar = new AudioRegion (other, srcs, srcs.front()->length(), name, layer, flags);
+ boost::shared_ptr<AudioRegion> arp (ar);
+ boost::shared_ptr<Region> ret (boost::static_pointer_cast<Region> (arp));
+ if (announce) {
+ CheckNewRegion (ret);
+ }
+ return ret;
+ } else {
+ fatal << _("programming error: RegionFactory::create() called with unknown Region type")
+ << endmsg;
+ /*NOTREACHED*/
+ return boost::shared_ptr<Region>();
+ }
+}
+
+boost::shared_ptr<Region>
RegionFactory::create (Session& session, XMLNode& node, bool yn)
{
boost::shared_ptr<Region> r = session.XMLRegionFactory (node, yn);
diff --git a/libs/ardour/reverse.cc b/libs/ardour/reverse.cc
index 2e78f25c22..a6ea7c4b10 100644
--- a/libs/ardour/reverse.cc
+++ b/libs/ardour/reverse.cc
@@ -66,6 +66,7 @@ Reverse::run (boost::shared_ptr<AudioRegion> region)
}
fpos = max (fstart, (fstart + region->length() - blocksize));
+
buf = new Sample[blocksize];
to_read = blocksize;
@@ -77,9 +78,9 @@ Reverse::run (boost::shared_ptr<AudioRegion> region)
for (n = 0, si = nsrcs.begin(); n < region->n_channels(); ++n, ++si) {
- /* read it in, with any amplitude scaling */
+ /* read it in directly from the source */
- if (region->read (buf, fpos, to_read, n) != to_read) {
+ if (region->source (n)->read (buf, fpos, to_read, n) != to_read) {
goto out;
}
@@ -88,7 +89,7 @@ Reverse::run (boost::shared_ptr<AudioRegion> region)
for (nframes_t i = 0; i < to_read/2; ++i) {
swap (buf[i],buf[to_read-1-i]);
}
-
+
/* write it out */
if ((*si)->write (buf, to_read) != to_read) {
diff --git a/libs/ardour/sndfilesource.cc b/libs/ardour/sndfilesource.cc
index d2b4704daf..0217c01d4f 100644
--- a/libs/ardour/sndfilesource.cc
+++ b/libs/ardour/sndfilesource.cc
@@ -349,7 +349,12 @@ SndFileSource::read_unlocked (Sample *dst, nframes_t start, nframes_t cnt) const
if (_info.channels == 1) {
nframes_t ret = sf_read_float (sf, dst, file_cnt);
- _read_data_count = cnt * sizeof(float);
+ _read_data_count = ret * sizeof(float);
+ if (ret != file_cnt) {
+ char errbuf[256];
+ sf_error_str (0, errbuf, sizeof (errbuf) - 1);
+ cerr << string_compose(_("SndFileSource: @ %1 could not read %2 within %3 (%4) (len = %5)"), start, file_cnt, _name.substr (1), errbuf, _length) << endl;
+ }
return ret;
}
}
@@ -413,7 +418,7 @@ SndFileSource::nondestructive_write_unlocked (Sample *data, nframes_t cnt)
}
_write_data_count = cnt;
-
+
return cnt;
}