#include "ardour/region_factory.h"
#include "ardour/runtime_functions.h"
#include "ardour/transient_detector.h"
+#include "ardour/progress.h"
#include "i18n.h"
#include <locale.h>
void
AudioRegion::make_property_quarks ()
{
- Properties::envelope_active.id = g_quark_from_static_string (X_("envelope-active"));
- Properties::default_fade_in.id = g_quark_from_static_string (X_("default-fade-in"));
- Properties::default_fade_out.id = g_quark_from_static_string (X_("default-fade-out"));
- Properties::fade_in_active.id = g_quark_from_static_string (X_("fade-in-active"));
- Properties::fade_out_active.id = g_quark_from_static_string (X_("fade-out-active"));
- Properties::scale_amplitude.id = g_quark_from_static_string (X_("scale-amplitude"));
+ Properties::envelope_active.property_id = g_quark_from_static_string (X_("envelope-active"));
+ DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for envelope-active = %1\n", Properties::envelope_active.property_id));
+ Properties::default_fade_in.property_id = g_quark_from_static_string (X_("default-fade-in"));
+ DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for default-fade-in = %1\n", Properties::default_fade_in.property_id));
+ Properties::default_fade_out.property_id = g_quark_from_static_string (X_("default-fade-out"));
+ DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for default-fade-out = %1\n", Properties::default_fade_out.property_id));
+ Properties::fade_in_active.property_id = g_quark_from_static_string (X_("fade-in-active"));
+ DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for fade-in-active = %1\n", Properties::fade_in_active.property_id));
+ Properties::fade_out_active.property_id = g_quark_from_static_string (X_("fade-out-active"));
+ DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for fade-out-active = %1\n", Properties::fade_out_active.property_id));
+ Properties::scale_amplitude.property_id = g_quark_from_static_string (X_("scale-amplitude"));
+ DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for scale-amplitude = %1\n", Properties::scale_amplitude.property_id));
}
void
}
#define AUDIOREGION_STATE_DEFAULT \
- _envelope_active (Properties::envelope_active, EnvelopeActiveChanged, false) \
- , _default_fade_in (Properties::default_fade_in, FadeInChanged, true) \
- , _default_fade_out (Properties::default_fade_out, FadeOutChanged, true) \
- , _fade_in_active (Properties::fade_in_active, FadeInActiveChanged, true) \
- , _fade_out_active (Properties::fade_out_active, FadeOutActiveChanged, true) \
- , _scale_amplitude (Properties::scale_amplitude, ScaleAmplitudeChanged, 1.0)
-
+ _envelope_active (Properties::envelope_active, false) \
+ , _default_fade_in (Properties::default_fade_in, true) \
+ , _default_fade_out (Properties::default_fade_out, true) \
+ , _fade_in_active (Properties::fade_in_active, true) \
+ , _fade_out_active (Properties::fade_out_active, true) \
+ , _scale_amplitude (Properties::scale_amplitude, 1.0)
+
#define AUDIOREGION_COPY_STATE(other) \
- _envelope_active (other->_envelope_active) \
- , _default_fade_in (other->_default_fade_in) \
- , _default_fade_out (other->_default_fade_out) \
- , _fade_in_active (other->_fade_in_active) \
- , _fade_out_active (other->_fade_out_active) \
- , _scale_amplitude (other->_scale_amplitude)
-
-PropertyChange AudioRegion::FadeInChanged = PBD::new_change();
-PropertyChange AudioRegion::FadeOutChanged = PBD::new_change();
-PropertyChange AudioRegion::FadeInActiveChanged = PBD::new_change();
-PropertyChange AudioRegion::FadeOutActiveChanged = PBD::new_change();
-PropertyChange AudioRegion::EnvelopeActiveChanged = PBD::new_change();
-PropertyChange AudioRegion::ScaleAmplitudeChanged = PBD::new_change();
-PropertyChange AudioRegion::EnvelopeChanged = PBD::new_change();
-
+ _envelope_active (Properties::envelope_active, other->_envelope_active) \
+ , _default_fade_in (Properties::default_fade_in, other->_default_fade_in) \
+ , _default_fade_out (Properties::default_fade_out, other->_default_fade_out) \
+ , _fade_in_active (Properties::fade_in_active, other->_fade_in_active) \
+ , _fade_out_active (Properties::fade_out_active, other->_fade_out_active) \
+ , _scale_amplitude (Properties::scale_amplitude, other->_scale_amplitude)
/* a Session will reset these to its chosen defaults by calling AudioRegion::set_default_fade() */
void
{
register_properties ();
+ suspend_property_changes();
set_default_fades ();
set_default_envelope ();
+ resume_property_changes();
listen_to_my_curves ();
connect_to_analysis_changed ();
assert (_sources.size() == _master_sources.size());
}
-/** Basic AudioRegion constructor (one channel) */
-AudioRegion::AudioRegion (boost::shared_ptr<AudioSource> src)
- : Region (boost::static_pointer_cast<Source>(src))
- , AUDIOREGION_STATE_DEFAULT
- , _automatable(src->session())
- , _fade_in (new AutomationList(Evoral::Parameter(FadeInAutomation)))
- , _fade_out (new AutomationList(Evoral::Parameter(FadeOutAutomation)))
- , _envelope (new AutomationList(Evoral::Parameter(EnvelopeAutomation)))
- , _fade_in_suspended (0)
- , _fade_out_suspended (0)
-{
- init ();
-
- /* XXX why is this set here ? - set in a property list given to RegionFactory */
- _external = true;
-
- assert (_sources.size() == _master_sources.size());
-}
-
-/** Basic AudioRegion constructor (many channels) */
+/** Basic AudioRegion constructor */
AudioRegion::AudioRegion (const SourceList& srcs)
: Region (srcs)
, AUDIOREGION_STATE_DEFAULT
assert (_sources.size() == _master_sources.size());
}
-AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other, nframes64_t offset, bool offset_relative)
+AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other, framecnt_t offset, bool offset_relative)
: Region (other, offset, offset_relative)
, AUDIOREGION_COPY_STATE (other)
, _automatable (other->session())
, _fade_in (new AutomationList (*other->_fade_in))
, _fade_out (new AutomationList (*other->_fade_out))
- /* XXX is this guaranteed to work for all values of offset+offset_relative? */
- , _envelope (new AutomationList (*other->_envelope, _start, _start + _length))
+ /* 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 (new AutomationList (*other->_envelope, offset, other->_length))
, _fade_in_suspended (0)
, _fade_out_suspended (0)
{
assert (_sources.size() == _master_sources.size());
}
-AudioRegion::AudioRegion (boost::shared_ptr<AudioSource> src, const XMLNode& node)
- : Region (src, node)
- , AUDIOREGION_STATE_DEFAULT
- , _automatable(src->session())
- , _fade_in (new AutomationList(Evoral::Parameter(FadeInAutomation)))
- , _fade_out (new AutomationList(Evoral::Parameter(FadeOutAutomation)))
- , _envelope (new AutomationList(Evoral::Parameter(EnvelopeAutomation)))
-{
- init ();
-
- if (set_state (node, Stateful::loading_state_version)) {
- throw failed_constructor();
- }
-
- assert(_type == DataType::AUDIO);
- assert (_sources.size() == _master_sources.size());
-}
-
-AudioRegion::AudioRegion (SourceList& srcs, const XMLNode& node)
- : Region (srcs, node)
+AudioRegion::AudioRegion (SourceList& srcs)
+ : Region (srcs)
, AUDIOREGION_STATE_DEFAULT
, _automatable(srcs[0]->session())
, _fade_in (new AutomationList(Evoral::Parameter(FadeInAutomation)))
{
init ();
- if (set_state (node, Stateful::loading_state_version)) {
- throw failed_constructor();
- }
-
assert(_type == DataType::AUDIO);
- connect_to_analysis_changed ();
assert (_sources.size() == _master_sources.size());
}
set_default_fade_in ();
_right_of_split = false;
}
+
+ /* If _length changed, adjust our gain envelope accordingly */
+ _envelope->truncate_end (_length);
}
void
for (SourceList::const_iterator i = _sources.begin(); i != _sources.end(); ++i) {
+ /* connect only once to HeaderPositionOffsetChanged, even if sources are replicated
+ */
+
if (unique_srcs.find (*i) == unique_srcs.end ()) {
unique_srcs.insert (*i);
boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (*i);
{
if (envelope_active() != yn) {
_envelope_active = yn;
- send_change (EnvelopeActiveChanged);
+ send_change (PropertyChange (Properties::envelope_active));
}
}
return _read_at (_sources, _length, buf, 0, 0, _position + timeline_position, cnt, channel, 0, 0, ReadOps (0));
}
-framecnt_t
-AudioRegion::read_with_ops (Sample* buf, framepos_t file_position, framecnt_t cnt, int channel, ReadOps rops) const
-{
- return _read_at (_sources, _length, buf, 0, 0, file_position, cnt, channel, 0, 0, rops);
-}
-
framecnt_t
AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer,
framepos_t file_position, framecnt_t cnt, uint32_t chan_n,
framecnt_t to_read;
bool raw = (rops == ReadOpsNone);
+ if (n_channels() == 0) {
+ return 0;
+ }
+
if (muted() && !raw) {
return 0; /* read nothing */
}
we don't have.
*/
- memset (mixdown_buffer, 0, sizeof (Sample) * cnt);
+ if (Config->get_replicate_missing_region_channels()) {
+ /* track is N-channel, this region has less channels, so use a relevant channel
+ */
+
+ uint32_t channel = n_channels() % chan_n;
+ boost::shared_ptr<AudioSource> src = audio_source (channel);
+
+ if (src->read (mixdown_buffer, _start + internal_offset, to_read) != to_read) {
+ return 0; /* "read nothing" */
+ }
+
+ /* adjust read data count appropriately since this was a duplicate read */
+ src->dec_read_data_count (to_read);
+ } else {
+ memset (mixdown_buffer, 0, sizeof (Sample) * cnt);
+ }
}
if (rops & ReadOpsFades) {
}
}
- if (!opaque()) {
+ if (!opaque() && (buf != mixdown_buffer)) {
/* gack. the things we do for users.
*/
}
XMLNode&
-AudioRegion::state (bool full)
+AudioRegion::state ()
{
- XMLNode& node (Region::state (full));
+ XMLNode& node (Region::state ());
XMLNode *child;
char buf[64];
- char buf2[64];
LocaleGuard lg (X_("POSIX"));
-
- // XXX these should move into Region
-
- for (uint32_t n=0; n < _sources.size(); ++n) {
- snprintf (buf2, sizeof(buf2), "source-%d", n);
- _sources[n]->id().print (buf, sizeof (buf));
- node.add_property (buf2, buf);
- }
-
- for (uint32_t n=0; n < _master_sources.size(); ++n) {
- snprintf (buf2, sizeof(buf2), "master-source-%d", n);
- _master_sources[n]->id().print (buf, sizeof (buf));
- node.add_property (buf2, buf);
- }
-
snprintf (buf, sizeof (buf), "%u", (uint32_t) _sources.size());
node.add_property ("channels", buf);
- if (full) {
- Stateful::add_properties (node);
- }
+ Stateful::add_properties (node);
child = node.add_child ("Envelope");
- if (full) {
- bool default_env = false;
-
- // If there are only two points, the points are in the start of the region and the end of the region
- // so, if they are both at 1.0f, that means the default region.
-
- if (_envelope->size() == 2 &&
- _envelope->front()->value == 1.0f &&
- _envelope->back()->value==1.0f) {
- if (_envelope->front()->when == 0 && _envelope->back()->when == _length) {
- default_env = true;
- }
+ bool default_env = false;
+
+ // If there are only two points, the points are in the start of the region and the end of the region
+ // so, if they are both at 1.0f, that means the default region.
+
+ if (_envelope->size() == 2 &&
+ _envelope->front()->value == 1.0f &&
+ _envelope->back()->value==1.0f) {
+ if (_envelope->front()->when == 0 && _envelope->back()->when == _length) {
+ default_env = true;
}
+ }
+
+ if (default_env) {
+ child->add_property ("default", "yes");
+ } else {
+ child->add_child_nocopy (_envelope->get_state ());
+ }
- if (default_env) {
- child->add_property ("default", "yes");
- } else {
- child->add_child_nocopy (_envelope->get_state ());
- }
+ child = node.add_child (X_("FadeIn"));
- } else {
+ if (_default_fade_in) {
child->add_property ("default", "yes");
+ } else {
+ child->add_child_nocopy (_fade_in->get_state ());
}
- if (full && _extra_xml) {
- node.add_child_copy (*_extra_xml);
+ child = node.add_child (X_("FadeOut"));
+
+ if (_default_fade_out) {
+ child->add_property ("default", "yes");
+ } else {
+ child->add_child_nocopy (_fade_out->get_state ());
}
return node;
LocaleGuard lg (X_("POSIX"));
boost::shared_ptr<Playlist> the_playlist (_playlist.lock());
- freeze ();
+ suspend_property_changes ();
if (the_playlist) {
the_playlist->freeze ();
float a = atof (prop->value().c_str());
if (a != _scale_amplitude) {
_scale_amplitude = a;
- what_changed = PropertyChange (what_changed|ScaleAmplitudeChanged);
- cerr << _name << " amp changed\n";
+ what_changed.add (Properties::scale_amplitude);
}
}
/* Now find envelope description and other related child items */
- _envelope->freeze ();
+ _envelope->freeze ();
for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
XMLNode *child;
_envelope->set_max_xval (_length);
_envelope->truncate_end (_length);
- cerr << _name << " envelope changd\n";
-
} else if (child->name() == "FadeIn") {
set_fade_in_active (false);
}
}
- cerr << _name << " fadein changd\n";
} else if (child->name() == "FadeOut") {
set_fade_out_active (false);
}
}
- cerr << _name << " fadeout changd\n";
}
}
- _envelope->thaw ();
- thaw ();
-
+ _envelope->thaw ();
+ resume_property_changes ();
+
if (send) {
- cerr << _name << ": audio final change: " << hex << what_changed << dec << endl;
send_change (what_changed);
}
return 0;
}
-PropertyChange
-AudioRegion::set_property (const PropertyBase& prop)
-{
- PropertyChange c = PropertyChange (0);
-
- DEBUG_TRACE (DEBUG::Properties, string_compose ("audio region %1 set property %2\n", _name.val(), prop.property_name()));
-
- if (prop == Properties::envelope_active.id) {
- bool val = dynamic_cast<const PropertyTemplate<bool>*>(&prop)->val();
- if (val != _envelope_active) {
- _envelope_active = val;
- c = EnvelopeActiveChanged;
- }
- } else if (prop == Properties::default_fade_in.id) {
- bool val = dynamic_cast<const PropertyTemplate<bool>*>(&prop)->val();
- if (val != _default_fade_in) {
- _default_fade_in = val;
- c = FadeInChanged;
- }
- } else if (prop == Properties::default_fade_out.id) {
- bool val = dynamic_cast<const PropertyTemplate<bool>*>(&prop)->val();
- if (val != _default_fade_out) {
- _default_fade_out = val;
- c = FadeOutChanged;
- }
- } else if (prop == Properties::fade_in_active.id) {
- bool val = dynamic_cast<const PropertyTemplate<bool>*>(&prop)->val();
- if (val != _fade_in_active) {
- _fade_in_active = val;
- c = FadeInActiveChanged;
- }
- } else if (prop == Properties::fade_out_active.id) {
- bool val = dynamic_cast<const PropertyTemplate<bool>*>(&prop)->val();
- if (val != _fade_out_active) {
- _fade_out_active = val;
- c = FadeOutChanged;
- }
- } else if (prop == Properties::scale_amplitude.id) {
- gain_t val = dynamic_cast<const PropertyTemplate<gain_t>*>(&prop)->val();
- if (val != _scale_amplitude) {
- _scale_amplitude = val;
- c = ScaleAmplitudeChanged;
- }
- } else {
- return Region::set_property (prop);
- }
-
- return c;
-}
-
int
AudioRegion::set_state (const XMLNode& node, int version)
{
void
AudioRegion::set_fade_in (boost::shared_ptr<AutomationList> f)
{
- _fade_in->freeze ();
+ _fade_in->freeze ();
*_fade_in = *f;
- _fade_in->thaw ();
+ _fade_in->thaw ();
- send_change (FadeInChanged);
+ send_change (PropertyChange (Properties::fade_in));
}
void
AudioRegion::set_fade_in (FadeShape shape, framecnt_t len)
{
- _fade_in->freeze ();
+ _fade_in->freeze ();
_fade_in->clear ();
switch (shape) {
- case Linear:
+ case FadeLinear:
_fade_in->fast_simple_add (0.0, 0.0);
_fade_in->fast_simple_add (len, 1.0);
break;
- case Fast:
+ case FadeFast:
_fade_in->fast_simple_add (0, 0);
_fade_in->fast_simple_add (len * 0.389401, 0.0333333);
_fade_in->fast_simple_add (len * 0.629032, 0.0861111);
_fade_in->fast_simple_add (len, 1);
break;
- case Slow:
+ case FadeSlow:
_fade_in->fast_simple_add (0, 0);
_fade_in->fast_simple_add (len * 0.0207373, 0.197222);
_fade_in->fast_simple_add (len * 0.0645161, 0.525);
_fade_in->fast_simple_add (len, 1);
break;
- case LogA:
+ case FadeLogA:
_fade_in->fast_simple_add (0, 0);
_fade_in->fast_simple_add (len * 0.0737327, 0.308333);
_fade_in->fast_simple_add (len * 0.246544, 0.658333);
_fade_in->fast_simple_add (len, 1);
break;
- case LogB:
+ case FadeLogB:
_fade_in->fast_simple_add (0, 0);
_fade_in->fast_simple_add (len * 0.304147, 0.0694444);
_fade_in->fast_simple_add (len * 0.529954, 0.152778);
break;
}
- _fade_in->thaw ();
+ _fade_in->thaw ();
+ send_change (PropertyChange (Properties::fade_in));
}
void
AudioRegion::set_fade_out (boost::shared_ptr<AutomationList> f)
{
- _fade_out->freeze ();
+ _fade_out->freeze ();
*_fade_out = *f;
- _fade_out->thaw ();
+ _fade_out->thaw ();
- send_change (FadeInChanged);
+ send_change (PropertyChange (Properties::fade_in));
}
void
AudioRegion::set_fade_out (FadeShape shape, framecnt_t len)
{
- _fade_out->freeze ();
+ _fade_out->freeze ();
_fade_out->clear ();
switch (shape) {
- case Fast:
+ case FadeFast:
_fade_out->fast_simple_add (len * 0, 1);
_fade_out->fast_simple_add (len * 0.023041, 0.697222);
_fade_out->fast_simple_add (len * 0.0553, 0.483333);
_fade_out->fast_simple_add (len * 1, 0);
break;
- case LogA:
+ case FadeLogA:
_fade_out->fast_simple_add (len * 0, 1);
_fade_out->fast_simple_add (len * 0.228111, 0.988889);
_fade_out->fast_simple_add (len * 0.347926, 0.972222);
_fade_out->fast_simple_add (len * 1, 0);
break;
- case Slow:
+ case FadeSlow:
_fade_out->fast_simple_add (len * 0, 1);
_fade_out->fast_simple_add (len * 0.305556, 1);
_fade_out->fast_simple_add (len * 0.548611, 0.991736);
_fade_out->fast_simple_add (len * 1, 0);
break;
- case LogB:
+ case FadeLogB:
_fade_out->fast_simple_add (len * 0, 1);
_fade_out->fast_simple_add (len * 0.080645, 0.730556);
_fade_out->fast_simple_add (len * 0.277778, 0.289256);
_fade_out->fast_simple_add (len * 1, 0);
break;
- case Linear:
+ case FadeLinear:
_fade_out->fast_simple_add (len * 0, 1);
_fade_out->fast_simple_add (len * 1, 0);
break;
}
- _fade_out->thaw ();
+ _fade_out->thaw ();
+ send_change (PropertyChange (Properties::fade_in));
}
void
if (changed) {
_default_fade_in = false;
- send_change (FadeInChanged);
+ send_change (PropertyChange (Properties::fade_in));
}
}
if (changed) {
_default_fade_out = false;
- send_change (FadeOutChanged);
+ send_change (PropertyChange (Properties::fade_out));
}
}
}
_fade_in_active = yn;
- send_change (FadeInActiveChanged);
+ send_change (PropertyChange (Properties::fade_in_active));
}
void
return;
}
_fade_out_active = yn;
- send_change (FadeOutActiveChanged);
+ send_change (PropertyChange (Properties::fade_out_active));
}
bool
AudioRegion::set_default_fade_in ()
{
_fade_in_suspended = 0;
- set_fade_in (Linear, 64);
+ set_fade_in (FadeLinear, 64);
}
void
AudioRegion::set_default_fade_out ()
{
_fade_out_suspended = 0;
- set_fade_out (Linear, 64);
+ set_fade_out (FadeLinear, 64);
}
void
void
AudioRegion::set_default_envelope ()
{
- _envelope->freeze ();
+ _envelope->freeze ();
_envelope->clear ();
_envelope->fast_simple_add (0, 1.0f);
_envelope->fast_simple_add (_length, 1.0f);
- _envelope->thaw ();
+ _envelope->thaw ();
}
void
based on the the existing curve.
*/
- _envelope->freeze ();
+ _envelope->freeze ();
_envelope->truncate_end (_length);
_envelope->set_max_xval (_length);
- _envelope->thaw ();
-
+ _envelope->thaw ();
+
+ suspend_property_changes();
+
+ if (_left_of_split) {
+ set_default_fade_out ();
+ _left_of_split = false;
+ } else if (_fade_out->back()->when > _length) {
+ _fade_out->extend_to (_length);
+ send_change (PropertyChange (Properties::fade_out));
+ }
+
if (_fade_in->back()->when > _length) {
_fade_in->extend_to (_length);
- send_change (FadeInChanged);
- }
-
- if (_fade_out->back()->when > _length) {
- _fade_out->extend_to (_length);
- send_change (FadeOutChanged);
+ send_change (PropertyChange (Properties::fade_in));
}
+
+ resume_property_changes();
}
void
/* as above, but the shift was from the front */
_envelope->truncate_start (_length);
+
+ suspend_property_changes();
- if (_fade_in->back()->when > _length) {
+ if (_right_of_split) {
+ set_default_fade_in ();
+ _right_of_split = false;
+ } else if (_fade_in->back()->when > _length) {
_fade_in->extend_to (_length);
- send_change (FadeInChanged);
+ send_change (PropertyChange (Properties::fade_in));
}
if (_fade_out->back()->when > _length) {
_fade_out->extend_to (_length);
- send_change (FadeOutChanged);
+ send_change (PropertyChange (Properties::fade_out));
}
+
+ resume_property_changes();
}
int
/* tell everybody else */
- send_change (ScaleAmplitudeChanged);
+ send_change (PropertyChange (Properties::scale_amplitude));
}
-void
-AudioRegion::normalize_to (float target_dB)
+/** @return the maximum (linear) amplitude of the region */
+double
+AudioRegion::maximum_amplitude (Progress* p) const
{
- const framecnt_t blocksize = 64 * 1024;
- Sample buf[blocksize];
- framepos_t fpos;
- framepos_t fend;
- framecnt_t to_read;
+ framepos_t fpos = _start;
+ framepos_t const fend = _start + _length;
double maxamp = 0;
- gain_t target = dB_to_coefficient (target_dB);
-
- if (target == 1.0f) {
- /* do not normalize to precisely 1.0 (0 dBFS), to avoid making it appear
- that we may have clipped.
- */
- target -= FLT_EPSILON;
- }
-
- fpos = _start;
- fend = _start + _length;
-
- /* first pass: find max amplitude */
+ framecnt_t const blocksize = 64 * 1024;
+ Sample buf[blocksize];
+
while (fpos < fend) {
uint32_t n;
- to_read = min (fend - fpos, blocksize);
+ framecnt_t const to_read = min (fend - fpos, blocksize);
for (n = 0; n < n_channels(); ++n) {
/* read it in */
if (read_raw_internal (buf, fpos, to_read, 0) != to_read) {
- return;
+ return 0;
}
maxamp = compute_peak (buf, to_read, maxamp);
}
fpos += to_read;
- };
+ p->set_progress (float (fpos - _start) / _length);
+ }
+
+ return maxamp;
+}
- if (maxamp == 0.0f) {
+/** Normalize using a given maximum amplitude and target, so that region
+ * _scale_amplitude becomes target / max_amplitude.
+ */
+void
+AudioRegion::normalize (float max_amplitude, float target_dB)
+{
+ gain_t target = dB_to_coefficient (target_dB);
+
+ if (target == 1.0f) {
+ /* do not normalize to precisely 1.0 (0 dBFS), to avoid making it appear
+ that we may have clipped.
+ */
+ target -= FLT_EPSILON;
+ }
+
+ if (max_amplitude == 0.0f) {
/* don't even try */
return;
}
- if (maxamp == target) {
+ if (max_amplitude == target) {
/* we can't do anything useful */
return;
}
- /* compute scale factor */
-
- _scale_amplitude = target/maxamp;
-
- /* tell the diskstream we're in */
-
- boost::shared_ptr<Playlist> pl (playlist());
-
- if (pl) {
- pl->ContentsChanged();
- }
-
- /* tell everybody else */
-
- send_change (ScaleAmplitudeChanged);
+ set_scale_amplitude (target / max_amplitude);
}
void
AudioRegion::fade_in_changed ()
{
- send_change (FadeInChanged);
+ send_change (PropertyChange (Properties::fade_in));
}
void
AudioRegion::fade_out_changed ()
{
- send_change (FadeOutChanged);
+ send_change (PropertyChange (Properties::fade_out));
}
void
AudioRegion::envelope_changed ()
{
- send_change (EnvelopeChanged);
+ send_change (PropertyChange (Properties::envelope));
}
void
return boost::dynamic_pointer_cast<AudioSource>(source(n));
}
+int
+AudioRegion::adjust_transients (frameoffset_t delta)
+{
+ for (AnalysisFeatureList::iterator x = _transients.begin(); x != _transients.end(); ++x) {
+ (*x) = (*x) + delta;
+ }
+
+ send_change (PropertyChange (Properties::valid_transients));
+
+ return 0;
+}
+
+int
+AudioRegion::update_transient (framepos_t old_position, framepos_t new_position)
+{
+ for (AnalysisFeatureList::iterator x = _transients.begin(); x != _transients.end(); ++x) {
+ if ((*x) == old_position) {
+ (*x) = new_position;
+ send_change (PropertyChange (Properties::valid_transients));
+
+ break;
+ }
+ }
+
+ return 0;
+}
+
+void
+AudioRegion::add_transient (framepos_t where)
+{
+ _transients.push_back(where);
+ _valid_transients = true;
+
+ send_change (PropertyChange (Properties::valid_transients));
+}
+
+void
+AudioRegion::remove_transient (framepos_t where)
+{
+ _transients.remove(where);
+ _valid_transients = true;
+
+ send_change (PropertyChange (Properties::valid_transients));
+}
+
+int
+AudioRegion::set_transients (AnalysisFeatureList& results)
+{
+ _transients.clear();
+ _transients = results;
+ _valid_transients = true;
+
+ send_change (PropertyChange (Properties::valid_transients));
+
+ return 0;
+}
+
int
AudioRegion::get_transients (AnalysisFeatureList& results, bool force_new)
{
/* no existing/complete transient info */
+ static bool analyse_dialog_shown = false; /* global per instance of Ardour */
+
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\
+You currently have \"auto-analyse-audio\" disabled, which means \
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."));
+If you are doing work that will require transient data on a \
+regular basis, you should probably enable \"auto-analyse-audio\" \
+then quit ardour and restart.\n\n\
+This dialog will not display again. But you may notice a slight delay \
+in this and future transient-detection operations.\n\
+"));
+ analyse_dialog_shown = true;
+ }
}
TransientDetector t (pl->session().frame_rate());
*/
std::list<std::pair<frameoffset_t, framecnt_t> >
-AudioRegion::find_silence (Sample threshold, framecnt_t min_length) const
+AudioRegion::find_silence (Sample threshold, framecnt_t min_length, InterThreadInfo& itt) const
{
framecnt_t const block_size = 64 * 1024;
Sample loudest[block_size];
frameoffset_t silence_start = 0;
bool silence;
- while (pos < end) {
+ while (pos < end && !itt.cancel) {
/* fill `loudest' with the loudest absolute sample at each instant, across all channels */
memset (loudest, 0, sizeof (Sample) * block_size);
}
pos += block_size;
+ itt.progress = (end-pos)/(double)_length;
}
if (in_silence && end - 1 - silence_start >= min_length) {
silent_periods.push_back (std::make_pair (silence_start, end));
}
+ itt.done = true;
+
return silent_periods;
}