: Region (other),
_fade_in (other->_fade_in),
_fade_out (other->_fade_out),
- _envelope (other->_envelope)
+ _envelope (other->_envelope)
+
{
/* Pure copy constructor */
}
_scale_amplitude = other->_scale_amplitude;
- _envelope = other->_envelope;
_fade_in_disabled = 0;
_fade_out_disabled = 0;
-
+
+ listen_to_my_curves ();
+ 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 ();
}
return true;
}
+
bool
AudioRegion::verify_start (nframes_t pos)
{
}
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, true);
+ 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 file_position, nframes64_t cnt, int channel, ReadOps rops) const
+{
+ 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, false);
+ return _read_at (sources, _length, buf, mixdown_buffer, gain_buffer, file_position, cnt,
+ chan_n, read_frames, skip_frames, ReadOps (~0));
}
nframes_t
AudioRegion::master_read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, nframes_t position,
nframes_t cnt, uint32_t chan_n) const
{
- return _read_at (master_sources, master_sources.front()->length(), buf, mixdown_buffer, gain_buffer, position, cnt, chan_n, 0, 0);
+ /* do not read gain/scaling/fades and do not count this disk i/o in statistics */
+
+ return _read_at (master_sources, master_sources.front()->length(), buf, mixdown_buffer,
+ gain_buffer, position, cnt, chan_n, 0, 0, ReadOps (0));
}
nframes_t
uint32_t chan_n,
nframes_t read_frames,
nframes_t skip_frames,
- bool raw) const
+ ReadOps rops) const
{
nframes_t internal_offset;
nframes_t buf_offset;
nframes_t to_read;
+ bool raw = (rops == ReadOpsNone);
if (muted() && !raw) {
return 0; /* read nothing */
mixdown_buffer += buf_offset;
}
- if (!raw) {
+ if (rops & ReadOpsCount) {
_read_data_count = 0;
}
return 0; /* "read nothing" */
}
- if (!raw) {
+ if (rops & ReadOpsCount) {
_read_data_count += srcs[chan_n]->read_data_count();
}
*/
memset (mixdown_buffer, 0, sizeof (Sample) * cnt);
-
- /* no fades required */
-
- if (!raw) {
- goto merge;
- }
}
- /* fade in */
-
- if (!raw) {
+ if (rops & ReadOpsFades) {
+ /* fade in */
+
if ((_flags & FadeIn) && Config->get_use_region_fades()) {
nframes_t fade_in_length = (nframes_t) _fade_in.back()->when;
if (internal_offset < fade_in_length) {
- nframes_t limit;
+ nframes_t fi_limit;
- limit = min (to_read, fade_in_length - internal_offset);
+ fi_limit = min (to_read, fade_in_length - internal_offset);
- _fade_in.get_vector (internal_offset, internal_offset+limit, gain_buffer, limit);
+ _fade_in.get_vector (internal_offset, internal_offset+fi_limit, gain_buffer, fi_limit);
- for (nframes_t n = 0; n < limit; ++n) {
+ for (nframes_t n = 0; n < fi_limit; ++n) {
mixdown_buffer[n] *= gain_buffer[n];
}
}
/* see if some part of this read is within the fade out */
/* ................. >| REGION
- limit
+ limit
{ } FADE
fade_out_length
^
- limit - fade_out_length
+ limit - fade_out_length
|--------------|
^internal_offset
^internal_offset + to_read
}
}
+ }
- /* Regular gain curves */
+ /* Regular gain curves and scaling */
+
+ if ((rops & ReadOpsOwnAutomation) && envelope_active()) {
+ _envelope.get_vector (internal_offset, internal_offset + to_read, gain_buffer, to_read);
- if (envelope_active()) {
- _envelope.get_vector (internal_offset, internal_offset + to_read, gain_buffer, to_read);
-
- if (_scale_amplitude != 1.0f) {
- for (nframes_t n = 0; n < to_read; ++n) {
- mixdown_buffer[n] *= gain_buffer[n] * _scale_amplitude;
- }
- } else {
- for (nframes_t n = 0; n < to_read; ++n) {
- mixdown_buffer[n] *= gain_buffer[n];
- }
+ if ((rops & ReadOpsOwnScaling) && _scale_amplitude != 1.0f) {
+ for (nframes_t n = 0; n < to_read; ++n) {
+ mixdown_buffer[n] *= gain_buffer[n] * _scale_amplitude;
+ }
+ } else {
+ for (nframes_t n = 0; n < to_read; ++n) {
+ mixdown_buffer[n] *= gain_buffer[n];
}
- } else if (_scale_amplitude != 1.0f) {
- Session::apply_gain_to_buffer (mixdown_buffer, to_read, _scale_amplitude);
}
+ } else if ((rops & ReadOpsOwnScaling) && _scale_amplitude != 1.0f) {
+ Session::apply_gain_to_buffer (mixdown_buffer, to_read, _scale_amplitude);
+ }
- merge:
+ if (!opaque()) {
- if (!opaque()) {
-
- /* gack. the things we do for users.
- */
-
- buf += buf_offset;
+ /* gack. the things we do for users.
+ */
+
+ buf += buf_offset;
- for (nframes_t n = 0; n < to_read; ++n) {
- buf[n] += mixdown_buffer[n];
- }
- }
- }
+ for (nframes_t n = 0; n < to_read; ++n) {
+ buf[n] += mixdown_buffer[n];
+ }
+ }
return to_read;
}
}
if ((prop = child->property ("active")) != 0) {
- if (prop->value() == "yes") {
+ if (string_is_affirmative (prop->value())) {
set_fade_in_active (true);
} else {
set_fade_in_active (true);
}
if ((prop = child->property ("active")) != 0) {
- if (prop->value() == "yes") {
+ if (string_is_affirmative (prop->value())) {
set_fade_out_active (true);
} else {
set_fade_out_active (false);
/* no existing/complete transient info */
+ static bool analyse_dialog_shown = false;
if (!Config->get_auto_analyse_audio()) {
- pl->session().Dialog (_("\
+ if ( !analyse_dialog_shown ) {
+ pl->session().Dialog (_("\
You have requested an operation that requires audio analysis.\n\n\
You currently have \"auto-analyse-audio\" disabled, which means\n\
that transient data must be generated every time it is required.\n\n\
If you are doing work that will require transient data on a\n\
regular basis, you should probably enable \"auto-analyse-audio\"\n\
-then quit ardour and restart."));
+then quit ardour and restart.\n\n\
+This dialog will not display again. But you may notice a slight delay\n\
+in this and future transient-detection operations.\n\
+"));
+ analyse_dialog_shown = true; //only show this dialog once
+ }
}
TransientDetector t (pl->session().frame_rate());