summaryrefslogtreecommitdiff
path: root/libs/ardour/audioregion.cc
diff options
context:
space:
mode:
Diffstat (limited to 'libs/ardour/audioregion.cc')
-rw-r--r--libs/ardour/audioregion.cc113
1 files changed, 67 insertions, 46 deletions
diff --git a/libs/ardour/audioregion.cc b/libs/ardour/audioregion.cc
index 822fe2cb72..20115ff944 100644
--- a/libs/ardour/audioregion.cc
+++ b/libs/ardour/audioregion.cc
@@ -66,12 +66,12 @@ void
AudioRegion::init ()
{
_scale_amplitude = 1.0;
- valid_transients = false;
set_default_fades ();
set_default_envelope ();
listen_to_my_curves ();
+ listen_to_my_sources ();
}
/* constructor for use by derived types only */
@@ -122,6 +122,7 @@ AudioRegion::AudioRegion (const SourceList& srcs, nframes_t start, nframes_t len
, _envelope (new AutomationList(Parameter(EnvelopeAutomation), 0.0, 2.0, 1.0))
{
init ();
+ listen_to_my_sources ();
}
/** Create a new AudioRegion, that is part of an existing one */
@@ -172,9 +173,9 @@ AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other, nframes_t
}
_scale_amplitude = other->_scale_amplitude;
- valid_transients = false;
assert(_type == DataType::AUDIO);
+ listen_to_my_sources ();
}
AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other)
@@ -183,15 +184,14 @@ AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other)
, _fade_out (new AutomationList(Parameter(FadeOutAutomation), 0.0, 2.0, 1.0))
, _envelope (new AutomationList(Parameter(EnvelopeAutomation), 0.0, 2.0, 1.0))
{
+ assert(_type == DataType::AUDIO);
_scale_amplitude = other->_scale_amplitude;
- valid_transients = false;
_envelope = other->_envelope;
set_default_fades ();
listen_to_my_curves ();
-
- assert(_type == DataType::AUDIO);
+ listen_to_my_sources ();
}
AudioRegion::AudioRegion (boost::shared_ptr<AudioSource> src, const XMLNode& node)
@@ -206,13 +206,13 @@ AudioRegion::AudioRegion (boost::shared_ptr<AudioSource> src, const XMLNode& nod
}
init ();
- valid_transients = false;
if (set_state (node)) {
throw failed_constructor();
}
assert(_type == DataType::AUDIO);
+ listen_to_my_sources ();
}
AudioRegion::AudioRegion (SourceList& srcs, const XMLNode& node)
@@ -228,6 +228,7 @@ AudioRegion::AudioRegion (SourceList& srcs, const XMLNode& node)
}
assert(_type == DataType::AUDIO);
+ listen_to_my_sources ();
}
AudioRegion::~AudioRegion ()
@@ -235,10 +236,11 @@ AudioRegion::~AudioRegion ()
}
void
-AudioRegion::invalidate_transients ()
+AudioRegion::listen_to_my_sources ()
{
- valid_transients = false;
- _transients.clear ();
+ for (SourceList::const_iterator i = _sources.begin(); i != _sources.end(); ++i) {
+ (*i)->AnalysisChanged.connect (mem_fun (*this, &AudioRegion::invalidate_transients));
+ }
}
void
@@ -1256,53 +1258,73 @@ AudioRegion::audio_source (uint32_t n) const
return boost::dynamic_pointer_cast<AudioSource>(source(n));
}
-void
-AudioRegion::cleanup_transients (vector<nframes64_t>& t)
-{
- sort (t.begin(), t.end());
-
- /* remove duplicates or other things that are too close */
-
- vector<nframes64_t>::iterator i = t.begin();
- nframes64_t curr = (*i);
-
- /* XXX force a 3msec gap - use a config variable */
-
- nframes64_t gap_frames = (nframes64_t) floor (3.0 * (playlist()->session().frame_rate() / 1000.0));
-
- ++i;
-
- while (i != t.end()) {
- if (((*i) == curr) || (((*i) - curr) < gap_frames)) {
- i = t.erase (i);
- } else {
- ++i;
- curr = *i;
- }
- }
-}
-
int
-AudioRegion::get_transients (vector<nframes64_t>& results, bool force_new)
+AudioRegion::get_transients (AnalysisFeatureList& results, bool force_new)
{
- if (!playlist()) {
+ boost::shared_ptr<Playlist> pl = playlist();
+
+ if (!pl) {
return -1;
}
- if (valid_transients && !force_new) {
+ if (_valid_transients && !force_new) {
results = _transients;
return 0;
}
- TransientDetector t (playlist()->session().frame_rate());
+ SourceList::iterator s;
+
+ for (s = _sources.begin() ; s != _sources.end(); ++s) {
+ if (!(*s)->has_been_analysed()) {
+ cerr << "For " << name() << " source " << (*s)->name() << " has not been analyzed\n";
+ break;
+ }
+ }
+
+ if (s == _sources.end()) {
+ /* all sources are analyzed, merge data from each one */
+
+ for (s = _sources.begin() ; s != _sources.end(); ++s) {
+
+ /* find the set of transients within the bounds of this region */
+
+ AnalysisFeatureList::iterator low = lower_bound ((*s)->transients.begin(),
+ (*s)->transients.end(),
+ _start);
+
+ AnalysisFeatureList::iterator high = upper_bound ((*s)->transients.begin(),
+ (*s)->transients.end(),
+ _start + _length);
+
+ /* and add them */
+
+ results.insert (results.end(), low, high);
+ }
+
+ TransientDetector::cleanup_transients (results, pl->session().frame_rate(), 3.0);
+
+ /* translate all transients to current position */
+
+ for (AnalysisFeatureList::iterator x = results.begin(); x != results.end(); ++x) {
+ (*x) -= _start;
+ (*x) += _position;
+ }
+
+ _transients = results;
+ _valid_transients = true;
+
+ return 0;
+ }
+
+ TransientDetector t (pl->session().frame_rate());
bool existing_results = !results.empty();
_transients.clear ();
- valid_transients = false;
+ _valid_transients = false;
for (uint32_t i = 0; i < n_channels(); ++i) {
- vector<nframes64_t> these_results;
+ AnalysisFeatureList these_results;
t.reset ();
@@ -1312,7 +1334,7 @@ AudioRegion::get_transients (vector<nframes64_t>& results, bool force_new)
/* translate all transients to give absolute position */
- for (vector<nframes64_t>::iterator i = these_results.begin(); i != these_results.end(); ++i) {
+ for (AnalysisFeatureList::iterator i = these_results.begin(); i != these_results.end(); ++i) {
(*i) += _position;
}
@@ -1329,20 +1351,19 @@ AudioRegion::get_transients (vector<nframes64_t>& results, bool force_new)
*/
results.insert (results.end(), _transients.begin(), _transients.end());
- cleanup_transients (results);
+ TransientDetector::cleanup_transients (results, pl->session().frame_rate(), 3.0);
}
/* make sure ours are clean too */
- cleanup_transients (_transients);
+ TransientDetector::cleanup_transients (_transients, pl->session().frame_rate(), 3.0);
}
- valid_transients = true;
+ _valid_transients = true;
return 0;
}
-
extern "C" {
int region_read_peaks_from_c (void *arg, uint32_t npeaks, uint32_t start, uint32_t cnt, intptr_t data, uint32_t n_chan, double samples_per_unit)