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
This commit is contained in:
Paul Davis 2008-11-11 14:12:08 +00:00
parent 7324e4cbe7
commit a4d46fb4ef
9 changed files with 200 additions and 44 deletions

View file

@ -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&);

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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

View file

@ -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);

View file

@ -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,12 +75,39 @@ 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)
{

View file

@ -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) {

View file

@ -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;
}