diff options
author | Paul Davis <paul@linuxaudiosystems.com> | 2008-11-11 14:12:08 +0000 |
---|---|---|
committer | Paul Davis <paul@linuxaudiosystems.com> | 2008-11-11 14:12:08 +0000 |
commit | a4d46fb4ef88a548a6470417c7dfd88db2cab119 (patch) | |
tree | 335fd6a391691f4bbc3ec1dea28ce0785669816e | |
parent | 7324e4cbe781a63fd886bf32e50db60c9546b4b9 (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.h | 1 | ||||
-rw-r--r-- | libs/ardour/ardour/region.h | 6 | ||||
-rw-r--r-- | libs/ardour/ardour/region_factory.h | 5 | ||||
-rw-r--r-- | libs/ardour/audiofilter.cc | 29 | ||||
-rw-r--r-- | libs/ardour/audioregion.cc | 60 | ||||
-rw-r--r-- | libs/ardour/region.cc | 96 | ||||
-rw-r--r-- | libs/ardour/region_factory.cc | 31 | ||||
-rw-r--r-- | libs/ardour/reverse.cc | 7 | ||||
-rw-r--r-- | libs/ardour/sndfilesource.cc | 9 |
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; } |