totally untested initial code for MidiPlaylistSource, to provide for compound MIDI...
[ardour.git] / libs / ardour / audioregion.cc
index 992ae7fab28269a08850f680e30e31868cb6053a..447e4b8d953c8ec5fd9c6d6ac0f2afe2d311f8e9 100644 (file)
@@ -24,6 +24,7 @@
 
 #include <set>
 
+#include <boost/scoped_array.hpp>
 
 #include <glibmm/thread.h>
 
@@ -45,6 +46,7 @@
 #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>
@@ -68,17 +70,17 @@ void
 AudioRegion::make_property_quarks ()
 {
        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));
+       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));
+       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));
+       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));
+       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));
+       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));
+       DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for scale-amplitude = %1\n",     Properties::scale_amplitude.property_id));
 }
 
 void
@@ -103,12 +105,12 @@ AudioRegion::register_properties ()
        , _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)
+       _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
@@ -116,8 +118,10 @@ AudioRegion::init ()
 {
        register_properties ();
 
+       suspend_property_changes();
        set_default_fades ();
        set_default_envelope ();
+       resume_property_changes();
 
        listen_to_my_curves ();
        connect_to_analysis_changed ();
@@ -154,8 +158,32 @@ AudioRegion::AudioRegion (const SourceList& srcs)
        assert (_sources.size() == _master_sources.size());
 }
 
-AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other, nframes64_t offset, bool offset_relative)
-       : Region (other, offset, offset_relative)
+AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other)
+       : Region (other)
+       , AUDIOREGION_COPY_STATE (other)
+       , _automatable (other->session())
+       , _fade_in (new AutomationList (*other->_fade_in))
+       , _fade_out (new AutomationList (*other->_fade_out))
+         /* 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, 0, other->_length))
+       , _fade_in_suspended (0)
+       , _fade_out_suspended (0)
+{
+       /* don't use init here, because we got fade in/out from the other region
+       */
+       register_properties ();
+       listen_to_my_curves ();
+       connect_to_analysis_changed ();
+       connect_to_header_position_offset_changed ();
+
+       assert(_type == DataType::AUDIO);
+       assert (_sources.size() == _master_sources.size());
+}
+
+AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other, framecnt_t offset)
+       : Region (other, offset)
        , AUDIOREGION_COPY_STATE (other)
        , _automatable (other->session())
        , _fade_in (new AutomationList (*other->_fade_in))
@@ -220,7 +248,7 @@ AudioRegion::~AudioRegion ()
 }
 
 void
-AudioRegion::post_set ()
+AudioRegion::post_set (const PropertyChange& /*ignored*/)
 {
        if (!_sync_marked) {
                _sync_position = _start;
@@ -264,8 +292,8 @@ AudioRegion::connect_to_header_position_offset_changed ()
 
        for (SourceList::const_iterator i = _sources.begin(); i != _sources.end(); ++i) {
 
-                /* connect only once to HeaderPositionOffsetChanged, even if sources are replicated
-                 */
+               /* connect only once to HeaderPositionOffsetChanged, even if sources are replicated
+                */
 
                if (unique_srcs.find (*i) == unique_srcs.end ()) {
                        unique_srcs.insert (*i);
@@ -294,8 +322,8 @@ AudioRegion::set_envelope_active (bool yn)
        }
 }
 
-ARDOUR::nframes_t
-AudioRegion::read_peaks (PeakData *buf, nframes_t npeaks, nframes_t offset, nframes_t cnt, uint32_t chan_n, double samples_per_unit) const
+ARDOUR::framecnt_t
+AudioRegion::read_peaks (PeakData *buf, framecnt_t npeaks, framecnt_t offset, framecnt_t cnt, uint32_t chan_n, double samples_per_unit) const
 {
        if (chan_n >= _sources.size()) {
                return 0;
@@ -305,7 +333,7 @@ AudioRegion::read_peaks (PeakData *buf, nframes_t npeaks, nframes_t offset, nfra
                return 0;
        } else {
                if (_scale_amplitude != 1.0f) {
-                       for (nframes_t n = 0; n < npeaks; ++n) {
+                       for (framecnt_t n = 0; n < npeaks; ++n) {
                                buf[n].max *= _scale_amplitude;
                                buf[n].min *= _scale_amplitude;
                        }
@@ -356,9 +384,9 @@ AudioRegion::_read_at (const SourceList& /*srcs*/, framecnt_t limit,
        framecnt_t to_read;
        bool raw = (rops == ReadOpsNone);
 
-        if (n_channels() == 0) {
-                return 0;
-        }
+       if (n_channels() == 0) {
+               return 0;
+       }
 
        if (muted() && !raw) {
                return 0; /* read nothing */
@@ -411,22 +439,22 @@ AudioRegion::_read_at (const SourceList& /*srcs*/, framecnt_t limit,
                   we don't have.
                */
 
-                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 (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" */
-                        }
+                       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);
-                }
+                       /* 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) {
@@ -435,20 +463,19 @@ AudioRegion::_read_at (const SourceList& /*srcs*/, framecnt_t limit,
 
                if (_fade_in_active && _session.config.get_use_region_fades()) {
 
-                       nframes_t fade_in_length = (nframes_t) _fade_in->back()->when;
+                       framecnt_t fade_in_length = (framecnt_t) _fade_in->back()->when;
 
                        /* see if this read is within the fade in */
 
                        if (internal_offset < fade_in_length) {
 
-                               nframes_t fi_limit;
+                               framecnt_t fi_limit;
 
                                fi_limit = min (to_read, fade_in_length - internal_offset);
 
-
                                _fade_in->curve().get_vector (internal_offset, internal_offset+fi_limit, gain_buffer, fi_limit);
 
-                               for (nframes_t n = 0; n < fi_limit; ++n) {
+                               for (framecnt_t n = 0; n < fi_limit; ++n) {
                                        mixdown_buffer[n] *= gain_buffer[n];
                                }
                        }
@@ -477,20 +504,20 @@ AudioRegion::_read_at (const SourceList& /*srcs*/, framecnt_t limit,
                */
 
 
-                       nframes_t fade_out_length = (nframes_t) _fade_out->back()->when;
-                       nframes_t fade_interval_start = max(internal_offset, limit-fade_out_length);
-                       nframes_t fade_interval_end   = min(internal_offset + to_read, limit);
+                       framecnt_t fade_out_length     = (framecnt_t) _fade_out->back()->when;
+                       framecnt_t fade_interval_start = max(internal_offset, limit-fade_out_length);
+                       framecnt_t fade_interval_end   = min(internal_offset + to_read, limit);
 
                        if (fade_interval_end > fade_interval_start) {
                                /* (part of the) the fade out is  in this buffer */
 
-                               nframes_t fo_limit = fade_interval_end - fade_interval_start;
-                               nframes_t curve_offset = fade_interval_start - (limit-fade_out_length);
-                               nframes_t fade_offset = fade_interval_start - internal_offset;
+                               framecnt_t fo_limit = fade_interval_end - fade_interval_start;
+                               framecnt_t curve_offset = fade_interval_start - (limit-fade_out_length);
+                               framecnt_t fade_offset = fade_interval_start - internal_offset;
 
                                _fade_out->curve().get_vector (curve_offset, curve_offset+fo_limit, gain_buffer, fo_limit);
 
-                               for (nframes_t n = 0, m = fade_offset; n < fo_limit; ++n, ++m) {
+                               for (framecnt_t n = 0, m = fade_offset; n < fo_limit; ++n, ++m) {
                                        mixdown_buffer[m] *= gain_buffer[n];
                                }
                        }
@@ -504,11 +531,11 @@ AudioRegion::_read_at (const SourceList& /*srcs*/, framecnt_t limit,
                _envelope->curve().get_vector (internal_offset, internal_offset + to_read, gain_buffer, to_read);
 
                if ((rops & ReadOpsOwnScaling) && _scale_amplitude != 1.0f) {
-                       for (nframes_t n = 0; n < to_read; ++n) {
+                       for (framecnt_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) {
+                       for (framecnt_t n = 0; n < to_read; ++n) {
                                mixdown_buffer[n] *= gain_buffer[n];
                        }
                }
@@ -517,19 +544,19 @@ AudioRegion::_read_at (const SourceList& /*srcs*/, framecnt_t limit,
                // XXX this should be using what in 2.0 would have been:
                // Session::apply_gain_to_buffer (mixdown_buffer, to_read, _scale_amplitude);
 
-               for (nframes_t n = 0; n < to_read; ++n) {
+               for (framecnt_t n = 0; n < to_read; ++n) {
                        mixdown_buffer[n] *= _scale_amplitude;
                }
        }
 
-       if (!opaque()) {
+       if (!opaque() && (buf != mixdown_buffer)) {
 
                /* gack. the things we do for users.
                 */
 
                buf += buf_offset;
 
-               for (nframes_t n = 0; n < to_read; ++n) {
+               for (framecnt_t n = 0; n < to_read; ++n) {
                        buf[n] += mixdown_buffer[n];
                }
        }
@@ -621,7 +648,7 @@ AudioRegion::_set_state (const XMLNode& node, int version, PropertyChange& what_
 
        /* Now find envelope description and other related child items */
 
-        _envelope->freeze ();
+       _envelope->freeze ();
 
        for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
                XMLNode *child;
@@ -686,9 +713,9 @@ AudioRegion::_set_state (const XMLNode& node, int version, PropertyChange& what_
                }
        }
 
-        _envelope->thaw ();
+       _envelope->thaw ();
        resume_property_changes ();
-        
+
        if (send) {
                send_change (what_changed);
        }
@@ -710,21 +737,21 @@ AudioRegion::set_state (const XMLNode& node, int version)
 void
 AudioRegion::set_fade_in_shape (FadeShape shape)
 {
-       set_fade_in (shape, (nframes_t) _fade_in->back()->when);
+       set_fade_in (shape, (framecnt_t) _fade_in->back()->when);
 }
 
 void
 AudioRegion::set_fade_out_shape (FadeShape shape)
 {
-       set_fade_out (shape, (nframes_t) _fade_out->back()->when);
+       set_fade_out (shape, (framecnt_t) _fade_out->back()->when);
 }
 
 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 (PropertyChange (Properties::fade_in));
 }
@@ -732,16 +759,16 @@ AudioRegion::set_fade_in (boost::shared_ptr<AutomationList> f)
 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);
@@ -751,7 +778,7 @@ AudioRegion::set_fade_in (FadeShape shape, framecnt_t len)
                _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);
@@ -762,7 +789,7 @@ AudioRegion::set_fade_in (FadeShape shape, framecnt_t len)
                _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);
@@ -772,7 +799,7 @@ AudioRegion::set_fade_in (FadeShape shape, framecnt_t len)
                _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);
@@ -783,15 +810,16 @@ AudioRegion::set_fade_in (FadeShape shape, framecnt_t len)
                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 (PropertyChange (Properties::fade_in));
 }
@@ -799,11 +827,11 @@ AudioRegion::set_fade_out (boost::shared_ptr<AutomationList> f)
 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);
@@ -813,7 +841,7 @@ AudioRegion::set_fade_out (FadeShape shape, framecnt_t len)
                _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);
@@ -823,7 +851,7 @@ AudioRegion::set_fade_out (FadeShape shape, framecnt_t len)
                _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);
@@ -833,7 +861,7 @@ AudioRegion::set_fade_out (FadeShape shape, framecnt_t len)
                _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);
@@ -842,13 +870,14 @@ AudioRegion::set_fade_out (FadeShape shape, framecnt_t len)
                _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
@@ -918,14 +947,14 @@ void
 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
@@ -938,11 +967,11 @@ AudioRegion::set_default_fades ()
 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
@@ -952,23 +981,27 @@ AudioRegion::recompute_at_end ()
           based on the the existing curve.
        */
 
-        _envelope->freeze ();
+       _envelope->freeze ();
        _envelope->truncate_end (_length);
        _envelope->set_max_xval (_length);
-        _envelope->thaw ();
-
-        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));
-        }
-        
+       _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 (PropertyChange (Properties::fade_in));
        }
+       
+       resume_property_changes();
 }
 
 void
@@ -977,11 +1010,13 @@ AudioRegion::recompute_at_start ()
        /* as above, but the shift was from the front */
 
        _envelope->truncate_start (_length);
+       
+       suspend_property_changes();
 
-        if (_right_of_split) {
-                set_default_fade_in ();
-                _right_of_split = false;
-        } else 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 (PropertyChange (Properties::fade_in));
        }
@@ -990,6 +1025,8 @@ AudioRegion::recompute_at_start ()
                _fade_out->extend_to (_length);
                send_change (PropertyChange (Properties::fade_out));
        }
+       
+       resume_property_changes();
 }
 
 int
@@ -1043,15 +1080,15 @@ AudioRegion::separate_by_channel (Session& /*session*/, vector<boost::shared_ptr
 framecnt_t
 AudioRegion::read_raw_internal (Sample* buf, framepos_t pos, framecnt_t cnt, int channel) const
 {
-       return audio_source()->read (buf, pos, cnt, channel);
+       return audio_source(channel)->read (buf, pos, cnt);
 }
 
 int
 AudioRegion::exportme (Session& /*session*/, ARDOUR::ExportSpecification& /*spec*/)
 {
        // TODO EXPORT
-//     const nframes_t blocksize = 4096;
-//     nframes_t to_read;
+//     const framecnt_t blocksize = 4096;
+//     framecnt_t to_read;
 //     int status = -1;
 //
 //     spec.channels = _sources.size();
@@ -1086,7 +1123,7 @@ AudioRegion::exportme (Session& /*session*/, ARDOUR::ExportSpecification& /*spec
 //                                     goto out;
 //                             }
 //
-//                             for (nframes_t x = 0; x < to_read; ++x) {
+//                             for (framecnt_t x = 0; x < to_read; ++x) {
 //                                     spec.dataF[chan+(x*spec.channels)] = buf[x];
 //                             }
 //                     }
@@ -1130,9 +1167,11 @@ AudioRegion::set_scale_amplitude (gain_t g)
        send_change (PropertyChange (Properties::scale_amplitude));
 }
 
-/** @return the maximum (linear) amplitude of the region */
+/** @return the maximum (linear) amplitude of the region, or a -ve
+ *  number if the Progress object reports that the process was cancelled.
+ */
 double
-AudioRegion::maximum_amplitude () const
+AudioRegion::maximum_amplitude (Progress* p) const
 {
        framepos_t fpos = _start;
        framepos_t const fend = _start + _length;
@@ -1151,7 +1190,7 @@ AudioRegion::maximum_amplitude () const
 
                        /* read it in */
 
-                       if (read_raw_internal (buf, fpos, to_read, 0) != to_read) {
+                       if (read_raw_internal (buf, fpos, to_read, n) != to_read) {
                                return 0;
                        }
 
@@ -1159,6 +1198,12 @@ AudioRegion::maximum_amplitude () const
                }
 
                fpos += to_read;
+               if (p) {
+                       p->set_progress (float (fpos - _start) / _length);
+                       if (p->cancelled ()) {
+                               return -1;
+                       }
+               }
        }
 
        return maxamp;
@@ -1287,7 +1332,7 @@ AudioRegion::audio_source (uint32_t n) const
 }
 
 int 
-AudioRegion::adjust_transients (nframes64_t delta)
+AudioRegion::adjust_transients (frameoffset_t delta)
 {
        for (AnalysisFeatureList::iterator x = _transients.begin(); x != _transients.end(); ++x) {
                (*x) = (*x) + delta;
@@ -1299,7 +1344,7 @@ AudioRegion::adjust_transients (nframes64_t delta)
 } 
 
 int
-AudioRegion::update_transient (nframes64_t old_position, nframes64_t new_position)
+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) {
@@ -1314,7 +1359,7 @@ AudioRegion::update_transient (nframes64_t old_position, nframes64_t new_positio
 }
 
 void
-AudioRegion::add_transient (nframes64_t where)
+AudioRegion::add_transient (framepos_t where)
 {
        _transients.push_back(where);
        _valid_transients = true;
@@ -1323,7 +1368,7 @@ AudioRegion::add_transient (nframes64_t where)
 }
 
 void
-AudioRegion::remove_transient (nframes64_t where)
+AudioRegion::remove_transient (framepos_t where)
 {
        _transients.remove(where);
        _valid_transients = true;
@@ -1403,22 +1448,22 @@ AudioRegion::get_transients (AnalysisFeatureList& results, bool force_new)
 
        /* no existing/complete transient info */
 
-        static bool analyse_dialog_shown = false; /* global per instance of Ardour */
+       static bool analyse_dialog_shown = false; /* global per instance of Ardour */
 
        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\
+               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 \
 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;
-                }
+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());
@@ -1478,32 +1523,31 @@ regular basis, you should probably enable \"auto-analyse-audio\"\n\
  *
  *  @param threshold Threshold below which signal is considered silence (as a sample value)
  *  @param min_length Minimum length of silent period to be reported.
- *  @return Silent periods; first of pair is the offset within the region, second is the length of the period
+ *  @return Silent intervals, measured relative to the region start in the source
  */
 
-std::list<std::pair<frameoffset_t, framecnt_t> >
+AudioIntervalResult
 AudioRegion::find_silence (Sample threshold, framecnt_t min_length, InterThreadInfo& itt) const
 {
        framecnt_t const block_size = 64 * 1024;
-       Sample loudest[block_size];
-       Sample buf[block_size];
+       boost::scoped_array<Sample> loudest (new Sample[block_size]);
+       boost::scoped_array<Sample> buf (new Sample[block_size]);
 
        framepos_t pos = _start;
        framepos_t const end = _start + _length - 1;
 
-       std::list<std::pair<frameoffset_t, framecnt_t> > silent_periods;
+       AudioIntervalResult silent_periods;
 
        bool in_silence = false;
        frameoffset_t silence_start = 0;
-       bool silence;
 
        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);
+               memset (loudest.get(), 0, sizeof (Sample) * block_size);
                for (uint32_t n = 0; n < n_channels(); ++n) {
 
-                       read_raw_internal (buf, pos, block_size, n);
+                       read_raw_internal (buf.get(), pos, block_size, n);
                        for (framecnt_t i = 0; i < block_size; ++i) {
                                loudest[i] = max (loudest[i], abs (buf[i]));
                        }
@@ -1511,7 +1555,7 @@ AudioRegion::find_silence (Sample threshold, framecnt_t min_length, InterThreadI
 
                /* now look for silence */
                for (framecnt_t i = 0; i < block_size; ++i) {
-                       silence = abs (loudest[i]) < threshold;
+                       bool const silence = abs (loudest[i]) < threshold;
                        if (silence && !in_silence) {
                                /* non-silence to silence */
                                in_silence = true;
@@ -1526,7 +1570,7 @@ AudioRegion::find_silence (Sample threshold, framecnt_t min_length, InterThreadI
                }
 
                pos += block_size;
-                itt.progress = (end-pos)/(double)_length;
+               itt.progress = (end-pos)/(double)_length;
        }
 
        if (in_silence && end - 1 - silence_start >= min_length) {
@@ -1534,7 +1578,7 @@ AudioRegion::find_silence (Sample threshold, framecnt_t min_length, InterThreadI
                silent_periods.push_back (std::make_pair (silence_start, end));
        }
 
-        itt.done = true;
+       itt.done = true;
 
        return silent_periods;
 }