ardour
audioregion.cc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2000-2006 Paul Davis
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; either version 2 of the License, or
7  (at your option) any later version.
8 
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with this program; if not, write to the Free Software
16  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 
18 */
19 
20 #include <cmath>
21 #include <climits>
22 #include <cfloat>
23 #include <algorithm>
24 
25 #include <set>
26 
27 #include <boost/scoped_array.hpp>
28 
29 #include <glibmm/threads.h>
30 
31 #include "pbd/basename.h"
32 #include "pbd/xml++.h"
33 #include "pbd/stacktrace.h"
34 #include "pbd/enumwriter.h"
35 #include "pbd/convert.h"
36 
37 #include "evoral/Curve.hpp"
38 
39 #include "ardour/audioregion.h"
40 #include "ardour/session.h"
41 #include "ardour/dB.h"
42 #include "ardour/debug.h"
43 #include "ardour/event_type_map.h"
44 #include "ardour/playlist.h"
45 #include "ardour/audiofilesource.h"
46 #include "ardour/region_factory.h"
50 #include "ardour/progress.h"
51 
52 #include "i18n.h"
53 #include <locale.h>
54 
55 using namespace std;
56 using namespace ARDOUR;
57 using namespace PBD;
58 
59 namespace ARDOUR {
60  namespace Properties {
72  }
73 }
74 
75 /* Curve manipulations */
76 
77 static void
79 {
80  size_t len = src->back()->when;
81  for (Evoral::ControlList::const_reverse_iterator it = src->rbegin(); it!=src->rend(); it++) {
82  dst->fast_simple_add (len - (*it)->when, (*it)->value);
83  }
84 }
85 
86 static void
88 {
89  // calc inverse curve using sum of squares
90  for (Evoral::ControlList::const_iterator it = src->begin(); it!=src->end(); ++it ) {
91  float value = (*it)->value;
92  value = 1 - powf(value,2);
93  value = sqrtf(value);
94  dst->fast_simple_add ( (*it)->when, value );
95  }
96 }
97 
98 static void
99 generate_db_fade (boost::shared_ptr<Evoral::ControlList> dst, double len, int num_steps, float dB_drop)
100 {
101  dst->clear ();
102  dst->fast_simple_add (0, 1);
103 
104  //generate a fade-out curve by successively applying a gain drop
105  float fade_speed = dB_to_coefficient(dB_drop / (float) num_steps);
106  for (int i = 1; i < (num_steps-1); i++) {
107  float coeff = GAIN_COEFF_UNITY;
108  for (int j = 0; j < i; j++) {
109  coeff *= fade_speed;
110  }
111  dst->fast_simple_add (len*(double)i/(double)num_steps, coeff);
112  }
113 
114  dst->fast_simple_add (len, GAIN_COEFF_SMALL);
115 }
116 
117 static void
121 {
122  Evoral::ControlList::EventList::size_type size = curve1->size();
123 
124  //curve lengths must match for now
125  if (size != curve2->size()) {
126  return;
127  }
128 
130  int count = 0;
131  for (Evoral::ControlList::const_iterator c2 = curve2->begin(); c2!=curve2->end(); c2++ ) {
132  float v1 = accurate_coefficient_to_dB((*c1)->value);
133  float v2 = accurate_coefficient_to_dB((*c2)->value);
134 
135  double interp = v1 * ( 1.0-( (double)count / (double)size) );
136  interp += v2 * ( (double)count / (double)size );
137 
138  interp = dB_to_coefficient(interp);
139  dst->fast_simple_add ( (*c1)->when, interp );
140  c1++;
141  count++;
142  }
143 }
144 
145 void
147 {
148  Properties::envelope_active.property_id = g_quark_from_static_string (X_("envelope-active"));
149  DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for envelope-active = %1\n", Properties::envelope_active.property_id));
150  Properties::default_fade_in.property_id = g_quark_from_static_string (X_("default-fade-in"));
151  DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for default-fade-in = %1\n", Properties::default_fade_in.property_id));
152  Properties::default_fade_out.property_id = g_quark_from_static_string (X_("default-fade-out"));
153  DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for default-fade-out = %1\n", Properties::default_fade_out.property_id));
154  Properties::fade_in_active.property_id = g_quark_from_static_string (X_("fade-in-active"));
155  DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for fade-in-active = %1\n", Properties::fade_in_active.property_id));
156  Properties::fade_out_active.property_id = g_quark_from_static_string (X_("fade-out-active"));
157  DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for fade-out-active = %1\n", Properties::fade_out_active.property_id));
158  Properties::scale_amplitude.property_id = g_quark_from_static_string (X_("scale-amplitude"));
159  DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for scale-amplitude = %1\n", Properties::scale_amplitude.property_id));
160  Properties::fade_in.property_id = g_quark_from_static_string (X_("FadeIn"));
161  DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for FadeIn = %1\n", Properties::fade_in.property_id));
162  Properties::inverse_fade_in.property_id = g_quark_from_static_string (X_("InverseFadeIn"));
163  DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for InverseFadeIn = %1\n", Properties::inverse_fade_in.property_id));
164  Properties::fade_out.property_id = g_quark_from_static_string (X_("FadeOut"));
165  DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for FadeOut = %1\n", Properties::fade_out.property_id));
166  Properties::inverse_fade_out.property_id = g_quark_from_static_string (X_("InverseFadeOut"));
167  DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for InverseFadeOut = %1\n", Properties::inverse_fade_out.property_id));
168  Properties::envelope.property_id = g_quark_from_static_string (X_("Envelope"));
169  DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for Envelope = %1\n", Properties::envelope.property_id));
170 }
171 
172 void
173 AudioRegion::register_properties ()
174 {
175  /* no need to register parent class properties */
176 
177  add_property (_envelope_active);
178  add_property (_default_fade_in);
179  add_property (_default_fade_out);
180  add_property (_fade_in_active);
181  add_property (_fade_out_active);
182  add_property (_scale_amplitude);
183  add_property (_fade_in);
184  add_property (_inverse_fade_in);
185  add_property (_fade_out);
186  add_property (_inverse_fade_out);
187  add_property (_envelope);
188 }
189 
190 #define AUDIOREGION_STATE_DEFAULT \
191  _envelope_active (Properties::envelope_active, false) \
192  , _default_fade_in (Properties::default_fade_in, true) \
193  , _default_fade_out (Properties::default_fade_out, true) \
194  , _fade_in_active (Properties::fade_in_active, true) \
195  , _fade_out_active (Properties::fade_out_active, true) \
196  , _scale_amplitude (Properties::scale_amplitude, 1.0) \
197  , _fade_in (Properties::fade_in, boost::shared_ptr<AutomationList> (new AutomationList (Evoral::Parameter (FadeInAutomation)))) \
198  , _inverse_fade_in (Properties::inverse_fade_in, boost::shared_ptr<AutomationList> (new AutomationList (Evoral::Parameter (FadeInAutomation)))) \
199  , _fade_out (Properties::fade_out, boost::shared_ptr<AutomationList> (new AutomationList (Evoral::Parameter (FadeOutAutomation)))) \
200  , _inverse_fade_out (Properties::inverse_fade_out, boost::shared_ptr<AutomationList> (new AutomationList (Evoral::Parameter (FadeOutAutomation))))
201 
202 #define AUDIOREGION_COPY_STATE(other) \
203  _envelope_active (Properties::envelope_active, other->_envelope_active) \
204  , _default_fade_in (Properties::default_fade_in, other->_default_fade_in) \
205  , _default_fade_out (Properties::default_fade_out, other->_default_fade_out) \
206  , _fade_in_active (Properties::fade_in_active, other->_fade_in_active) \
207  , _fade_out_active (Properties::fade_out_active, other->_fade_out_active) \
208  , _scale_amplitude (Properties::scale_amplitude, other->_scale_amplitude) \
209  , _fade_in (Properties::fade_in, boost::shared_ptr<AutomationList> (new AutomationList (*other->_fade_in.val()))) \
210  , _inverse_fade_in (Properties::fade_in, boost::shared_ptr<AutomationList> (new AutomationList (*other->_inverse_fade_in.val()))) \
211  , _fade_out (Properties::fade_in, boost::shared_ptr<AutomationList> (new AutomationList (*other->_fade_out.val()))) \
212  , _inverse_fade_out (Properties::fade_in, boost::shared_ptr<AutomationList> (new AutomationList (*other->_inverse_fade_out.val())))
213 /* a Session will reset these to its chosen defaults by calling AudioRegion::set_default_fade() */
214 
215 void
217 {
218  register_properties ();
219 
220  suspend_property_changes();
221  set_default_fades ();
222  set_default_envelope ();
223  resume_property_changes();
224 
225  listen_to_my_curves ();
226  connect_to_analysis_changed ();
227  connect_to_header_position_offset_changed ();
228 }
229 
231 AudioRegion::AudioRegion (Session& s, framepos_t start, framecnt_t len, std::string name)
232  : Region (s, start, len, name, DataType::AUDIO)
234  , _envelope (Properties::envelope, boost::shared_ptr<AutomationList> (new AutomationList (Evoral::Parameter(EnvelopeAutomation))))
235  , _automatable (s)
236  , _fade_in_suspended (0)
237  , _fade_out_suspended (0)
238 {
239  init ();
240  assert (_sources.size() == _master_sources.size());
241 }
242 
245  : Region (srcs)
247  , _envelope (Properties::envelope, boost::shared_ptr<AutomationList> (new AutomationList (Evoral::Parameter(EnvelopeAutomation))))
248  , _automatable(srcs[0]->session())
249  , _fade_in_suspended (0)
250  , _fade_out_suspended (0)
251 {
252  init ();
253  assert (_sources.size() == _master_sources.size());
254 }
255 
257  : Region (other)
258  , AUDIOREGION_COPY_STATE (other)
259  /* As far as I can see, the _envelope's times are relative to region position, and have nothing
260  to do with sources (and hence _start). So when we copy the envelope, we just use the supplied offset.
261  */
262  , _envelope (Properties::envelope, boost::shared_ptr<AutomationList> (new AutomationList (*other->_envelope.val(), 0, other->_length)))
263  , _automatable (other->session())
264  , _fade_in_suspended (0)
265  , _fade_out_suspended (0)
266 {
267  /* don't use init here, because we got fade in/out from the other region
268  */
273 
274  assert(_type == DataType::AUDIO);
275  assert (_sources.size() == _master_sources.size());
276 }
277 
279  : Region (other, offset)
280  , AUDIOREGION_COPY_STATE (other)
281  /* As far as I can see, the _envelope's times are relative to region position, and have nothing
282  to do with sources (and hence _start). So when we copy the envelope, we just use the supplied offset.
283  */
284  , _envelope (Properties::envelope, boost::shared_ptr<AutomationList> (new AutomationList (*other->_envelope.val(), offset, other->_length)))
285  , _automatable (other->session())
286  , _fade_in_suspended (0)
287  , _fade_out_suspended (0)
288 {
289  /* don't use init here, because we got fade in/out from the other region
290  */
295 
296  assert(_type == DataType::AUDIO);
297  assert (_sources.size() == _master_sources.size());
298 }
299 
301  : Region (boost::static_pointer_cast<const Region>(other), srcs)
302  , AUDIOREGION_COPY_STATE (other)
303  , _envelope (Properties::envelope, boost::shared_ptr<AutomationList> (new AutomationList (*other->_envelope.val())))
304  , _automatable (other->session())
305  , _fade_in_suspended (0)
306  , _fade_out_suspended (0)
307 {
308  /* make-a-sort-of-copy-with-different-sources constructor (used by audio filter) */
309 
311 
315 
316  assert (_sources.size() == _master_sources.size());
317 }
318 
320  : Region (srcs)
322  , _envelope (Properties::envelope, boost::shared_ptr<AutomationList> (new AutomationList(Evoral::Parameter(EnvelopeAutomation))))
323  , _automatable(srcs[0]->session())
324  , _fade_in_suspended (0)
325  , _fade_out_suspended (0)
326 {
327  init ();
328 
329  assert(_type == DataType::AUDIO);
330  assert (_sources.size() == _master_sources.size());
331 }
332 
334 {
335 }
336 
337 void
339 {
340  if (!_sync_marked) {
342  }
343 
344  /* return to default fades if the existing ones are too long */
345 
346  if (_left_of_split) {
347  if (_fade_in->back()->when >= _length) {
349  }
351  _left_of_split = false;
352  }
353 
354  if (_right_of_split) {
355  if (_fade_out->back()->when >= _length) {
357  }
358 
360  _right_of_split = false;
361  }
362 
363  /* If _length changed, adjust our gain envelope accordingly */
364  _envelope->truncate_end (_length);
365 }
366 
367 void
369 {
370  for (SourceList::const_iterator i = _sources.begin(); i != _sources.end(); ++i) {
371  (*i)->AnalysisChanged.connect_same_thread (*this, boost::bind (&AudioRegion::invalidate_transients, this));
372  }
373 }
374 
375 void
377 {
378  set<boost::shared_ptr<Source> > unique_srcs;
379 
380  for (SourceList::const_iterator i = _sources.begin(); i != _sources.end(); ++i) {
381 
382  /* connect only once to HeaderPositionOffsetChanged, even if sources are replicated
383  */
384 
385  if (unique_srcs.find (*i) == unique_srcs.end ()) {
386  unique_srcs.insert (*i);
388  if (afs) {
389  afs->HeaderPositionOffsetChanged.connect_same_thread (*this, boost::bind (&AudioRegion::source_offset_changed, this));
390  }
391  }
392  }
393 }
394 
395 void
397 {
398  _envelope->StateChanged.connect_same_thread (*this, boost::bind (&AudioRegion::envelope_changed, this));
399  _fade_in->StateChanged.connect_same_thread (*this, boost::bind (&AudioRegion::fade_in_changed, this));
400  _fade_out->StateChanged.connect_same_thread (*this, boost::bind (&AudioRegion::fade_out_changed, this));
401 }
402 
403 void
405 {
406  if (envelope_active() != yn) {
407  _envelope_active = yn;
409  }
410 }
411 
421 AudioRegion::read_peaks (PeakData *buf, framecnt_t npeaks, framecnt_t offset, framecnt_t cnt, uint32_t chan_n, double frames_per_pixel) const
422 {
423  if (chan_n >= _sources.size()) {
424  return 0;
425  }
426 
427  if (audio_source(chan_n)->read_peaks (buf, npeaks, offset, cnt, frames_per_pixel)) {
428  return 0;
429  } else {
430  if (_scale_amplitude != 1.0f) {
431  for (framecnt_t n = 0; n < npeaks; ++n) {
432  buf[n].max *= _scale_amplitude;
433  buf[n].min *= _scale_amplitude;
434  }
435  }
436  return cnt;
437  }
438 }
439 
446 AudioRegion::read (Sample* buf, framepos_t pos, framecnt_t cnt, int channel) const
447 {
448  /* raw read, no fades, no gain, nada */
449  return read_from_sources (_sources, _length, buf, _position + pos, cnt, channel);
450 }
451 
453 AudioRegion::master_read_at (Sample *buf, Sample* /*mixdown_buffer*/, float* /*gain_buffer*/,
454  framepos_t position, framecnt_t cnt, uint32_t chan_n) const
455 {
456  /* do not read gain/scaling/fades and do not count this disk i/o in statistics */
457 
458  assert (cnt >= 0);
459  return read_from_sources (
460  _master_sources, _master_sources.front()->length (_master_sources.front()->timeline_position()),
461  buf, position, cnt, chan_n
462  );
463 }
464 
473 AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer,
475  framecnt_t cnt,
476  uint32_t chan_n) const
477 {
478  /* We are reading data from this region into buf (possibly via mixdown_buffer).
479  The caller has verified that we cover the desired section.
480  */
481 
482  /* See doc/region_read.svg for a drawing which might help to explain
483  what is going on.
484  */
485 
486  assert (cnt >= 0);
487 
488  if (n_channels() == 0) {
489  return 0;
490  }
491 
492  /* WORK OUT WHERE TO GET DATA FROM */
493 
494  framecnt_t to_read;
495 
496  assert (position >= _position);
497  frameoffset_t const internal_offset = position - _position;
498 
499  if (internal_offset >= _length) {
500  return 0; /* read nothing */
501  }
502 
503  if ((to_read = min (cnt, _length - internal_offset)) == 0) {
504  return 0; /* read nothing */
505  }
506 
507 
508  /* COMPUTE DETAILS OF ANY FADES INVOLVED IN THIS READ */
509 
510  /* Amount (length) of fade in that we are dealing with in this read */
511  framecnt_t fade_in_limit = 0;
512 
513  /* Offset from buf / mixdown_buffer of the start
514  of any fade out that we are dealing with
515  */
516  frameoffset_t fade_out_offset = 0;
517 
518  /* Amount (length) of fade out that we are dealing with in this read */
519  framecnt_t fade_out_limit = 0;
520 
521  framecnt_t fade_interval_start = 0;
522 
523  /* Fade in */
524 
525  if (_fade_in_active && _session.config.get_use_region_fades()) {
526 
527  framecnt_t fade_in_length = (framecnt_t) _fade_in->back()->when;
528 
529  /* see if this read is within the fade in */
530 
531  if (internal_offset < fade_in_length) {
532  fade_in_limit = min (to_read, fade_in_length - internal_offset);
533  }
534  }
535 
536  /* Fade out */
537 
538  if (_fade_out_active && _session.config.get_use_region_fades()) {
539 
540  /* see if some part of this read is within the fade out */
541 
542  /* ................. >| REGION
543  * _length
544  *
545  * { } FADE
546  * fade_out_length
547  * ^
548  * _length - fade_out_length
549  *
550  * |--------------|
551  * ^internal_offset
552  * ^internal_offset + to_read
553  *
554  * we need the intersection of [internal_offset,internal_offset+to_read] with
555  * [_length - fade_out_length, _length]
556  *
557  */
558 
559  fade_interval_start = max (internal_offset, _length - framecnt_t (_fade_out->back()->when));
560  framecnt_t fade_interval_end = min(internal_offset + to_read, _length.val());
561 
562  if (fade_interval_end > fade_interval_start) {
563  /* (part of the) the fade out is in this buffer */
564  fade_out_limit = fade_interval_end - fade_interval_start;
565  fade_out_offset = fade_interval_start - internal_offset;
566  }
567  }
568 
569  /* READ DATA FROM THE SOURCE INTO mixdown_buffer.
570  We can never read directly into buf, since it may contain data
571  from a region `below' this one in the stack, and our fades (if they exist)
572  may need to mix with the existing data.
573  */
574 
575  if (read_from_sources (_sources, _length, mixdown_buffer, position, to_read, chan_n) != to_read) {
576  return 0;
577  }
578 
579  /* APPLY REGULAR GAIN CURVES AND SCALING TO mixdown_buffer */
580 
581  if (envelope_active()) {
582  _envelope->curve().get_vector (internal_offset, internal_offset + to_read, gain_buffer, to_read);
583 
584  if (_scale_amplitude != 1.0f) {
585  for (framecnt_t n = 0; n < to_read; ++n) {
586  mixdown_buffer[n] *= gain_buffer[n] * _scale_amplitude;
587  }
588  } else {
589  for (framecnt_t n = 0; n < to_read; ++n) {
590  mixdown_buffer[n] *= gain_buffer[n];
591  }
592  }
593  } else if (_scale_amplitude != 1.0f) {
594  apply_gain_to_buffer (mixdown_buffer, to_read, _scale_amplitude);
595  }
596 
597  /* APPLY FADES TO THE DATA IN mixdown_buffer AND MIX THE RESULTS INTO
598  * buf. The key things to realize here: (1) the fade being applied is
599  * (as of April 26th 2012) just the inverse of the fade in curve (2)
600  * "buf" contains data from lower regions already. So this operation
601  * fades out the existing material.
602  */
603 
604  if (fade_in_limit != 0) {
605 
606  if (opaque()) {
607  if (_inverse_fade_in) {
608 
609  /* explicit inverse fade in curve (e.g. for constant
610  * power), so we have to fetch it.
611  */
612 
613  _inverse_fade_in->curve().get_vector (internal_offset, internal_offset + fade_in_limit, gain_buffer, fade_in_limit);
614 
615  /* Fade the data from lower layers out */
616  for (framecnt_t n = 0; n < fade_in_limit; ++n) {
617  buf[n] *= gain_buffer[n];
618  }
619 
620  /* refill gain buffer with the fade in */
621 
622  _fade_in->curve().get_vector (internal_offset, internal_offset + fade_in_limit, gain_buffer, fade_in_limit);
623 
624  } else {
625 
626  /* no explicit inverse fade in, so just use (1 - fade
627  * in) for the fade out of lower layers
628  */
629 
630  _fade_in->curve().get_vector (internal_offset, internal_offset + fade_in_limit, gain_buffer, fade_in_limit);
631 
632  for (framecnt_t n = 0; n < fade_in_limit; ++n) {
633  buf[n] *= 1 - gain_buffer[n];
634  }
635  }
636  } else {
637  _fade_in->curve().get_vector (internal_offset, internal_offset + fade_in_limit, gain_buffer, fade_in_limit);
638  }
639 
640  /* Mix our newly-read data in, with the fade */
641  for (framecnt_t n = 0; n < fade_in_limit; ++n) {
642  buf[n] += mixdown_buffer[n] * gain_buffer[n];
643  }
644  }
645 
646  if (fade_out_limit != 0) {
647 
648  framecnt_t const curve_offset = fade_interval_start - (_length - _fade_out->back()->when);
649 
650  if (opaque()) {
651  if (_inverse_fade_out) {
652 
653  _inverse_fade_out->curve().get_vector (curve_offset, curve_offset + fade_out_limit, gain_buffer, fade_out_limit);
654 
655  /* Fade the data from lower levels in */
656  for (framecnt_t n = 0, m = fade_out_offset; n < fade_out_limit; ++n, ++m) {
657  buf[m] *= gain_buffer[n];
658  }
659 
660  /* fetch the actual fade out */
661 
662  _fade_out->curve().get_vector (curve_offset, curve_offset + fade_out_limit, gain_buffer, fade_out_limit);
663 
664  } else {
665 
666  /* no explicit inverse fade out (which is
667  * actually a fade in), so just use (1 - fade
668  * out) for the fade in of lower layers
669  */
670 
671  _fade_out->curve().get_vector (curve_offset, curve_offset + fade_out_limit, gain_buffer, fade_out_limit);
672 
673  for (framecnt_t n = 0, m = fade_out_offset; n < fade_out_limit; ++n, ++m) {
674  buf[m] *= 1 - gain_buffer[n];
675  }
676  }
677  } else {
678  _fade_out->curve().get_vector (curve_offset, curve_offset + fade_out_limit, gain_buffer, fade_out_limit);
679  }
680 
681  /* Mix our newly-read data with whatever was already there,
682  with the fade out applied to our data.
683  */
684  for (framecnt_t n = 0, m = fade_out_offset; n < fade_out_limit; ++n, ++m) {
685  buf[m] += mixdown_buffer[m] * gain_buffer[n];
686  }
687  }
688 
689  /* MIX OR COPY THE REGION BODY FROM mixdown_buffer INTO buf */
690 
691  framecnt_t const N = to_read - fade_in_limit - fade_out_limit;
692  if (N > 0) {
693  if (opaque ()) {
694  DEBUG_TRACE (DEBUG::AudioPlayback, string_compose ("Region %1 memcpy into buf @ %2 + %3, from mixdown buffer @ %4 + %5, len = %6 cnt was %7\n",
695  name(), buf, fade_in_limit, mixdown_buffer, fade_in_limit, N, cnt));
696  memcpy (buf + fade_in_limit, mixdown_buffer + fade_in_limit, N * sizeof (Sample));
697  } else {
698  mix_buffers_no_gain (buf + fade_in_limit, mixdown_buffer + fade_in_limit, N);
699  }
700  }
701 
702  return to_read;
703 }
704 
718 AudioRegion::read_from_sources (SourceList const & srcs, framecnt_t limit, Sample* buf, framepos_t position, framecnt_t cnt, uint32_t chan_n) const
719 {
720  frameoffset_t const internal_offset = position - _position;
721  if (internal_offset >= limit) {
722  return 0;
723  }
724 
725  framecnt_t const to_read = min (cnt, limit - internal_offset);
726  if (to_read == 0) {
727  return 0;
728  }
729 
730  if (chan_n < n_channels()) {
731 
733  if (src->read (buf, _start + internal_offset, to_read) != to_read) {
734  return 0; /* "read nothing" */
735  }
736 
737  } else {
738 
739  /* track is N-channel, this region has fewer channels; silence the ones
740  we don't have.
741  */
742 
743  if (Config->get_replicate_missing_region_channels()) {
744 
745  /* copy an existing channel's data in for this non-existant one */
746 
747  uint32_t channel = chan_n % n_channels();
749 
750  if (src->read (buf, _start + internal_offset, to_read) != to_read) {
751  return 0; /* "read nothing" */
752  }
753 
754  } else {
755 
756  /* use silence */
757  memset (buf, 0, sizeof (Sample) * to_read);
758  }
759  }
760 
761  return to_read;
762 }
763 
764 XMLNode&
766 {
767  XMLNode& node (Region::state ());
768  char buf[64];
769  LocaleGuard lg (X_("C"));
770 
771  snprintf (buf, sizeof (buf), "%u", (uint32_t) _sources.size());
772  node.add_property ("channels", buf);
773 
774  return node;
775 }
776 
777 XMLNode&
779 {
780  XMLNode& node (get_basic_state());
781  XMLNode *child;
782  LocaleGuard lg (X_("C"));
783 
784  child = node.add_child ("Envelope");
785 
786  bool default_env = false;
787 
788  // If there are only two points, the points are in the start of the region and the end of the region
789  // so, if they are both at 1.0f, that means the default region.
790 
791  if (_envelope->size() == 2 &&
792  _envelope->front()->value == GAIN_COEFF_UNITY &&
793  _envelope->back()->value==GAIN_COEFF_UNITY) {
794  if (_envelope->front()->when == 0 && _envelope->back()->when == _length) {
795  default_env = true;
796  }
797  }
798 
799  if (default_env) {
800  child->add_property ("default", "yes");
801  } else {
802  child->add_child_nocopy (_envelope->get_state ());
803  }
804 
805  child = node.add_child (X_("FadeIn"));
806 
807  if (_default_fade_in) {
808  child->add_property ("default", "yes");
809  } else {
810  child->add_child_nocopy (_fade_in->get_state ());
811  }
812 
813  if (_inverse_fade_in) {
814  child = node.add_child (X_("InverseFadeIn"));
815  child->add_child_nocopy (_inverse_fade_in->get_state ());
816  }
817 
818  child = node.add_child (X_("FadeOut"));
819 
820  if (_default_fade_out) {
821  child->add_property ("default", "yes");
822  } else {
823  child->add_child_nocopy (_fade_out->get_state ());
824  }
825 
826  if (_inverse_fade_out) {
827  child = node.add_child (X_("InverseFadeOut"));
828  child->add_child_nocopy (_inverse_fade_out->get_state ());
829  }
830 
831  return node;
832 }
833 
834 int
835 AudioRegion::_set_state (const XMLNode& node, int version, PropertyChange& what_changed, bool send)
836 {
837  const XMLNodeList& nlist = node.children();
838  const XMLProperty *prop;
839  LocaleGuard lg (X_("C"));
840  boost::shared_ptr<Playlist> the_playlist (_playlist.lock());
841 
843 
844  if (the_playlist) {
845  the_playlist->freeze ();
846  }
847 
848 
849  /* this will set all our State members and stuff controlled by the Region.
850  It should NOT send any changed signals - that is our responsibility.
851  */
852 
853  Region::_set_state (node, version, what_changed, false);
854 
855  if ((prop = node.property ("scale-gain")) != 0) {
856  float a = atof (prop->value().c_str());
857  if (a != _scale_amplitude) {
858  _scale_amplitude = a;
859  what_changed.add (Properties::scale_amplitude);
860  }
861  }
862 
863  /* Now find envelope description and other related child items */
864 
865  _envelope->freeze ();
866 
867  for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
868  XMLNode *child;
869  XMLProperty *prop;
870 
871  child = (*niter);
872 
873  if (child->name() == "Envelope") {
874 
875  _envelope->clear ();
876 
877  if ((prop = child->property ("default")) != 0 || _envelope->set_state (*child, version)) {
879  }
880 
881  _envelope->truncate_end (_length);
882 
883 
884  } else if (child->name() == "FadeIn") {
885 
886  _fade_in->clear ();
887 
888  if (((prop = child->property ("default")) != 0 && string_is_affirmative (prop->value())) || (prop = child->property ("steepness")) != 0) {
890  } else {
891  XMLNode* grandchild = child->child ("AutomationList");
892  if (grandchild) {
893  _fade_in->set_state (*grandchild, version);
894  }
895  }
896 
897  if ((prop = child->property ("active")) != 0) {
898  if (string_is_affirmative (prop->value())) {
899  set_fade_in_active (true);
900  } else {
901  set_fade_in_active (false);
902  }
903  }
904 
905  } else if (child->name() == "FadeOut") {
906 
907  _fade_out->clear ();
908 
909  if (((prop = child->property ("default")) != 0 && (string_is_affirmative (prop->value()))) || (prop = child->property ("steepness")) != 0) {
911  } else {
912  XMLNode* grandchild = child->child ("AutomationList");
913  if (grandchild) {
914  _fade_out->set_state (*grandchild, version);
915  }
916  }
917 
918  if ((prop = child->property ("active")) != 0) {
919  if (string_is_affirmative (prop->value())) {
920  set_fade_out_active (true);
921  } else {
922  set_fade_out_active (false);
923  }
924  }
925 
926  } else if ( (child->name() == "InverseFadeIn") || (child->name() == "InvFadeIn") ) {
927  XMLNode* grandchild = child->child ("AutomationList");
928  if (grandchild) {
929  _inverse_fade_in->set_state (*grandchild, version);
930  }
931  } else if ( (child->name() == "InverseFadeOut") || (child->name() == "InvFadeOut") ) {
932  XMLNode* grandchild = child->child ("AutomationList");
933  if (grandchild) {
934  _inverse_fade_out->set_state (*grandchild, version);
935  }
936  }
937  }
938 
939  _envelope->thaw ();
941 
942  if (send) {
943  send_change (what_changed);
944  }
945 
946  if (the_playlist) {
947  the_playlist->thaw ();
948  }
949 
950  return 0;
951 }
952 
953 int
954 AudioRegion::set_state (const XMLNode& node, int version)
955 {
956  PropertyChange what_changed;
957  return _set_state (node, version, what_changed, true);
958 }
959 
960 void
962 {
963  framepos_t s, e;
964 
965  switch (coverage (start, end)) {
967  s = _position;
968  e = end;
970  break;
971  case Evoral::OverlapEnd:
972  s = start;
973  e = _position + _length;
975  break;
977  /* needs addressing, perhaps. Difficult to do if we can't
978  * control one edge of the fade relative to the relevant edge
979  * of the region, which we cannot - fades are currently assumed
980  * to start/end at the start/end of the region
981  */
982  break;
983  default:
984  return;
985  }
986 }
987 
988 void
990 {
991  set_fade_in (shape, (framecnt_t) _fade_in->back()->when);
992 }
993 
994 void
996 {
997  set_fade_out (shape, (framecnt_t) _fade_out->back()->when);
998 }
999 
1000 void
1002 {
1003  _fade_in->freeze ();
1004  *(_fade_in.val()) = *f;
1005  _fade_in->thaw ();
1006  _default_fade_in = false;
1007 
1009 }
1010 
1011 void
1013 {
1018 
1019  _fade_in->freeze ();
1020  _fade_in->clear ();
1021  _inverse_fade_in->clear ();
1022 
1023  const int num_steps = 32;
1024 
1025  switch (shape) {
1026  case FadeLinear:
1027  _fade_in->fast_simple_add (0.0, GAIN_COEFF_SMALL);
1028  _fade_in->fast_simple_add (len, GAIN_COEFF_UNITY);
1030  break;
1031 
1032  case FadeFast:
1033  generate_db_fade (_fade_in.val(), len, num_steps, -60);
1034  reverse_curve (c1, _fade_in.val());
1035  _fade_in->copy_events (*c1);
1037  break;
1038 
1039  case FadeSlow:
1040  generate_db_fade (c1, len, num_steps, -1); // start off with a slow fade
1041  generate_db_fade (c2, len, num_steps, -80); // end with a fast fade
1042  merge_curves (_fade_in.val(), c1, c2);
1043  reverse_curve (c3, _fade_in.val());
1044  _fade_in->copy_events (*c3);
1046  break;
1047 
1048  case FadeConstantPower:
1049  _fade_in->fast_simple_add (0.0, GAIN_COEFF_SMALL);
1050  for (int i = 1; i < num_steps; ++i) {
1051  const float dist = i / (num_steps + 1.f);
1052  _fade_in->fast_simple_add (len * dist, sin (dist * M_PI / 2.0));
1053  }
1054  _fade_in->fast_simple_add (len, GAIN_COEFF_UNITY);
1056  break;
1057 
1058  case FadeSymmetric:
1059  //start with a nearly linear cuve
1060  _fade_in->fast_simple_add (0, 1);
1061  _fade_in->fast_simple_add (0.5 * len, 0.6);
1062  //now generate a fade-out curve by successively applying a gain drop
1063  const double breakpoint = 0.7; //linear for first 70%
1064  for (int i = 2; i < 9; ++i) {
1065  const float coeff = (1.f - breakpoint) * powf (0.5, i);
1066  _fade_in->fast_simple_add (len * (breakpoint + ((GAIN_COEFF_UNITY - breakpoint) * (double)i / 9.0)), coeff);
1067  }
1068  _fade_in->fast_simple_add (len, GAIN_COEFF_SMALL);
1069  reverse_curve (c3, _fade_in.val());
1070  _fade_in->copy_events (*c3);
1072  break;
1073  }
1074 
1075  _fade_in->set_interpolation(Evoral::ControlList::Curved);
1076  _inverse_fade_in->set_interpolation(Evoral::ControlList::Curved);
1077 
1078  _default_fade_in = false;
1079  _fade_in->thaw ();
1081 }
1082 
1083 void
1085 {
1086  _fade_out->freeze ();
1087  *(_fade_out.val()) = *f;
1088  _fade_out->thaw ();
1089  _default_fade_out = false;
1090 
1092 }
1093 
1094 void
1096 {
1100 
1101  _fade_out->freeze ();
1102  _fade_out->clear ();
1103  _inverse_fade_out->clear ();
1104 
1105  const int num_steps = 32;
1106 
1107  switch (shape) {
1108  case FadeLinear:
1109  _fade_out->fast_simple_add (0.0, GAIN_COEFF_UNITY);
1110  _fade_out->fast_simple_add (len, GAIN_COEFF_SMALL);
1112  break;
1113 
1114  case FadeFast:
1115  generate_db_fade (_fade_out.val(), len, num_steps, -60);
1117  break;
1118 
1119  case FadeSlow:
1120  generate_db_fade (c1, len, num_steps, -1); //start off with a slow fade
1121  generate_db_fade (c2, len, num_steps, -80); //end with a fast fade
1122  merge_curves (_fade_out.val(), c1, c2);
1124  break;
1125 
1126  case FadeConstantPower:
1127  //constant-power fades use a sin/cos relationship
1128  //the cutoff is abrupt but it has the benefit of being symmetrical
1129  _fade_out->fast_simple_add (0.0, GAIN_COEFF_UNITY);
1130  for (int i = 1; i < num_steps; ++i) {
1131  const float dist = i / (num_steps + 1.f);
1132  _fade_out->fast_simple_add (len * dist, cos (dist * M_PI / 2.0));
1133  }
1134  _fade_out->fast_simple_add (len, GAIN_COEFF_SMALL);
1136  break;
1137 
1138  case FadeSymmetric:
1139  //start with a nearly linear cuve
1140  _fade_out->fast_simple_add (0, 1);
1141  _fade_out->fast_simple_add (0.5 * len, 0.6);
1142  //now generate a fade-out curve by successively applying a gain drop
1143  const double breakpoint = 0.7; //linear for first 70%
1144  for (int i = 2; i < 9; ++i) {
1145  const float coeff = (1.f - breakpoint) * powf (0.5, i);
1146  _fade_out->fast_simple_add (len * (breakpoint + ((GAIN_COEFF_UNITY - breakpoint) * (double)i / 9.0)), coeff);
1147  }
1148  _fade_out->fast_simple_add (len, GAIN_COEFF_SMALL);
1150  break;
1151  }
1152 
1153  _fade_out->set_interpolation(Evoral::ControlList::Curved);
1154  _inverse_fade_out->set_interpolation(Evoral::ControlList::Curved);
1155 
1156  _default_fade_out = false;
1157  _fade_out->thaw ();
1159 }
1160 
1161 void
1163 {
1164  if (len > _length) {
1165  len = _length - 1;
1166  }
1167 
1168  if (len < 64) {
1169  len = 64;
1170  }
1171 
1172  bool changed = _fade_in->extend_to (len);
1173 
1174  if (changed) {
1175  if (_inverse_fade_in) {
1176  _inverse_fade_in->extend_to (len);
1177  }
1178 
1179  _default_fade_in = false;
1181  }
1182 }
1183 
1184 void
1186 {
1187  if (len > _length) {
1188  len = _length - 1;
1189  }
1190 
1191  if (len < 64) {
1192  len = 64;
1193  }
1194 
1195  bool changed = _fade_out->extend_to (len);
1196 
1197  if (changed) {
1198 
1199  if (_inverse_fade_out) {
1200  _inverse_fade_out->extend_to (len);
1201  }
1202  _default_fade_out = false;
1203 
1205  }
1206 }
1207 
1208 void
1210 {
1211  if (yn == _fade_in_active) {
1212  return;
1213  }
1214 
1215  _fade_in_active = yn;
1217 }
1218 
1219 void
1221 {
1222  if (yn == _fade_out_active) {
1223  return;
1224  }
1225  _fade_out_active = yn;
1227 }
1228 
1229 bool
1231 {
1232  return _fade_in->size() == 2 && _fade_in->front()->when == 0 && _fade_in->back()->when == 64;
1233 }
1234 
1235 bool
1237 {
1238  return _fade_out->size() == 2 && _fade_out->front()->when == 0 && _fade_out->back()->when == 64;
1239 }
1240 
1241 void
1243 {
1244  _fade_in_suspended = 0;
1245  set_fade_in (Config->get_default_fade_shape(), 64);
1246 }
1247 
1248 void
1250 {
1251  _fade_out_suspended = 0;
1252  set_fade_out (Config->get_default_fade_shape(), 64);
1253 }
1254 
1255 void
1257 {
1260 }
1261 
1262 void
1264 {
1265  _envelope->freeze ();
1266  _envelope->clear ();
1267  _envelope->fast_simple_add (0, GAIN_COEFF_UNITY);
1268  _envelope->fast_simple_add (_length, GAIN_COEFF_UNITY);
1269  _envelope->thaw ();
1270 }
1271 
1272 void
1274 {
1275  /* our length has changed. recompute a new final point by interpolating
1276  based on the the existing curve.
1277  */
1278 
1279  _envelope->freeze ();
1280  _envelope->truncate_end (_length);
1281  _envelope->thaw ();
1282 
1284 
1285  if (_left_of_split) {
1287  _left_of_split = false;
1288  } else if (_fade_out->back()->when > _length) {
1289  _fade_out->extend_to (_length);
1291  }
1292 
1293  if (_fade_in->back()->when > _length) {
1294  _fade_in->extend_to (_length);
1296  }
1297 
1299 }
1300 
1301 void
1303 {
1304  /* as above, but the shift was from the front */
1305 
1306  _envelope->truncate_start (_length);
1307 
1309 
1310  if (_right_of_split) {
1312  _right_of_split = false;
1313  } else if (_fade_in->back()->when > _length) {
1314  _fade_in->extend_to (_length);
1316  }
1317 
1318  if (_fade_out->back()->when > _length) {
1319  _fade_out->extend_to (_length);
1321  }
1322 
1324 }
1325 
1326 int
1328 {
1329  SourceList srcs;
1330  string new_name;
1331  int n = 0;
1332 
1333  if (_sources.size() < 2) {
1334  return 0;
1335  }
1336 
1337  for (SourceList::const_iterator i = _sources.begin(); i != _sources.end(); ++i) {
1338  srcs.clear ();
1339  srcs.push_back (*i);
1340 
1341  new_name = _name;
1342 
1343  if (_sources.size() == 2) {
1344  if (n == 0) {
1345  new_name += "-L";
1346  } else {
1347  new_name += "-R";
1348  }
1349  } else {
1350  new_name += '-';
1351  new_name += ('0' + n + 1);
1352  }
1353 
1354  /* create a copy with just one source. prevent if from being thought of as
1355  "whole file" even if it covers the entire source file(s).
1356  */
1357 
1358  PropertyList plist;
1359 
1360  plist.add (Properties::start, _start.val());
1361  plist.add (Properties::length, _length.val());
1362  plist.add (Properties::name, new_name);
1363  plist.add (Properties::layer, layer ());
1364 
1365  v.push_back(RegionFactory::create (srcs, plist));
1366  v.back()->set_whole_file (false);
1367 
1368  ++n;
1369  }
1370 
1371  return 0;
1372 }
1373 
1374 framecnt_t
1375 AudioRegion::read_raw_internal (Sample* buf, framepos_t pos, framecnt_t cnt, int channel) const
1376 {
1377  return audio_source(channel)->read (buf, pos, cnt);
1378 }
1379 
1380 void
1382 {
1384 
1385  _scale_amplitude = g;
1386 
1387  /* tell the diskstream we're in */
1388 
1389  if (pl) {
1390  pl->ContentsChanged();
1391  }
1392 
1393  /* tell everybody else */
1394 
1396 }
1397 
1401 double
1403 {
1404  framepos_t fpos = _start;
1405  framepos_t const fend = _start + _length;
1406  double maxamp = 0;
1407 
1408  framecnt_t const blocksize = 64 * 1024;
1409  Sample buf[blocksize];
1410 
1411  while (fpos < fend) {
1412 
1413  uint32_t n;
1414 
1415  framecnt_t const to_read = min (fend - fpos, blocksize);
1416 
1417  for (n = 0; n < n_channels(); ++n) {
1418 
1419  /* read it in */
1420 
1421  if (read_raw_internal (buf, fpos, to_read, n) != to_read) {
1422  return 0;
1423  }
1424 
1425  maxamp = compute_peak (buf, to_read, maxamp);
1426  }
1427 
1428  fpos += to_read;
1429  if (p) {
1430  p->set_progress (float (fpos - _start) / _length);
1431  if (p->cancelled ()) {
1432  return -1;
1433  }
1434  }
1435  }
1436 
1437  return maxamp;
1438 }
1439 
1443 void
1444 AudioRegion::normalize (float max_amplitude, float target_dB)
1445 {
1446  gain_t target = dB_to_coefficient (target_dB);
1447 
1448  if (target == GAIN_COEFF_UNITY) {
1449  /* do not normalize to precisely 1.0 (0 dBFS), to avoid making it appear
1450  that we may have clipped.
1451  */
1452  target -= FLT_EPSILON;
1453  }
1454 
1455  if (max_amplitude < GAIN_COEFF_SMALL) {
1456  /* don't even try */
1457  return;
1458  }
1459 
1460  if (max_amplitude == target) {
1461  /* we can't do anything useful */
1462  return;
1463  }
1464 
1465  set_scale_amplitude (target / max_amplitude);
1466 }
1467 
1468 void
1470 {
1472 }
1473 
1474 void
1476 {
1478 }
1479 
1480 void
1482 {
1484 }
1485 
1486 void
1488 {
1489  if (++_fade_in_suspended == 1) {
1490  if (fade_in_is_default()) {
1491  set_fade_in_active (false);
1492  }
1493  }
1494 }
1495 
1496 void
1498 {
1499  if (--_fade_in_suspended == 0 && _fade_in_suspended) {
1500  set_fade_in_active (true);
1501  }
1502 }
1503 
1504 void
1506 {
1507  if (++_fade_out_suspended == 1) {
1508  if (fade_out_is_default()) {
1509  set_fade_out_active (false);
1510  }
1511  }
1512 }
1513 
1514 void
1516 {
1518  set_fade_out_active (true);
1519  }
1520 }
1521 
1522 bool
1524 {
1525  if (_sources.empty()) {
1526  /* impossible, but ... */
1527  return false;
1528  }
1529 
1530  float fsr = audio_source()->sample_rate();
1531 
1532  return fsr != sr;
1533 }
1534 
1535 void
1537 {
1538  /* XXX this fixes a crash that should not occur. It does occur
1539  becauses regions are not being deleted when a session
1540  is unloaded. That bug must be fixed.
1541  */
1542 
1543  if (_sources.empty()) {
1544  return;
1545  }
1546 
1548 
1549  if (afs && afs->destructive()) {
1550  // set_start (source()->natural_position(), this);
1551  set_position (source()->natural_position());
1552  }
1553 }
1554 
1556 AudioRegion::audio_source (uint32_t n) const
1557 {
1558  // Guaranteed to succeed (use a static cast for speed?)
1560 }
1561 
1562 int
1564 {
1565  for (AnalysisFeatureList::iterator x = _transients.begin(); x != _transients.end(); ++x) {
1566  (*x) = (*x) + delta;
1567  }
1568 
1570 
1571  return 0;
1572 }
1573 
1574 int
1576 {
1577  for (AnalysisFeatureList::iterator x = _transients.begin(); x != _transients.end(); ++x) {
1578  if ((*x) == old_position) {
1579  (*x) = new_position;
1581 
1582  break;
1583  }
1584  }
1585 
1586  return 0;
1587 }
1588 
1589 void
1591 {
1592  _transients.push_back(where);
1593  _valid_transients = true;
1594 
1596 }
1597 
1598 void
1600 {
1601  _transients.remove(where);
1602  _valid_transients = true;
1603 
1605 }
1606 
1607 int
1609 {
1610  _transients.clear();
1611  _transients = results;
1612  _valid_transients = true;
1613 
1615 
1616  return 0;
1617 }
1618 
1619 int
1621 {
1623 
1624  if (!pl) {
1625  return -1;
1626  }
1627 
1628  if (_valid_transients && !force_new) {
1629  results = _transients;
1630  return 0;
1631  }
1632 
1633  SourceList::iterator s;
1634 
1635  for (s = _sources.begin() ; s != _sources.end(); ++s) {
1636  if (!(*s)->has_been_analysed()) {
1637  cerr << "For " << name() << " source " << (*s)->name() << " has not been analyzed\n";
1638  break;
1639  }
1640  }
1641 
1642  if (s == _sources.end()) {
1643  /* all sources are analyzed, merge data from each one */
1644 
1645  for (s = _sources.begin() ; s != _sources.end(); ++s) {
1646 
1647  /* find the set of transients within the bounds of this region */
1648 
1649  AnalysisFeatureList::iterator low = lower_bound ((*s)->transients.begin(),
1650  (*s)->transients.end(),
1651  _start);
1652 
1653  AnalysisFeatureList::iterator high = upper_bound ((*s)->transients.begin(),
1654  (*s)->transients.end(),
1655  _start + _length);
1656 
1657  /* and add them */
1658 
1659  results.insert (results.end(), low, high);
1660  }
1661 
1663 
1664  /* translate all transients to current position */
1665 
1666  for (AnalysisFeatureList::iterator x = results.begin(); x != results.end(); ++x) {
1667  (*x) -= _start;
1668  (*x) += _position;
1669  }
1670 
1671  _transients = results;
1672  _valid_transients = true;
1673 
1674  return 0;
1675  }
1676 
1677  /* no existing/complete transient info */
1678 
1679  static bool analyse_dialog_shown = false; /* global per instance of Ardour */
1680 
1681  if (!Config->get_auto_analyse_audio()) {
1682  if (!analyse_dialog_shown) {
1683  pl->session().Dialog (string_compose (_("\
1684 You have requested an operation that requires audio analysis.\n\n\
1685 You currently have \"auto-analyse-audio\" disabled, which means \
1686 that transient data must be generated every time it is required.\n\n\
1687 If you are doing work that will require transient data on a \
1688 regular basis, you should probably enable \"auto-analyse-audio\" \
1689 then quit %1 and restart.\n\n\
1690 This dialog will not display again. But you may notice a slight delay \
1691 in this and future transient-detection operations.\n\
1692 "), PROGRAM_NAME));
1693  analyse_dialog_shown = true;
1694  }
1695  }
1696 
1697  bool existing_results = !results.empty();
1698 
1699  try {
1700 
1701  TransientDetector t (pl->session().frame_rate());
1702 
1703  _transients.clear ();
1704  _valid_transients = false;
1705 
1706  for (uint32_t i = 0; i < n_channels(); ++i) {
1707 
1708  AnalysisFeatureList these_results;
1709 
1710  t.reset ();
1711 
1712  if (t.run ("", this, i, these_results)) {
1713  return -1;
1714  }
1715 
1716  /* translate all transients to give absolute position */
1717 
1718  for (AnalysisFeatureList::iterator i = these_results.begin(); i != these_results.end(); ++i) {
1719  (*i) += _position;
1720  }
1721 
1722  /* merge */
1723 
1724  _transients.insert (_transients.end(), these_results.begin(), these_results.end());
1725  }
1726  } catch (...) {
1727  error << string_compose(_("Transient Analysis failed for %1."), _("Audio Region")) << endmsg;
1728  return -1;
1729  }
1730 
1731  if (!results.empty()) {
1732  if (existing_results) {
1733 
1734  /* merge our transients into the existing ones, then clean up
1735  those.
1736  */
1737 
1738  results.insert (results.end(), _transients.begin(), _transients.end());
1740  }
1741 
1742  /* make sure ours are clean too */
1743 
1745 
1746  } else {
1747 
1749  results = _transients;
1750  }
1751 
1752  _valid_transients = true;
1753 
1754  return 0;
1755 }
1756 
1765 AudioRegion::find_silence (Sample threshold, framecnt_t min_length, InterThreadInfo& itt) const
1766 {
1767  framecnt_t const block_size = 64 * 1024;
1768  boost::scoped_array<Sample> loudest (new Sample[block_size]);
1769  boost::scoped_array<Sample> buf (new Sample[block_size]);
1770 
1771  framepos_t pos = _start;
1772  framepos_t const end = _start + _length - 1;
1773 
1774  AudioIntervalResult silent_periods;
1775 
1776  bool in_silence = false;
1777  frameoffset_t silence_start = 0;
1778 
1779  while (pos < end && !itt.cancel) {
1780 
1781  /* fill `loudest' with the loudest absolute sample at each instant, across all channels */
1782  memset (loudest.get(), 0, sizeof (Sample) * block_size);
1783  for (uint32_t n = 0; n < n_channels(); ++n) {
1784 
1785  read_raw_internal (buf.get(), pos, block_size, n);
1786  for (framecnt_t i = 0; i < block_size; ++i) {
1787  loudest[i] = max (loudest[i], abs (buf[i]));
1788  }
1789  }
1790 
1791  /* now look for silence */
1792  for (framecnt_t i = 0; i < block_size; ++i) {
1793  bool const silence = abs (loudest[i]) < threshold;
1794  if (silence && !in_silence) {
1795  /* non-silence to silence */
1796  in_silence = true;
1797  silence_start = pos + i;
1798  } else if (!silence && in_silence) {
1799  /* silence to non-silence */
1800  in_silence = false;
1801  if (pos + i - 1 - silence_start >= min_length) {
1802  silent_periods.push_back (std::make_pair (silence_start, pos + i - 1));
1803  }
1804  }
1805  }
1806 
1807  pos += block_size;
1808  itt.progress = (end-pos)/(double)_length;
1809  }
1810 
1811  if (in_silence && end - 1 - silence_start >= min_length) {
1812  /* last block was silent, so finish off the last period */
1813  silent_periods.push_back (std::make_pair (silence_start, end));
1814  }
1815 
1816  itt.done = true;
1817 
1818  return silent_periods;
1819 }
1820 
1823 {
1824  return Evoral::Range<framepos_t> (first_frame() + _fade_in->back()->when + 1, last_frame() - _fade_out->back()->when);
1825 }
1826 
1829 {
1831 
1832  if (!pl) {
1833  /* not currently in a playlist - xfade length is unbounded
1834  (and irrelevant)
1835  */
1837  }
1838 
1840 
1841  if (start) {
1842  rl = pl->regions_at (position());
1843  } else {
1844  rl = pl->regions_at (last_frame());
1845  }
1846 
1847  RegionList::iterator i;
1849  uint32_t n = 0;
1850 
1851  /* count and find the other region in a single pass through the list */
1852 
1853  for (i = rl->begin(); i != rl->end(); ++i) {
1854  if ((*i).get() != this) {
1855  other = *i;
1856  }
1857  ++n;
1858  }
1859 
1860  if (n != 2) {
1861  /* zero or multiple regions stacked here - don't care about xfades */
1863  }
1864 
1865  return other;
1866 }
1867 
1868 framecnt_t
1870 {
1871  /* this is called from a UI to check on whether a new proposed
1872  length for an xfade is legal or not. it returns the legal
1873  length corresponding to @a len which may be shorter than or
1874  equal to @a len itself.
1875  */
1876 
1878  framecnt_t maxlen;
1879 
1880  if (!other) {
1881  /* zero or > 2 regions here, don't care about len, but
1882  it can't be longer than the region itself.
1883  */
1884  return min (length(), len);
1885  }
1886 
1887  /* we overlap a single region. clamp the length of an xfade to
1888  the maximum possible duration of the overlap (if the other
1889  region were trimmed appropriately).
1890  */
1891 
1892  if (start) {
1893  maxlen = other->latest_possible_frame() - position();
1894  } else {
1895  maxlen = last_frame() - other->earliest_possible_position();
1896  }
1897 
1898  return min (length(), min (maxlen, len));
1899 
1900 }
1901 
void fade_range(framepos_t, framepos_t)
Definition: audioregion.cc:961
virtual void resume_property_changes()
Definition: stateful.cc:302
AnalysisFeatureList _transients
Definition: region.h:374
ARDOUR::Session & _session
LIBARDOUR_API PBD::PropertyDescriptor< bool > default_fade_in
Definition: audioregion.cc:62
LIBARDOUR_API PBD::PropertyDescriptor< bool > fade_out_active
Definition: audioregion.cc:65
LIBARDOUR_API PBD::PropertyDescriptor< bool > default_fade_out
Definition: audioregion.cc:63
virtual framecnt_t read_raw_internal(Sample *, framepos_t, framecnt_t, int channel) const
Evoral::Range< framepos_t > body_range() const
void add_transient(framepos_t where)
PBD::Property< bool > _default_fade_out
Definition: audioregion.h:189
void set_fade_out(FadeShape, framecnt_t)
virtual framecnt_t read_peaks(PeakData *buf, framecnt_t npeaks, framecnt_t offset, framecnt_t cnt, uint32_t chan_n=0, double frames_per_pixel=1.0) const
Definition: audioregion.cc:421
static void cleanup_transients(AnalysisFeatureList &, float sr, float gap_msecs)
void connect_to_analysis_changed()
Definition: audioregion.cc:368
const std::string & value() const
Definition: xml++.h:159
void set_fade_out_length(framecnt_t)
LIBARDOUR_API PBD::PropertyDescriptor< layer_t > layer
Definition: region.cc:67
bool fade_out_is_default() const
Session & session() const
void set_envelope_active(bool yn)
Definition: audioregion.cc:404
virtual framecnt_t read(Sample *, framepos_t pos, framecnt_t cnt, int channel) const
Definition: audioregion.cc:446
framepos_t latest_possible_frame() const
Definition: region.cc:1724
PBD::Property< bool > _fade_out_active
Definition: audioregion.h:191
AutomationListProperty _inverse_fade_in
Definition: audioregion.h:219
shared_ptr< T > dynamic_pointer_cast(shared_ptr< U > const &r)
Definition: shared_ptr.hpp:396
PBD::Property< gain_t > _scale_amplitude
Definition: audioregion.h:193
LIBARDOUR_API PBD::PropertyDescriptor< std::string > name
T const & val() const
Definition: properties.h:96
static PBD::Signal1< void, std::string > Dialog
Definition: session.h:184
const std::string & name() const
Definition: xml++.h:104
AutomationListProperty _envelope
Definition: audioregion.h:222
std::list< std::pair< frameoffset_t, frameoffset_t > > AudioIntervalResult
Definition: types.h:83
static void generate_inverse_power_curve(boost::shared_ptr< Evoral::ControlList > dst, boost::shared_ptr< const Evoral::ControlList > src)
Definition: audioregion.cc:87
uint32_t _fade_out_suspended
Definition: audioregion.h:225
static int N
Definition: signals_test.cc:27
int separate_by_channel(ARDOUR::Session &, std::vector< boost::shared_ptr< Region > > &) const
PBD::Property< bool > _default_fade_in
Definition: audioregion.h:188
LIBARDOUR_API compute_peak_t compute_peak
Definition: globals.cc:129
tuple f
Definition: signals.py:35
PBD::Signal0< void > ContentsChanged
Definition: playlist.h:190
Definition: Beats.hpp:239
LIBPBD_API Transmitter error
const XMLNodeList & children(const std::string &str=std::string()) const
Definition: xml++.cc:329
float gain_t
Definition: types.h:58
std::ostream & endmsg(std::ostream &ostr)
Definition: transmitter.h:71
LIBARDOUR_API uint64_t AudioPlayback
Definition: debug.cc:49
SessionConfiguration config
Definition: session.h:866
PBD::Property< framepos_t > _sync_position
Definition: region.h:368
EventList::const_reverse_iterator const_reverse_iterator
Definition: ControlList.hpp:85
boost::shared_ptr< Source > source(uint32_t n=0) const
Definition: region.h:258
AudioRegion(boost::shared_ptr< AudioSource >)
AutomationListProperty _inverse_fade_out
Definition: audioregion.h:221
LIBARDOUR_API PBD::PropertyDescriptor< framepos_t > start
Definition: region.cc:63
virtual int _set_state(const XMLNode &, int version, PBD::PropertyChange &what_changed, bool send_signal)
Definition: region.cc:1241
XMLNode * add_child(const char *)
Definition: xml++.cc:351
PBD::Property< bool > _left_of_split
Definition: region.h:361
bool fade_in_is_default() const
framecnt_t frame_rate() const
Definition: session.h:365
PeakDatum max
Definition: types.h:489
static float accurate_coefficient_to_dB(float coeff)
Definition: dB.h:38
PBD::Property< bool > _valid_transients
Definition: region.h:363
std::list< XMLNode * > XMLNodeList
Definition: xml++.h:44
virtual framecnt_t read(Sample *dst, framepos_t start, framecnt_t cnt, int channel=0) const
Definition: audiosource.cc:312
PBD::Property< bool > _right_of_split
Definition: region.h:362
AutomationListProperty _fade_out
Definition: audioregion.h:220
void set_fade_out_shape(FadeShape)
Definition: audioregion.cc:995
#define _(Text)
Definition: i18n.h:11
bool destructive() const
Definition: source.h:82
void invalidate_transients()
Definition: region.cc:1608
SourceList _master_sources
Definition: region.h:372
SourceList _sources
Definition: region.h:370
#define X_(Text)
Definition: i18n.h:13
PBD::Property< framepos_t > _start
Definition: region.h:364
int64_t framecnt_t
Definition: types.h:76
XMLProperty * property(const char *)
Definition: xml++.cc:413
LIBARDOUR_API RCConfiguration * Config
Definition: globals.cc:119
static PBD::Signal0< void > HeaderPositionOffsetChanged
float Sample
Definition: types.h:54
void set_position(framepos_t)
Definition: region.cc:579
double maximum_amplitude(Progress *p=0) const
PBD::Property< bool > _sync_marked
Definition: region.h:360
std::list< framepos_t > AnalysisFeatureList
Definition: types.h:530
#define GAIN_COEFF_SMALL
Definition: dB.h:27
void set_progress(float)
Definition: progress.cc:59
PeakDatum min
Definition: types.h:488
bool string_is_affirmative(const std::string &str)
Definition: convert.cc:282
boost::shared_ptr< RegionList > regions_at(framepos_t frame)
Definition: playlist.cc:1705
void connect_to_header_position_offset_changed()
Definition: audioregion.cc:376
reverse_iterator rend()
PBD::Property< bool > _envelope_active
Definition: audioregion.h:187
#define AUDIOREGION_COPY_STATE(other)
Definition: audioregion.cc:202
Definition: amp.h:29
boost::shared_ptr< AudioSource > audio_source(uint32_t n=0) const
void set_fade_in_length(framecnt_t)
#define AUDIOREGION_STATE_DEFAULT
Definition: audioregion.cc:190
std::vector< boost::shared_ptr< Source > > SourceList
Definition: region.h:91
void set_fade_in(FadeShape, framecnt_t)
LIBARDOUR_API PBD::PropertyDescriptor< boost::shared_ptr< AutomationList > > fade_out
Definition: audioregion.cc:69
int adjust_transients(frameoffset_t delta)
Evoral::OverlapType coverage(framepos_t start, framepos_t end) const
Definition: region.h:195
LIBARDOUR_API PBD::PropertyDescriptor< boost::shared_ptr< AutomationList > > fade_in
Definition: audioregion.cc:67
LIBARDOUR_API PBD::PropertyDescriptor< boost::shared_ptr< AutomationList > > inverse_fade_in
Definition: audioregion.cc:68
#define DEBUG_TRACE(bits, str)
Definition: debug.h:55
int get_transients(AnalysisFeatureList &, bool force_new=false)
void set_fade_out_active(bool yn)
void fast_simple_add(double when, double value)
LIBARDOUR_API void make_property_quarks()
int64_t framepos_t
Definition: types.h:66
RouteGroup::RouteGroup(Session &s, const string &n) add_property(_relative)
Definition: route_group.cc:101
shared_ptr< T > static_pointer_cast(shared_ptr< U > const &r)
Definition: shared_ptr.hpp:386
uint32_t _fade_in_suspended
Definition: audioregion.h:224
FadeShape
Definition: types.h:592
framepos_t earliest_possible_position() const
Definition: region.cc:1714
int64_t frameoffset_t
Definition: types.h:71
EventList::size_type size() const
PBD::Property< std::string > _name
layer_t layer() const
Definition: region.h:115
virtual framecnt_t master_read_at(Sample *buf, Sample *mixdown_buf, float *gain_buf, framepos_t position, framecnt_t cnt, uint32_t chan_n=0) const
Definition: audioregion.cc:453
static void reverse_curve(boost::shared_ptr< Evoral::ControlList > dst, boost::shared_ptr< const Evoral::ControlList > src)
Definition: audioregion.cc:78
bool changed() const
Definition: stateful.cc:325
void set_fade_in_shape(FadeShape)
Definition: audioregion.cc:989
void set_fade_in_active(bool yn)
framecnt_t verify_xfade_bounds(framecnt_t, bool start)
framepos_t position() const
Definition: region.h:112
LIBPBD_API uint64_t Properties
Definition: debug.cc:47
framecnt_t read_from_sources(SourceList const &, framecnt_t, Sample *, framepos_t, framecnt_t, uint32_t) const
Definition: audioregion.cc:718
LIBARDOUR_API PBD::PropertyDescriptor< boost::shared_ptr< AutomationList > > inverse_fade_out
Definition: audioregion.cc:70
XMLProperty * add_property(const char *name, const std::string &value)
void remove_transient(framepos_t where)
const char * name
boost::shared_ptr< ARDOUR::Region > get_single_other_xfade_region(bool start) const
virtual XMLNode & state()
Definition: region.cc:1136
void add_child_nocopy(XMLNode &)
Definition: xml++.cc:357
uint32_t n_channels() const
Definition: region.h:259
Definition: xml++.h:95
DataType _type
Definition: region.h:358
std::string name() const
LIBARDOUR_API PBD::PropertyDescriptor< framepos_t > position
Definition: region.cc:65
bool speed_mismatch(float) const
void set_scale_amplitude(gain_t)
LIBARDOUR_API mix_buffers_no_gain_t mix_buffers_no_gain
Definition: globals.cc:133
Definition: debug.h:30
void send_change(const PBD::PropertyChange &)
Definition: region.cc:1311
virtual framecnt_t read_at(Sample *buf, Sample *mixdown_buf, float *gain_buf, framepos_t position, framecnt_t cnt, uint32_t chan_n=0) const
Definition: audioregion.cc:473
EventList::const_iterator const_iterator
Definition: ControlList.hpp:84
static float dB_to_coefficient(float dB)
Definition: dB.h:30
bool opaque() const
Definition: region.h:163
XMLNode * child(const char *) const
Definition: xml++.cc:309
bool cancelled() const
Definition: progress.cc:82
int _set_state(const XMLNode &, int version, PBD::PropertyChange &what_changed, bool send_signal)
Definition: audioregion.cc:835
int set_transients(AnalysisFeatureList &)
framecnt_t length() const
Definition: region.h:114
framepos_t first_frame() const
Definition: region.h:141
ControlEvent * back()
framepos_t start() const
Definition: region.h:113
int set_state(const XMLNode &, int version)
Definition: audioregion.cc:954
void post_set(const PBD::PropertyChange &)
Definition: audioregion.cc:338
int update_transient(framepos_t old_position, framepos_t new_position)
#define GAIN_COEFF_UNITY
Definition: dB.h:28
AudioIntervalResult find_silence(Sample, framecnt_t, InterThreadInfo &) const
LIBARDOUR_API apply_gain_to_buffer_t apply_gain_to_buffer
Definition: globals.cc:131
static boost::shared_ptr< Region > create(boost::shared_ptr< const Region > other, bool announce=false)
static void merge_curves(boost::shared_ptr< Evoral::ControlList > dst, boost::shared_ptr< const Evoral::ControlList > curve1, boost::shared_ptr< const Evoral::ControlList > curve2)
Definition: audioregion.cc:118
void normalize(float, float target_in_dB=0.0f)
XMLNodeList::const_iterator XMLNodeConstIterator
Definition: xml++.h:49
LIBARDOUR_API PBD::PropertyDescriptor< float > scale_amplitude
Definition: audioregion.cc:66
LIBARDOUR_API bool init(bool with_vst, bool try_optimization, const char *localedir)
Definition: globals.cc:376
LIBARDOUR_API PBD::PropertyDescriptor< bool > valid_transients
Definition: region.cc:62
LIBARDOUR_API PBD::PropertyDescriptor< bool > envelope_active
Definition: audioregion.cc:61
bool add(PropertyBase *prop)
XMLNode & get_basic_state()
Definition: audioregion.cc:765
void add(PropertyID id)
LIBARDOUR_API PBD::PropertyDescriptor< bool > fade_in_active
Definition: audioregion.cc:64
static void generate_db_fade(boost::shared_ptr< Evoral::ControlList > dst, double len, int num_steps, float dB_drop)
Definition: audioregion.cc:99
PBD::Property< bool > _fade_in_active
Definition: audioregion.h:190
AutomationListProperty _fade_in
Definition: audioregion.h:218
std::string string_compose(const std::string &fmt, const T1 &o1)
Definition: compose.h:208
double atof(const string &s)
Definition: convert.cc:158
LIBARDOUR_API PBD::PropertyDescriptor< boost::shared_ptr< AutomationList > > envelope
Definition: audioregion.cc:71
boost::shared_ptr< ARDOUR::Playlist > playlist() const
Definition: region.h:251
reverse_iterator rbegin()
boost::weak_ptr< ARDOUR::Playlist > _playlist
Definition: region.h:376
PBD::Property< framepos_t > _position
Definition: region.h:366
void suspend_property_changes()
Definition: region.cc:1292
PBD::Property< framecnt_t > _length
Definition: region.h:365
framepos_t last_frame() const
Definition: region.h:142
LIBARDOUR_API PBD::PropertyDescriptor< framecnt_t > length
Definition: region.cc:64
bool envelope_active() const
Definition: audioregion.h:83