+int
+AudioRegion::get_transients (AnalysisFeatureList& results, bool force_new)
+{
+ boost::shared_ptr<Playlist> pl = playlist();
+
+ if (!pl) {
+ return -1;
+ }
+
+ if (valid_transients && !force_new) {
+ results = _transients;
+ return 0;
+ }
+
+ 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;
+ }
+
+ /* no existing/complete transient info */
+
+ static bool analyse_dialog_shown = false;
+ if (!Config->get_auto_analyse_audio()) {
+ 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.\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());
+ bool existing_results = !results.empty();
+
+ _transients.clear ();
+ valid_transients = false;
+
+ for (uint32_t i = 0; i < n_channels(); ++i) {
+
+ AnalysisFeatureList these_results;
+
+ t.reset ();
+
+ if (t.run ("", this, i, these_results)) {
+ return -1;
+ }
+
+ /* translate all transients to give absolute position */
+
+ for (AnalysisFeatureList::iterator i = these_results.begin(); i != these_results.end(); ++i) {
+ (*i) += _position;
+ }
+
+ /* merge */
+
+ _transients.insert (_transients.end(), these_results.begin(), these_results.end());
+ }
+
+ if (!results.empty()) {
+ if (existing_results) {
+
+ /* merge our transients into the existing ones, then clean up
+ those.
+ */
+
+ results.insert (results.end(), _transients.begin(), _transients.end());
+ TransientDetector::cleanup_transients (results, pl->session().frame_rate(), 3.0);
+ }
+
+ /* make sure ours are clean too */
+
+ TransientDetector::cleanup_transients (_transients, pl->session().frame_rate(), 3.0);
+
+ } else {
+
+ TransientDetector::cleanup_transients (_transients, pl->session().frame_rate(), 3.0);
+ results = _transients;
+ }
+
+ valid_transients = true;
+
+ return 0;
+}
+