fix up fwd/reverse stuff in semitone mode
[ardour2.git] / libs / ardour / audioregion.cc
blob447e4b8d953c8ec5fd9c6d6ac0f2afe2d311f8e9
1 /*
2 Copyright (C) 2000-2006 Paul Davis
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.
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.
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.
20 #include <cmath>
21 #include <climits>
22 #include <cfloat>
23 #include <algorithm>
25 #include <set>
27 #include <boost/scoped_array.hpp>
29 #include <glibmm/thread.h>
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"
37 #include "evoral/Curve.hpp"
39 #include "ardour/audioregion.h"
40 #include "ardour/debug.h"
41 #include "ardour/session.h"
42 #include "ardour/gain.h"
43 #include "ardour/dB.h"
44 #include "ardour/playlist.h"
45 #include "ardour/audiofilesource.h"
46 #include "ardour/region_factory.h"
47 #include "ardour/runtime_functions.h"
48 #include "ardour/transient_detector.h"
49 #include "ardour/progress.h"
51 #include "i18n.h"
52 #include <locale.h>
54 using namespace std;
55 using namespace ARDOUR;
56 using namespace PBD;
58 namespace ARDOUR {
59 namespace Properties {
60 PBD::PropertyDescriptor<bool> envelope_active;
61 PBD::PropertyDescriptor<bool> default_fade_in;
62 PBD::PropertyDescriptor<bool> default_fade_out;
63 PBD::PropertyDescriptor<bool> fade_in_active;
64 PBD::PropertyDescriptor<bool> fade_out_active;
65 PBD::PropertyDescriptor<float> scale_amplitude;
69 void
70 AudioRegion::make_property_quarks ()
72 Properties::envelope_active.property_id = g_quark_from_static_string (X_("envelope-active"));
73 DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for envelope-active = %1\n", Properties::envelope_active.property_id));
74 Properties::default_fade_in.property_id = g_quark_from_static_string (X_("default-fade-in"));
75 DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for default-fade-in = %1\n", Properties::default_fade_in.property_id));
76 Properties::default_fade_out.property_id = g_quark_from_static_string (X_("default-fade-out"));
77 DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for default-fade-out = %1\n", Properties::default_fade_out.property_id));
78 Properties::fade_in_active.property_id = g_quark_from_static_string (X_("fade-in-active"));
79 DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for fade-in-active = %1\n", Properties::fade_in_active.property_id));
80 Properties::fade_out_active.property_id = g_quark_from_static_string (X_("fade-out-active"));
81 DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for fade-out-active = %1\n", Properties::fade_out_active.property_id));
82 Properties::scale_amplitude.property_id = g_quark_from_static_string (X_("scale-amplitude"));
83 DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for scale-amplitude = %1\n", Properties::scale_amplitude.property_id));
86 void
87 AudioRegion::register_properties ()
89 /* no need to register parent class properties */
91 add_property (_envelope_active);
92 add_property (_default_fade_in);
93 add_property (_default_fade_out);
94 add_property (_fade_in_active);
95 add_property (_fade_out_active);
96 add_property (_scale_amplitude);
99 #define AUDIOREGION_STATE_DEFAULT \
100 _envelope_active (Properties::envelope_active, false) \
101 , _default_fade_in (Properties::default_fade_in, true) \
102 , _default_fade_out (Properties::default_fade_out, true) \
103 , _fade_in_active (Properties::fade_in_active, true) \
104 , _fade_out_active (Properties::fade_out_active, true) \
105 , _scale_amplitude (Properties::scale_amplitude, 1.0)
107 #define AUDIOREGION_COPY_STATE(other) \
108 _envelope_active (Properties::envelope_active, other->_envelope_active) \
109 , _default_fade_in (Properties::default_fade_in, other->_default_fade_in) \
110 , _default_fade_out (Properties::default_fade_out, other->_default_fade_out) \
111 , _fade_in_active (Properties::fade_in_active, other->_fade_in_active) \
112 , _fade_out_active (Properties::fade_out_active, other->_fade_out_active) \
113 , _scale_amplitude (Properties::scale_amplitude, other->_scale_amplitude)
114 /* a Session will reset these to its chosen defaults by calling AudioRegion::set_default_fade() */
116 void
117 AudioRegion::init ()
119 register_properties ();
121 suspend_property_changes();
122 set_default_fades ();
123 set_default_envelope ();
124 resume_property_changes();
126 listen_to_my_curves ();
127 connect_to_analysis_changed ();
128 connect_to_header_position_offset_changed ();
131 /** Constructor for use by derived types only */
132 AudioRegion::AudioRegion (Session& s, framepos_t start, framecnt_t len, std::string name)
133 : Region (s, start, len, name, DataType::AUDIO)
134 , AUDIOREGION_STATE_DEFAULT
135 , _automatable (s)
136 , _fade_in (new AutomationList(Evoral::Parameter(FadeInAutomation)))
137 , _fade_out (new AutomationList(Evoral::Parameter(FadeOutAutomation)))
138 , _envelope (new AutomationList(Evoral::Parameter(EnvelopeAutomation)))
139 , _fade_in_suspended (0)
140 , _fade_out_suspended (0)
142 init ();
143 assert (_sources.size() == _master_sources.size());
146 /** Basic AudioRegion constructor */
147 AudioRegion::AudioRegion (const SourceList& srcs)
148 : Region (srcs)
149 , AUDIOREGION_STATE_DEFAULT
150 , _automatable(srcs[0]->session())
151 , _fade_in (new AutomationList(Evoral::Parameter(FadeInAutomation)))
152 , _fade_out (new AutomationList(Evoral::Parameter(FadeOutAutomation)))
153 , _envelope (new AutomationList(Evoral::Parameter(EnvelopeAutomation)))
154 , _fade_in_suspended (0)
155 , _fade_out_suspended (0)
157 init ();
158 assert (_sources.size() == _master_sources.size());
161 AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other)
162 : Region (other)
163 , AUDIOREGION_COPY_STATE (other)
164 , _automatable (other->session())
165 , _fade_in (new AutomationList (*other->_fade_in))
166 , _fade_out (new AutomationList (*other->_fade_out))
167 /* As far as I can see, the _envelope's times are relative to region position, and have nothing
168 to do with sources (and hence _start). So when we copy the envelope, we just use the supplied offset.
170 , _envelope (new AutomationList (*other->_envelope, 0, other->_length))
171 , _fade_in_suspended (0)
172 , _fade_out_suspended (0)
174 /* don't use init here, because we got fade in/out from the other region
176 register_properties ();
177 listen_to_my_curves ();
178 connect_to_analysis_changed ();
179 connect_to_header_position_offset_changed ();
181 assert(_type == DataType::AUDIO);
182 assert (_sources.size() == _master_sources.size());
185 AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other, framecnt_t offset)
186 : Region (other, offset)
187 , AUDIOREGION_COPY_STATE (other)
188 , _automatable (other->session())
189 , _fade_in (new AutomationList (*other->_fade_in))
190 , _fade_out (new AutomationList (*other->_fade_out))
191 /* As far as I can see, the _envelope's times are relative to region position, and have nothing
192 to do with sources (and hence _start). So when we copy the envelope, we just use the supplied offset.
194 , _envelope (new AutomationList (*other->_envelope, offset, other->_length))
195 , _fade_in_suspended (0)
196 , _fade_out_suspended (0)
198 /* don't use init here, because we got fade in/out from the other region
200 register_properties ();
201 listen_to_my_curves ();
202 connect_to_analysis_changed ();
203 connect_to_header_position_offset_changed ();
205 assert(_type == DataType::AUDIO);
206 assert (_sources.size() == _master_sources.size());
209 AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other, const SourceList& srcs)
210 : Region (boost::static_pointer_cast<const Region>(other), srcs)
211 , AUDIOREGION_COPY_STATE (other)
212 , _automatable (other->session())
213 , _fade_in (new AutomationList (*other->_fade_in))
214 , _fade_out (new AutomationList (*other->_fade_out))
215 , _envelope (new AutomationList (*other->_envelope))
216 , _fade_in_suspended (0)
217 , _fade_out_suspended (0)
219 /* make-a-sort-of-copy-with-different-sources constructor (used by audio filter) */
221 register_properties ();
223 listen_to_my_curves ();
224 connect_to_analysis_changed ();
225 connect_to_header_position_offset_changed ();
227 assert (_sources.size() == _master_sources.size());
230 AudioRegion::AudioRegion (SourceList& srcs)
231 : Region (srcs)
232 , AUDIOREGION_STATE_DEFAULT
233 , _automatable(srcs[0]->session())
234 , _fade_in (new AutomationList(Evoral::Parameter(FadeInAutomation)))
235 , _fade_out (new AutomationList(Evoral::Parameter(FadeOutAutomation)))
236 , _envelope (new AutomationList(Evoral::Parameter(EnvelopeAutomation)))
237 , _fade_in_suspended (0)
238 , _fade_out_suspended (0)
240 init ();
242 assert(_type == DataType::AUDIO);
243 assert (_sources.size() == _master_sources.size());
246 AudioRegion::~AudioRegion ()
250 void
251 AudioRegion::post_set (const PropertyChange& /*ignored*/)
253 if (!_sync_marked) {
254 _sync_position = _start;
257 /* return to default fades if the existing ones are too long */
259 if (_left_of_split) {
260 if (_fade_in->back()->when >= _length) {
261 set_default_fade_in ();
263 set_default_fade_out ();
264 _left_of_split = false;
267 if (_right_of_split) {
268 if (_fade_out->back()->when >= _length) {
269 set_default_fade_out ();
272 set_default_fade_in ();
273 _right_of_split = false;
276 /* If _length changed, adjust our gain envelope accordingly */
277 _envelope->truncate_end (_length);
280 void
281 AudioRegion::connect_to_analysis_changed ()
283 for (SourceList::const_iterator i = _sources.begin(); i != _sources.end(); ++i) {
284 (*i)->AnalysisChanged.connect_same_thread (*this, boost::bind (&AudioRegion::invalidate_transients, this));
288 void
289 AudioRegion::connect_to_header_position_offset_changed ()
291 set<boost::shared_ptr<Source> > unique_srcs;
293 for (SourceList::const_iterator i = _sources.begin(); i != _sources.end(); ++i) {
295 /* connect only once to HeaderPositionOffsetChanged, even if sources are replicated
298 if (unique_srcs.find (*i) == unique_srcs.end ()) {
299 unique_srcs.insert (*i);
300 boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (*i);
301 if (afs) {
302 afs->HeaderPositionOffsetChanged.connect_same_thread (*this, boost::bind (&AudioRegion::source_offset_changed, this));
308 void
309 AudioRegion::listen_to_my_curves ()
311 _envelope->StateChanged.connect_same_thread (*this, boost::bind (&AudioRegion::envelope_changed, this));
312 _fade_in->StateChanged.connect_same_thread (*this, boost::bind (&AudioRegion::fade_in_changed, this));
313 _fade_out->StateChanged.connect_same_thread (*this, boost::bind (&AudioRegion::fade_out_changed, this));
316 void
317 AudioRegion::set_envelope_active (bool yn)
319 if (envelope_active() != yn) {
320 _envelope_active = yn;
321 send_change (PropertyChange (Properties::envelope_active));
325 ARDOUR::framecnt_t
326 AudioRegion::read_peaks (PeakData *buf, framecnt_t npeaks, framecnt_t offset, framecnt_t cnt, uint32_t chan_n, double samples_per_unit) const
328 if (chan_n >= _sources.size()) {
329 return 0;
332 if (audio_source(chan_n)->read_peaks (buf, npeaks, offset, cnt, samples_per_unit)) {
333 return 0;
334 } else {
335 if (_scale_amplitude != 1.0f) {
336 for (framecnt_t n = 0; n < npeaks; ++n) {
337 buf[n].max *= _scale_amplitude;
338 buf[n].min *= _scale_amplitude;
341 return cnt;
345 framecnt_t
346 AudioRegion::read (Sample* buf, framepos_t timeline_position, framecnt_t cnt, int channel) const
348 /* raw read, no fades, no gain, nada */
349 return _read_at (_sources, _length, buf, 0, 0, _position + timeline_position, cnt, channel, 0, 0, ReadOps (0));
352 framecnt_t
353 AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer,
354 framepos_t file_position, framecnt_t cnt, uint32_t chan_n,
355 framecnt_t read_frames, framecnt_t skip_frames) const
357 /* regular diskstream/butler read complete with fades etc */
358 return _read_at (_sources, _length, buf, mixdown_buffer, gain_buffer,
359 file_position, cnt, chan_n, read_frames, skip_frames, ReadOps (~0));
362 framecnt_t
363 AudioRegion::master_read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer,
364 framepos_t position, framecnt_t cnt, uint32_t chan_n) const
366 /* do not read gain/scaling/fades and do not count this disk i/o in statistics */
368 return _read_at (_master_sources, _master_sources.front()->length(_master_sources.front()->timeline_position()),
369 buf, mixdown_buffer, gain_buffer, position, cnt, chan_n, 0, 0, ReadOps (0));
372 framecnt_t
373 AudioRegion::_read_at (const SourceList& /*srcs*/, framecnt_t limit,
374 Sample *buf, Sample *mixdown_buffer, float *gain_buffer,
375 framepos_t position,
376 framecnt_t cnt,
377 uint32_t chan_n,
378 framecnt_t /*read_frames*/,
379 framecnt_t /*skip_frames*/,
380 ReadOps rops) const
382 frameoffset_t internal_offset;
383 frameoffset_t buf_offset;
384 framecnt_t to_read;
385 bool raw = (rops == ReadOpsNone);
387 if (n_channels() == 0) {
388 return 0;
391 if (muted() && !raw) {
392 return 0; /* read nothing */
395 /* precondition: caller has verified that we cover the desired section */
397 if (position < _position) {
398 internal_offset = 0;
399 buf_offset = _position - position;
400 cnt -= buf_offset;
401 } else {
402 internal_offset = position - _position;
403 buf_offset = 0;
406 if (internal_offset >= limit) {
407 return 0; /* read nothing */
410 if ((to_read = min (cnt, limit - internal_offset)) == 0) {
411 return 0; /* read nothing */
414 if (opaque() || raw) {
415 /* overwrite whatever is there */
416 mixdown_buffer = buf + buf_offset;
417 } else {
418 mixdown_buffer += buf_offset;
421 if (rops & ReadOpsCount) {
422 _read_data_count = 0;
425 if (chan_n < n_channels()) {
427 boost::shared_ptr<AudioSource> src = audio_source(chan_n);
428 if (src->read (mixdown_buffer, _start + internal_offset, to_read) != to_read) {
429 return 0; /* "read nothing" */
432 if (rops & ReadOpsCount) {
433 _read_data_count += src->read_data_count();
436 } else {
438 /* track is N-channel, this region has less channels; silence the ones
439 we don't have.
442 if (Config->get_replicate_missing_region_channels()) {
443 /* track is N-channel, this region has less channels, so use a relevant channel
446 uint32_t channel = n_channels() % chan_n;
447 boost::shared_ptr<AudioSource> src = audio_source (channel);
449 if (src->read (mixdown_buffer, _start + internal_offset, to_read) != to_read) {
450 return 0; /* "read nothing" */
453 /* adjust read data count appropriately since this was a duplicate read */
454 src->dec_read_data_count (to_read);
455 } else {
456 memset (mixdown_buffer, 0, sizeof (Sample) * cnt);
460 if (rops & ReadOpsFades) {
462 /* fade in */
464 if (_fade_in_active && _session.config.get_use_region_fades()) {
466 framecnt_t fade_in_length = (framecnt_t) _fade_in->back()->when;
468 /* see if this read is within the fade in */
470 if (internal_offset < fade_in_length) {
472 framecnt_t fi_limit;
474 fi_limit = min (to_read, fade_in_length - internal_offset);
476 _fade_in->curve().get_vector (internal_offset, internal_offset+fi_limit, gain_buffer, fi_limit);
478 for (framecnt_t n = 0; n < fi_limit; ++n) {
479 mixdown_buffer[n] *= gain_buffer[n];
484 /* fade out */
486 if (_fade_out_active && _session.config.get_use_region_fades()) {
488 /* see if some part of this read is within the fade out */
490 /* ................. >| REGION
491 limit
493 { } FADE
494 fade_out_length
496 limit - fade_out_length
497 |--------------|
498 ^internal_offset
499 ^internal_offset + to_read
501 we need the intersection of [internal_offset,internal_offset+to_read] with
502 [limit - fade_out_length, limit]
507 framecnt_t fade_out_length = (framecnt_t) _fade_out->back()->when;
508 framecnt_t fade_interval_start = max(internal_offset, limit-fade_out_length);
509 framecnt_t fade_interval_end = min(internal_offset + to_read, limit);
511 if (fade_interval_end > fade_interval_start) {
512 /* (part of the) the fade out is in this buffer */
514 framecnt_t fo_limit = fade_interval_end - fade_interval_start;
515 framecnt_t curve_offset = fade_interval_start - (limit-fade_out_length);
516 framecnt_t fade_offset = fade_interval_start - internal_offset;
518 _fade_out->curve().get_vector (curve_offset, curve_offset+fo_limit, gain_buffer, fo_limit);
520 for (framecnt_t n = 0, m = fade_offset; n < fo_limit; ++n, ++m) {
521 mixdown_buffer[m] *= gain_buffer[n];
528 /* Regular gain curves and scaling */
530 if ((rops & ReadOpsOwnAutomation) && envelope_active()) {
531 _envelope->curve().get_vector (internal_offset, internal_offset + to_read, gain_buffer, to_read);
533 if ((rops & ReadOpsOwnScaling) && _scale_amplitude != 1.0f) {
534 for (framecnt_t n = 0; n < to_read; ++n) {
535 mixdown_buffer[n] *= gain_buffer[n] * _scale_amplitude;
537 } else {
538 for (framecnt_t n = 0; n < to_read; ++n) {
539 mixdown_buffer[n] *= gain_buffer[n];
542 } else if ((rops & ReadOpsOwnScaling) && _scale_amplitude != 1.0f) {
544 // XXX this should be using what in 2.0 would have been:
545 // Session::apply_gain_to_buffer (mixdown_buffer, to_read, _scale_amplitude);
547 for (framecnt_t n = 0; n < to_read; ++n) {
548 mixdown_buffer[n] *= _scale_amplitude;
552 if (!opaque() && (buf != mixdown_buffer)) {
554 /* gack. the things we do for users.
557 buf += buf_offset;
559 for (framecnt_t n = 0; n < to_read; ++n) {
560 buf[n] += mixdown_buffer[n];
564 return to_read;
567 XMLNode&
568 AudioRegion::state ()
570 XMLNode& node (Region::state ());
571 XMLNode *child;
572 char buf[64];
573 LocaleGuard lg (X_("POSIX"));
575 snprintf (buf, sizeof (buf), "%u", (uint32_t) _sources.size());
576 node.add_property ("channels", buf);
578 Stateful::add_properties (node);
580 child = node.add_child ("Envelope");
582 bool default_env = false;
584 // If there are only two points, the points are in the start of the region and the end of the region
585 // so, if they are both at 1.0f, that means the default region.
587 if (_envelope->size() == 2 &&
588 _envelope->front()->value == 1.0f &&
589 _envelope->back()->value==1.0f) {
590 if (_envelope->front()->when == 0 && _envelope->back()->when == _length) {
591 default_env = true;
595 if (default_env) {
596 child->add_property ("default", "yes");
597 } else {
598 child->add_child_nocopy (_envelope->get_state ());
601 child = node.add_child (X_("FadeIn"));
603 if (_default_fade_in) {
604 child->add_property ("default", "yes");
605 } else {
606 child->add_child_nocopy (_fade_in->get_state ());
609 child = node.add_child (X_("FadeOut"));
611 if (_default_fade_out) {
612 child->add_property ("default", "yes");
613 } else {
614 child->add_child_nocopy (_fade_out->get_state ());
617 return node;
621 AudioRegion::_set_state (const XMLNode& node, int version, PropertyChange& what_changed, bool send)
623 const XMLNodeList& nlist = node.children();
624 const XMLProperty *prop;
625 LocaleGuard lg (X_("POSIX"));
626 boost::shared_ptr<Playlist> the_playlist (_playlist.lock());
628 suspend_property_changes ();
630 if (the_playlist) {
631 the_playlist->freeze ();
635 /* this will set all our State members and stuff controlled by the Region.
636 It should NOT send any changed signals - that is our responsibility.
639 Region::_set_state (node, version, what_changed, false);
641 if ((prop = node.property ("scale-gain")) != 0) {
642 float a = atof (prop->value().c_str());
643 if (a != _scale_amplitude) {
644 _scale_amplitude = a;
645 what_changed.add (Properties::scale_amplitude);
649 /* Now find envelope description and other related child items */
651 _envelope->freeze ();
653 for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
654 XMLNode *child;
655 XMLProperty *prop;
657 child = (*niter);
659 if (child->name() == "Envelope") {
661 _envelope->clear ();
663 if ((prop = child->property ("default")) != 0 || _envelope->set_state (*child, version)) {
664 set_default_envelope ();
667 _envelope->set_max_xval (_length);
668 _envelope->truncate_end (_length);
671 } else if (child->name() == "FadeIn") {
673 _fade_in->clear ();
675 if ((prop = child->property ("default")) != 0 || (prop = child->property ("steepness")) != 0) {
676 set_default_fade_in ();
677 } else {
678 XMLNode* grandchild = child->child ("AutomationList");
679 if (grandchild) {
680 _fade_in->set_state (*grandchild, version);
684 if ((prop = child->property ("active")) != 0) {
685 if (string_is_affirmative (prop->value())) {
686 set_fade_in_active (true);
687 } else {
688 set_fade_in_active (false);
692 } else if (child->name() == "FadeOut") {
694 _fade_out->clear ();
696 if ((prop = child->property ("default")) != 0 || (prop = child->property ("steepness")) != 0) {
697 set_default_fade_out ();
698 } else {
699 XMLNode* grandchild = child->child ("AutomationList");
700 if (grandchild) {
701 _fade_out->set_state (*grandchild, version);
705 if ((prop = child->property ("active")) != 0) {
706 if (string_is_affirmative (prop->value())) {
707 set_fade_out_active (true);
708 } else {
709 set_fade_out_active (false);
716 _envelope->thaw ();
717 resume_property_changes ();
719 if (send) {
720 send_change (what_changed);
723 if (the_playlist) {
724 the_playlist->thaw ();
727 return 0;
731 AudioRegion::set_state (const XMLNode& node, int version)
733 PropertyChange what_changed;
734 return _set_state (node, version, what_changed, true);
737 void
738 AudioRegion::set_fade_in_shape (FadeShape shape)
740 set_fade_in (shape, (framecnt_t) _fade_in->back()->when);
743 void
744 AudioRegion::set_fade_out_shape (FadeShape shape)
746 set_fade_out (shape, (framecnt_t) _fade_out->back()->when);
749 void
750 AudioRegion::set_fade_in (boost::shared_ptr<AutomationList> f)
752 _fade_in->freeze ();
753 *_fade_in = *f;
754 _fade_in->thaw ();
756 send_change (PropertyChange (Properties::fade_in));
759 void
760 AudioRegion::set_fade_in (FadeShape shape, framecnt_t len)
762 _fade_in->freeze ();
763 _fade_in->clear ();
765 switch (shape) {
766 case FadeLinear:
767 _fade_in->fast_simple_add (0.0, 0.0);
768 _fade_in->fast_simple_add (len, 1.0);
769 break;
771 case FadeFast:
772 _fade_in->fast_simple_add (0, 0);
773 _fade_in->fast_simple_add (len * 0.389401, 0.0333333);
774 _fade_in->fast_simple_add (len * 0.629032, 0.0861111);
775 _fade_in->fast_simple_add (len * 0.829493, 0.233333);
776 _fade_in->fast_simple_add (len * 0.9447, 0.483333);
777 _fade_in->fast_simple_add (len * 0.976959, 0.697222);
778 _fade_in->fast_simple_add (len, 1);
779 break;
781 case FadeSlow:
782 _fade_in->fast_simple_add (0, 0);
783 _fade_in->fast_simple_add (len * 0.0207373, 0.197222);
784 _fade_in->fast_simple_add (len * 0.0645161, 0.525);
785 _fade_in->fast_simple_add (len * 0.152074, 0.802778);
786 _fade_in->fast_simple_add (len * 0.276498, 0.919444);
787 _fade_in->fast_simple_add (len * 0.481567, 0.980556);
788 _fade_in->fast_simple_add (len * 0.767281, 1);
789 _fade_in->fast_simple_add (len, 1);
790 break;
792 case FadeLogA:
793 _fade_in->fast_simple_add (0, 0);
794 _fade_in->fast_simple_add (len * 0.0737327, 0.308333);
795 _fade_in->fast_simple_add (len * 0.246544, 0.658333);
796 _fade_in->fast_simple_add (len * 0.470046, 0.886111);
797 _fade_in->fast_simple_add (len * 0.652074, 0.972222);
798 _fade_in->fast_simple_add (len * 0.771889, 0.988889);
799 _fade_in->fast_simple_add (len, 1);
800 break;
802 case FadeLogB:
803 _fade_in->fast_simple_add (0, 0);
804 _fade_in->fast_simple_add (len * 0.304147, 0.0694444);
805 _fade_in->fast_simple_add (len * 0.529954, 0.152778);
806 _fade_in->fast_simple_add (len * 0.725806, 0.333333);
807 _fade_in->fast_simple_add (len * 0.847926, 0.558333);
808 _fade_in->fast_simple_add (len * 0.919355, 0.730556);
809 _fade_in->fast_simple_add (len, 1);
810 break;
813 _fade_in->thaw ();
814 send_change (PropertyChange (Properties::fade_in));
817 void
818 AudioRegion::set_fade_out (boost::shared_ptr<AutomationList> f)
820 _fade_out->freeze ();
821 *_fade_out = *f;
822 _fade_out->thaw ();
824 send_change (PropertyChange (Properties::fade_in));
827 void
828 AudioRegion::set_fade_out (FadeShape shape, framecnt_t len)
830 _fade_out->freeze ();
831 _fade_out->clear ();
833 switch (shape) {
834 case FadeFast:
835 _fade_out->fast_simple_add (len * 0, 1);
836 _fade_out->fast_simple_add (len * 0.023041, 0.697222);
837 _fade_out->fast_simple_add (len * 0.0553, 0.483333);
838 _fade_out->fast_simple_add (len * 0.170507, 0.233333);
839 _fade_out->fast_simple_add (len * 0.370968, 0.0861111);
840 _fade_out->fast_simple_add (len * 0.610599, 0.0333333);
841 _fade_out->fast_simple_add (len * 1, 0);
842 break;
844 case FadeLogA:
845 _fade_out->fast_simple_add (len * 0, 1);
846 _fade_out->fast_simple_add (len * 0.228111, 0.988889);
847 _fade_out->fast_simple_add (len * 0.347926, 0.972222);
848 _fade_out->fast_simple_add (len * 0.529954, 0.886111);
849 _fade_out->fast_simple_add (len * 0.753456, 0.658333);
850 _fade_out->fast_simple_add (len * 0.9262673, 0.308333);
851 _fade_out->fast_simple_add (len * 1, 0);
852 break;
854 case FadeSlow:
855 _fade_out->fast_simple_add (len * 0, 1);
856 _fade_out->fast_simple_add (len * 0.305556, 1);
857 _fade_out->fast_simple_add (len * 0.548611, 0.991736);
858 _fade_out->fast_simple_add (len * 0.759259, 0.931129);
859 _fade_out->fast_simple_add (len * 0.918981, 0.68595);
860 _fade_out->fast_simple_add (len * 0.976852, 0.22865);
861 _fade_out->fast_simple_add (len * 1, 0);
862 break;
864 case FadeLogB:
865 _fade_out->fast_simple_add (len * 0, 1);
866 _fade_out->fast_simple_add (len * 0.080645, 0.730556);
867 _fade_out->fast_simple_add (len * 0.277778, 0.289256);
868 _fade_out->fast_simple_add (len * 0.470046, 0.152778);
869 _fade_out->fast_simple_add (len * 0.695853, 0.0694444);
870 _fade_out->fast_simple_add (len * 1, 0);
871 break;
873 case FadeLinear:
874 _fade_out->fast_simple_add (len * 0, 1);
875 _fade_out->fast_simple_add (len * 1, 0);
876 break;
879 _fade_out->thaw ();
880 send_change (PropertyChange (Properties::fade_in));
883 void
884 AudioRegion::set_fade_in_length (framecnt_t len)
886 if (len > _length) {
887 len = _length - 1;
890 bool changed = _fade_in->extend_to (len);
892 if (changed) {
893 _default_fade_in = false;
894 send_change (PropertyChange (Properties::fade_in));
898 void
899 AudioRegion::set_fade_out_length (framecnt_t len)
901 if (len > _length) {
902 len = _length - 1;
905 bool changed = _fade_out->extend_to (len);
907 if (changed) {
908 _default_fade_out = false;
909 send_change (PropertyChange (Properties::fade_out));
913 void
914 AudioRegion::set_fade_in_active (bool yn)
916 if (yn == _fade_in_active) {
917 return;
920 _fade_in_active = yn;
921 send_change (PropertyChange (Properties::fade_in_active));
924 void
925 AudioRegion::set_fade_out_active (bool yn)
927 if (yn == _fade_out_active) {
928 return;
930 _fade_out_active = yn;
931 send_change (PropertyChange (Properties::fade_out_active));
934 bool
935 AudioRegion::fade_in_is_default () const
937 return _fade_in->size() == 2 && _fade_in->front()->when == 0 && _fade_in->back()->when == 64;
940 bool
941 AudioRegion::fade_out_is_default () const
943 return _fade_out->size() == 2 && _fade_out->front()->when == 0 && _fade_out->back()->when == 64;
946 void
947 AudioRegion::set_default_fade_in ()
949 _fade_in_suspended = 0;
950 set_fade_in (FadeLinear, 64);
953 void
954 AudioRegion::set_default_fade_out ()
956 _fade_out_suspended = 0;
957 set_fade_out (FadeLinear, 64);
960 void
961 AudioRegion::set_default_fades ()
963 set_default_fade_in ();
964 set_default_fade_out ();
967 void
968 AudioRegion::set_default_envelope ()
970 _envelope->freeze ();
971 _envelope->clear ();
972 _envelope->fast_simple_add (0, 1.0f);
973 _envelope->fast_simple_add (_length, 1.0f);
974 _envelope->thaw ();
977 void
978 AudioRegion::recompute_at_end ()
980 /* our length has changed. recompute a new final point by interpolating
981 based on the the existing curve.
984 _envelope->freeze ();
985 _envelope->truncate_end (_length);
986 _envelope->set_max_xval (_length);
987 _envelope->thaw ();
989 suspend_property_changes();
991 if (_left_of_split) {
992 set_default_fade_out ();
993 _left_of_split = false;
994 } else if (_fade_out->back()->when > _length) {
995 _fade_out->extend_to (_length);
996 send_change (PropertyChange (Properties::fade_out));
999 if (_fade_in->back()->when > _length) {
1000 _fade_in->extend_to (_length);
1001 send_change (PropertyChange (Properties::fade_in));
1004 resume_property_changes();
1007 void
1008 AudioRegion::recompute_at_start ()
1010 /* as above, but the shift was from the front */
1012 _envelope->truncate_start (_length);
1014 suspend_property_changes();
1016 if (_right_of_split) {
1017 set_default_fade_in ();
1018 _right_of_split = false;
1019 } else if (_fade_in->back()->when > _length) {
1020 _fade_in->extend_to (_length);
1021 send_change (PropertyChange (Properties::fade_in));
1024 if (_fade_out->back()->when > _length) {
1025 _fade_out->extend_to (_length);
1026 send_change (PropertyChange (Properties::fade_out));
1029 resume_property_changes();
1033 AudioRegion::separate_by_channel (Session& /*session*/, vector<boost::shared_ptr<Region> >& v) const
1035 SourceList srcs;
1036 string new_name;
1037 int n = 0;
1039 if (_sources.size() < 2) {
1040 return 0;
1043 for (SourceList::const_iterator i = _sources.begin(); i != _sources.end(); ++i) {
1044 srcs.clear ();
1045 srcs.push_back (*i);
1047 new_name = _name;
1049 if (_sources.size() == 2) {
1050 if (n == 0) {
1051 new_name += "-L";
1052 } else {
1053 new_name += "-R";
1055 } else {
1056 new_name += '-';
1057 new_name += ('0' + n + 1);
1060 /* create a copy with just one source. prevent if from being thought of as
1061 "whole file" even if it covers the entire source file(s).
1064 PropertyList plist;
1066 plist.add (Properties::start, _start.val());
1067 plist.add (Properties::length, _length.val());
1068 plist.add (Properties::name, new_name);
1069 plist.add (Properties::layer, _layer.val());
1071 v.push_back(RegionFactory::create (srcs, plist));
1072 v.back()->set_whole_file (false);
1074 ++n;
1077 return 0;
1080 framecnt_t
1081 AudioRegion::read_raw_internal (Sample* buf, framepos_t pos, framecnt_t cnt, int channel) const
1083 return audio_source(channel)->read (buf, pos, cnt);
1087 AudioRegion::exportme (Session& /*session*/, ARDOUR::ExportSpecification& /*spec*/)
1089 // TODO EXPORT
1090 // const framecnt_t blocksize = 4096;
1091 // framecnt_t to_read;
1092 // int status = -1;
1094 // spec.channels = _sources.size();
1096 // if (spec.prepare (blocksize, session.frame_rate())) {
1097 // goto out;
1098 // }
1100 // spec.pos = 0;
1101 // spec.total_frames = _length;
1103 // while (spec.pos < _length && !spec.stop) {
1106 // /* step 1: interleave */
1108 // to_read = min (_length - spec.pos, blocksize);
1110 // if (spec.channels == 1) {
1112 // if (read_raw_internal (spec.dataF, _start + spec.pos, to_read) != to_read) {
1113 // goto out;
1114 // }
1116 // } else {
1118 // Sample buf[blocksize];
1120 // for (uint32_t chan = 0; chan < spec.channels; ++chan) {
1122 // if (audio_source(chan)->read (buf, _start + spec.pos, to_read) != to_read) {
1123 // goto out;
1124 // }
1126 // for (framecnt_t x = 0; x < to_read; ++x) {
1127 // spec.dataF[chan+(x*spec.channels)] = buf[x];
1128 // }
1129 // }
1130 // }
1132 // if (spec.process (to_read)) {
1133 // goto out;
1134 // }
1136 // spec.pos += to_read;
1137 // spec.progress = (double) spec.pos /_length;
1139 // }
1141 // status = 0;
1143 // out:
1144 // spec.running = false;
1145 // spec.status = status;
1146 // spec.clear();
1148 // return status;
1149 return 0;
1152 void
1153 AudioRegion::set_scale_amplitude (gain_t g)
1155 boost::shared_ptr<Playlist> pl (playlist());
1157 _scale_amplitude = g;
1159 /* tell the diskstream we're in */
1161 if (pl) {
1162 pl->ContentsChanged();
1165 /* tell everybody else */
1167 send_change (PropertyChange (Properties::scale_amplitude));
1170 /** @return the maximum (linear) amplitude of the region, or a -ve
1171 * number if the Progress object reports that the process was cancelled.
1173 double
1174 AudioRegion::maximum_amplitude (Progress* p) const
1176 framepos_t fpos = _start;
1177 framepos_t const fend = _start + _length;
1178 double maxamp = 0;
1180 framecnt_t const blocksize = 64 * 1024;
1181 Sample buf[blocksize];
1183 while (fpos < fend) {
1185 uint32_t n;
1187 framecnt_t const to_read = min (fend - fpos, blocksize);
1189 for (n = 0; n < n_channels(); ++n) {
1191 /* read it in */
1193 if (read_raw_internal (buf, fpos, to_read, n) != to_read) {
1194 return 0;
1197 maxamp = compute_peak (buf, to_read, maxamp);
1200 fpos += to_read;
1201 if (p) {
1202 p->set_progress (float (fpos - _start) / _length);
1203 if (p->cancelled ()) {
1204 return -1;
1209 return maxamp;
1212 /** Normalize using a given maximum amplitude and target, so that region
1213 * _scale_amplitude becomes target / max_amplitude.
1215 void
1216 AudioRegion::normalize (float max_amplitude, float target_dB)
1218 gain_t target = dB_to_coefficient (target_dB);
1220 if (target == 1.0f) {
1221 /* do not normalize to precisely 1.0 (0 dBFS), to avoid making it appear
1222 that we may have clipped.
1224 target -= FLT_EPSILON;
1227 if (max_amplitude == 0.0f) {
1228 /* don't even try */
1229 return;
1232 if (max_amplitude == target) {
1233 /* we can't do anything useful */
1234 return;
1237 set_scale_amplitude (target / max_amplitude);
1240 void
1241 AudioRegion::fade_in_changed ()
1243 send_change (PropertyChange (Properties::fade_in));
1246 void
1247 AudioRegion::fade_out_changed ()
1249 send_change (PropertyChange (Properties::fade_out));
1252 void
1253 AudioRegion::envelope_changed ()
1255 send_change (PropertyChange (Properties::envelope));
1258 void
1259 AudioRegion::suspend_fade_in ()
1261 if (++_fade_in_suspended == 1) {
1262 if (fade_in_is_default()) {
1263 set_fade_in_active (false);
1268 void
1269 AudioRegion::resume_fade_in ()
1271 if (--_fade_in_suspended == 0 && _fade_in_suspended) {
1272 set_fade_in_active (true);
1276 void
1277 AudioRegion::suspend_fade_out ()
1279 if (++_fade_out_suspended == 1) {
1280 if (fade_out_is_default()) {
1281 set_fade_out_active (false);
1286 void
1287 AudioRegion::resume_fade_out ()
1289 if (--_fade_out_suspended == 0 &&_fade_out_suspended) {
1290 set_fade_out_active (true);
1294 bool
1295 AudioRegion::speed_mismatch (float sr) const
1297 if (_sources.empty()) {
1298 /* impossible, but ... */
1299 return false;
1302 float fsr = audio_source()->sample_rate();
1304 return fsr != sr;
1307 void
1308 AudioRegion::source_offset_changed ()
1310 /* XXX this fixes a crash that should not occur. It does occur
1311 becauses regions are not being deleted when a session
1312 is unloaded. That bug must be fixed.
1315 if (_sources.empty()) {
1316 return;
1319 boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(_sources.front());
1321 if (afs && afs->destructive()) {
1322 // set_start (source()->natural_position(), this);
1323 set_position (source()->natural_position(), this);
1327 boost::shared_ptr<AudioSource>
1328 AudioRegion::audio_source (uint32_t n) const
1330 // Guaranteed to succeed (use a static cast for speed?)
1331 return boost::dynamic_pointer_cast<AudioSource>(source(n));
1334 int
1335 AudioRegion::adjust_transients (frameoffset_t delta)
1337 for (AnalysisFeatureList::iterator x = _transients.begin(); x != _transients.end(); ++x) {
1338 (*x) = (*x) + delta;
1341 send_change (PropertyChange (Properties::valid_transients));
1343 return 0;
1347 AudioRegion::update_transient (framepos_t old_position, framepos_t new_position)
1349 for (AnalysisFeatureList::iterator x = _transients.begin(); x != _transients.end(); ++x) {
1350 if ((*x) == old_position) {
1351 (*x) = new_position;
1352 send_change (PropertyChange (Properties::valid_transients));
1354 break;
1358 return 0;
1361 void
1362 AudioRegion::add_transient (framepos_t where)
1364 _transients.push_back(where);
1365 _valid_transients = true;
1367 send_change (PropertyChange (Properties::valid_transients));
1370 void
1371 AudioRegion::remove_transient (framepos_t where)
1373 _transients.remove(where);
1374 _valid_transients = true;
1376 send_change (PropertyChange (Properties::valid_transients));
1380 AudioRegion::set_transients (AnalysisFeatureList& results)
1382 _transients.clear();
1383 _transients = results;
1384 _valid_transients = true;
1386 send_change (PropertyChange (Properties::valid_transients));
1388 return 0;
1392 AudioRegion::get_transients (AnalysisFeatureList& results, bool force_new)
1394 boost::shared_ptr<Playlist> pl = playlist();
1396 if (!pl) {
1397 return -1;
1400 if (_valid_transients && !force_new) {
1401 results = _transients;
1402 return 0;
1405 SourceList::iterator s;
1407 for (s = _sources.begin() ; s != _sources.end(); ++s) {
1408 if (!(*s)->has_been_analysed()) {
1409 cerr << "For " << name() << " source " << (*s)->name() << " has not been analyzed\n";
1410 break;
1414 if (s == _sources.end()) {
1415 /* all sources are analyzed, merge data from each one */
1417 for (s = _sources.begin() ; s != _sources.end(); ++s) {
1419 /* find the set of transients within the bounds of this region */
1421 AnalysisFeatureList::iterator low = lower_bound ((*s)->transients.begin(),
1422 (*s)->transients.end(),
1423 _start);
1425 AnalysisFeatureList::iterator high = upper_bound ((*s)->transients.begin(),
1426 (*s)->transients.end(),
1427 _start + _length);
1429 /* and add them */
1431 results.insert (results.end(), low, high);
1434 TransientDetector::cleanup_transients (results, pl->session().frame_rate(), 3.0);
1436 /* translate all transients to current position */
1438 for (AnalysisFeatureList::iterator x = results.begin(); x != results.end(); ++x) {
1439 (*x) -= _start;
1440 (*x) += _position;
1443 _transients = results;
1444 _valid_transients = true;
1446 return 0;
1449 /* no existing/complete transient info */
1451 static bool analyse_dialog_shown = false; /* global per instance of Ardour */
1453 if (!Config->get_auto_analyse_audio()) {
1454 if (!analyse_dialog_shown) {
1455 pl->session().Dialog (_("\
1456 You have requested an operation that requires audio analysis.\n\n\
1457 You currently have \"auto-analyse-audio\" disabled, which means \
1458 that transient data must be generated every time it is required.\n\n\
1459 If you are doing work that will require transient data on a \
1460 regular basis, you should probably enable \"auto-analyse-audio\" \
1461 then quit ardour and restart.\n\n\
1462 This dialog will not display again. But you may notice a slight delay \
1463 in this and future transient-detection operations.\n\
1464 "));
1465 analyse_dialog_shown = true;
1469 TransientDetector t (pl->session().frame_rate());
1470 bool existing_results = !results.empty();
1472 _transients.clear ();
1473 _valid_transients = false;
1475 for (uint32_t i = 0; i < n_channels(); ++i) {
1477 AnalysisFeatureList these_results;
1479 t.reset ();
1481 if (t.run ("", this, i, these_results)) {
1482 return -1;
1485 /* translate all transients to give absolute position */
1487 for (AnalysisFeatureList::iterator i = these_results.begin(); i != these_results.end(); ++i) {
1488 (*i) += _position;
1491 /* merge */
1493 _transients.insert (_transients.end(), these_results.begin(), these_results.end());
1496 if (!results.empty()) {
1497 if (existing_results) {
1499 /* merge our transients into the existing ones, then clean up
1500 those.
1503 results.insert (results.end(), _transients.begin(), _transients.end());
1504 TransientDetector::cleanup_transients (results, pl->session().frame_rate(), 3.0);
1507 /* make sure ours are clean too */
1509 TransientDetector::cleanup_transients (_transients, pl->session().frame_rate(), 3.0);
1511 } else {
1513 TransientDetector::cleanup_transients (_transients, pl->session().frame_rate(), 3.0);
1514 results = _transients;
1517 _valid_transients = true;
1519 return 0;
1522 /** Find areas of `silence' within a region.
1524 * @param threshold Threshold below which signal is considered silence (as a sample value)
1525 * @param min_length Minimum length of silent period to be reported.
1526 * @return Silent intervals, measured relative to the region start in the source
1529 AudioIntervalResult
1530 AudioRegion::find_silence (Sample threshold, framecnt_t min_length, InterThreadInfo& itt) const
1532 framecnt_t const block_size = 64 * 1024;
1533 boost::scoped_array<Sample> loudest (new Sample[block_size]);
1534 boost::scoped_array<Sample> buf (new Sample[block_size]);
1536 framepos_t pos = _start;
1537 framepos_t const end = _start + _length - 1;
1539 AudioIntervalResult silent_periods;
1541 bool in_silence = false;
1542 frameoffset_t silence_start = 0;
1544 while (pos < end && !itt.cancel) {
1546 /* fill `loudest' with the loudest absolute sample at each instant, across all channels */
1547 memset (loudest.get(), 0, sizeof (Sample) * block_size);
1548 for (uint32_t n = 0; n < n_channels(); ++n) {
1550 read_raw_internal (buf.get(), pos, block_size, n);
1551 for (framecnt_t i = 0; i < block_size; ++i) {
1552 loudest[i] = max (loudest[i], abs (buf[i]));
1556 /* now look for silence */
1557 for (framecnt_t i = 0; i < block_size; ++i) {
1558 bool const silence = abs (loudest[i]) < threshold;
1559 if (silence && !in_silence) {
1560 /* non-silence to silence */
1561 in_silence = true;
1562 silence_start = pos + i;
1563 } else if (!silence && in_silence) {
1564 /* silence to non-silence */
1565 in_silence = false;
1566 if (pos + i - 1 - silence_start >= min_length) {
1567 silent_periods.push_back (std::make_pair (silence_start, pos + i - 1));
1572 pos += block_size;
1573 itt.progress = (end-pos)/(double)_length;
1576 if (in_silence && end - 1 - silence_start >= min_length) {
1577 /* last block was silent, so finish off the last period */
1578 silent_periods.push_back (std::make_pair (silence_start, end));
1581 itt.done = true;
1583 return silent_periods;
1588 extern "C" {
1590 int region_read_peaks_from_c (void *arg, uint32_t npeaks, uint32_t start, uint32_t cnt, intptr_t data, uint32_t n_chan, double samples_per_unit)
1592 return ((AudioRegion *) arg)->read_peaks ((PeakData *) data, (framecnt_t) npeaks, (framepos_t) start, (framecnt_t) cnt, n_chan,samples_per_unit);
1595 uint32_t region_length_from_c (void *arg)
1598 return ((AudioRegion *) arg)->length();
1601 uint32_t sourcefile_length_from_c (void *arg, double zoom_factor)
1603 return ( (AudioRegion *) arg)->audio_source()->available_peaks (zoom_factor) ;
1606 } /* extern "C" */