Automation of LV2 plugin properties.
[ardour.git] / libs / ardour / audioregion.cc
index 331de043cda7cc62cba212b59b726372786e9465..8c4eb6aa2a13d3f3eb2fb3a9bed2bedfcf7360d5 100644 (file)
@@ -540,21 +540,21 @@ AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer,
                /* see if some part of this read is within the fade out */
 
                /* .................        >|            REGION
-                                            _length
-
-                                 {           }            FADE
-                                            fade_out_length
-                                 ^
-                                 _length - fade_out_length
-                        |--------------|
-                        ^internal_offset
-                                       ^internal_offset + to_read
-
-                                      we need the intersection of [internal_offset,internal_offset+to_read] with
-                                      [_length - fade_out_length, _length]
-
-               */
-
+                *                           _length
+                *
+                *               {           }            FADE
+                *                           fade_out_length
+                *               ^
+                *               _length - fade_out_length
+                *
+                *      |--------------|
+                *      ^internal_offset
+                *                     ^internal_offset + to_read
+                *
+                *                     we need the intersection of [internal_offset,internal_offset+to_read] with
+                *                     [_length - fade_out_length, _length]
+                *
+                */
 
                fade_interval_start = max (internal_offset, _length - framecnt_t (_fade_out->back()->when));
                framecnt_t fade_interval_end = min(internal_offset + to_read, _length.val());
@@ -957,6 +957,34 @@ AudioRegion::set_state (const XMLNode& node, int version)
        return _set_state (node, version, what_changed, true);
 }
 
+void
+AudioRegion::fade_range (framepos_t start, framepos_t end)
+{
+       framepos_t s, e;
+
+       switch (coverage (start, end)) {
+       case Evoral::OverlapStart:
+               s = _position;
+               e = end;
+               set_fade_in (FadeConstantPower, e - s);
+               break;
+       case Evoral::OverlapEnd:
+               s = start;
+               e = _position + _length;
+               set_fade_out (FadeConstantPower, e - s);
+               break;
+       case Evoral::OverlapInternal:
+               /* needs addressing, perhaps. Difficult to do if we can't
+                * control one edge of the fade relative to the relevant edge
+                * of the region, which we cannot - fades are currently assumed
+                * to start/end at the start/end of the region
+                */
+               break;
+       default:
+               return;
+       }
+}
+
 void
 AudioRegion::set_fade_in_shape (FadeShape shape)
 {
@@ -991,23 +1019,25 @@ AudioRegion::set_fade_in (FadeShape shape, framecnt_t len)
        _fade_in->clear ();
        _inverse_fade_in->clear ();
 
+       const int num_steps = 32;
+
        switch (shape) {
        case FadeLinear:
-               _fade_in->fast_simple_add (0.0, 0.0);
+               _fade_in->fast_simple_add (0.0, VERY_SMALL_SIGNAL);
                _fade_in->fast_simple_add (len, 1.0);
                reverse_curve (_inverse_fade_in.val(), _fade_in.val());
                break;
 
        case FadeFast:
-               generate_db_fade (_fade_in.val(), len, 10, -60);
+               generate_db_fade (_fade_in.val(), len, num_steps, -60);
                reverse_curve (c1, _fade_in.val());
                _fade_in->copy_events (*c1);
                generate_inverse_power_curve (_inverse_fade_in.val(), _fade_in.val());
                break;
 
        case FadeSlow:
-               generate_db_fade (c1, len, 10, -1);  // start off with a slow fade
-               generate_db_fade (c2, len, 10, -80); // end with a fast fade
+               generate_db_fade (c1, len, num_steps, -1);  // start off with a slow fade
+               generate_db_fade (c2, len, num_steps, -80); // end with a fast fade
                merge_curves (_fade_in.val(), c1, c2);
                reverse_curve (c3, _fade_in.val());
                _fade_in->copy_events (*c3);
@@ -1015,9 +1045,10 @@ AudioRegion::set_fade_in (FadeShape shape, framecnt_t len)
                break;
 
        case FadeConstantPower:
-               for (int i = 0; i < 9; ++i) {
-                       float dist = (float) i / 10.0f;
-                       _fade_in->fast_simple_add (len*dist, sin (dist*M_PI/2));
+               _fade_in->fast_simple_add (0.0, VERY_SMALL_SIGNAL);
+               for (int i = 1; i < num_steps; ++i) {
+                       const float dist = i / (num_steps + 1.f);
+                       _fade_in->fast_simple_add (len * dist, sin (dist * M_PI / 2.0));
                }
                _fade_in->fast_simple_add (len, 1.0);
                reverse_curve (_inverse_fade_in.val(), _fade_in.val());
@@ -1026,16 +1057,12 @@ AudioRegion::set_fade_in (FadeShape shape, framecnt_t len)
        case FadeSymmetric:
                //start with a nearly linear cuve
                _fade_in->fast_simple_add (0, 1);
-               _fade_in->fast_simple_add (0.5*len, 0.6);
+               _fade_in->fast_simple_add (0.5 * len, 0.6);
                //now generate a fade-out curve by successively applying a gain drop
-               const float breakpoint = 0.7;  //linear for first 70%
-               const int num_steps = 9;
-               for (int i = 2; i < num_steps; i++) {
-                       float coeff = (1.0-breakpoint);
-                       for (int j = 0; j < i; j++) {
-                               coeff *= 0.5;  //6dB drop per step
-                       }
-                       _fade_in->fast_simple_add (len* (breakpoint+((1.0-breakpoint)*(double)i/(double)num_steps)), coeff);
+               const double breakpoint = 0.7;  //linear for first 70%
+               for (int i = 2; i < 9; ++i) {
+                       const float coeff = (1.f - breakpoint) * powf (0.5, i);
+                       _fade_in->fast_simple_add (len * (breakpoint + ((1.0 - breakpoint) * (double)i / 9.0)), coeff);
                }
                _fade_in->fast_simple_add (len, VERY_SMALL_SIGNAL);
                reverse_curve (c3, _fade_in.val());
@@ -1044,6 +1071,9 @@ AudioRegion::set_fade_in (FadeShape shape, framecnt_t len)
                break;
        }
 
+       _fade_in->set_interpolation(Evoral::ControlList::Curved);
+       _inverse_fade_in->set_interpolation(Evoral::ControlList::Curved);
+
        _default_fade_in = false;
        _fade_in->thaw ();
        send_change (PropertyChange (Properties::fade_in));
@@ -1070,6 +1100,8 @@ AudioRegion::set_fade_out (FadeShape shape, framecnt_t len)
        _fade_out->clear ();
        _inverse_fade_out->clear ();
 
+       const int num_steps = 32;
+
        switch (shape) {
        case FadeLinear:
                _fade_out->fast_simple_add (0.0, 1.0);
@@ -1078,13 +1110,13 @@ AudioRegion::set_fade_out (FadeShape shape, framecnt_t len)
                break;
                
        case FadeFast: 
-               generate_db_fade (_fade_out.val(), len, 10, -60);
+               generate_db_fade (_fade_out.val(), len, num_steps, -60);
                generate_inverse_power_curve (_inverse_fade_out.val(), _fade_out.val());
                break;
                
        case FadeSlow: 
-               generate_db_fade (c1, len, 10, -1);  //start off with a slow fade
-               generate_db_fade (c2, len, 10, -80);  //end with a fast fade
+               generate_db_fade (c1, len, num_steps, -1);  //start off with a slow fade
+               generate_db_fade (c2, len, num_steps, -80);  //end with a fast fade
                merge_curves (_fade_out.val(), c1, c2);
                generate_inverse_power_curve (_inverse_fade_out.val(), _fade_out.val());
                break;
@@ -1093,9 +1125,9 @@ AudioRegion::set_fade_out (FadeShape shape, framecnt_t len)
                //constant-power fades use a sin/cos relationship
                //the cutoff is abrupt but it has the benefit of being symmetrical
                _fade_out->fast_simple_add (0.0, 1.0);
-               for (int i = 1; i < 9; i++ ) {
-                       float dist = (float)i/10.0;
-                       _fade_out->fast_simple_add ((len * dist), cos(dist*M_PI/2));
+               for (int i = 1; i < num_steps; ++i) {
+                       const float dist = i / (num_steps + 1.f);
+                       _fade_out->fast_simple_add (len * dist, cos (dist * M_PI / 2.0));
                }
                _fade_out->fast_simple_add (len, VERY_SMALL_SIGNAL);
                reverse_curve (_inverse_fade_out.val(), _fade_out.val());
@@ -1104,23 +1136,21 @@ AudioRegion::set_fade_out (FadeShape shape, framecnt_t len)
        case FadeSymmetric:
                //start with a nearly linear cuve
                _fade_out->fast_simple_add (0, 1);
-               _fade_out->fast_simple_add (0.5*len, 0.6);
-
+               _fade_out->fast_simple_add (0.5 * len, 0.6);
                //now generate a fade-out curve by successively applying a gain drop
-               const float breakpoint = 0.7;  //linear for first 70%
-               const int num_steps = 9;
-               for (int i = 2; i < num_steps; i++) {
-                       float coeff = (1.0-breakpoint);
-                       for (int j = 0; j < i; j++) {
-                               coeff *= 0.5;  //6dB drop per step
-                       }
-                       _fade_out->fast_simple_add (len* (breakpoint+((1.0-breakpoint)*(double)i/(double)num_steps)), coeff);
+               const double breakpoint = 0.7;  //linear for first 70%
+               for (int i = 2; i < 9; ++i) {
+                       const float coeff = (1.f - breakpoint) * powf (0.5, i);
+                       _fade_out->fast_simple_add (len * (breakpoint + ((1.0 - breakpoint) * (double)i / 9.0)), coeff);
                }
                _fade_out->fast_simple_add (len, VERY_SMALL_SIGNAL);
                reverse_curve (_inverse_fade_out.val(), _fade_out.val());
                break;
        }
 
+       _fade_out->set_interpolation(Evoral::ControlList::Curved);
+       _inverse_fade_out->set_interpolation(Evoral::ControlList::Curved);
+
        _default_fade_out = false;
        _fade_out->thaw ();
        send_change (PropertyChange (Properties::fade_out));
@@ -1210,14 +1240,14 @@ void
 AudioRegion::set_default_fade_in ()
 {
        _fade_in_suspended = 0;
-       set_fade_in (FadeLinear, 64);
+       set_fade_in (Config->get_default_fade_shape(), 64);
 }
 
 void
 AudioRegion::set_default_fade_out ()
 {
        _fade_out_suspended = 0;
-       set_fade_out (FadeLinear, 64);
+       set_fade_out (Config->get_default_fade_shape(), 64);
 }
 
 void
@@ -1648,16 +1678,16 @@ AudioRegion::get_transients (AnalysisFeatureList& results, bool force_new)
 
        if (!Config->get_auto_analyse_audio()) {
                if (!analyse_dialog_shown) {
-                       pl->session().Dialog (_("\
+                       pl->session().Dialog (string_compose (_("\
 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 \
 regular basis, you should probably enable \"auto-analyse-audio\" \
-then quit ardour and restart.\n\n\
+then quit %1 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\
-"));
+"), PROGRAM_NAME));
                        analyse_dialog_shown = true;
                }
        }