new RegionCommand object; remove unused string argument from Region::thaw(); add...
[ardour.git] / libs / ardour / audioregion.cc
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
28 #include <glibmm/thread.h>
29
30 #include "pbd/basename.h"
31 #include "pbd/xml++.h"
32 #include "pbd/stacktrace.h"
33 #include "pbd/enumwriter.h"
34 #include "pbd/convert.h"
35
36 #include "evoral/Curve.hpp"
37
38 #include "ardour/audioregion.h"
39 #include "ardour/session.h"
40 #include "ardour/gain.h"
41 #include "ardour/dB.h"
42 #include "ardour/playlist.h"
43 #include "ardour/audiofilesource.h"
44 #include "ardour/region_factory.h"
45 #include "ardour/runtime_functions.h"
46 #include "ardour/transient_detector.h"
47
48 #include "i18n.h"
49 #include <locale.h>
50
51 using namespace std;
52 using namespace ARDOUR;
53 using namespace PBD;
54
55 /* a Session will reset these to its chosen defaults by calling AudioRegion::set_default_fade() */
56
57 Change AudioRegion::FadeInChanged         = ARDOUR::new_change();
58 Change AudioRegion::FadeOutChanged        = ARDOUR::new_change();
59 Change AudioRegion::FadeInActiveChanged   = ARDOUR::new_change();
60 Change AudioRegion::FadeOutActiveChanged  = ARDOUR::new_change();
61 Change AudioRegion::EnvelopeActiveChanged = ARDOUR::new_change();
62 Change AudioRegion::ScaleAmplitudeChanged = ARDOUR::new_change();
63 Change AudioRegion::EnvelopeChanged       = ARDOUR::new_change();
64
65 void
66 AudioRegion::init ()
67 {
68         _scale_amplitude = 1.0;
69
70         set_default_fades ();
71         set_default_envelope ();
72
73         listen_to_my_curves ();
74         connect_to_analysis_changed ();
75 }
76
77 /** Constructor for use by derived types only */
78 AudioRegion::AudioRegion (Session& s, nframes_t start, nframes_t length, string name)
79         : Region (s, start, length, name, DataType::AUDIO)
80         , _automatable(s)
81         , _fade_in (new AutomationList(Evoral::Parameter(FadeInAutomation)))
82         , _fade_out (new AutomationList(Evoral::Parameter(FadeOutAutomation)))
83         , _envelope (new AutomationList(Evoral::Parameter(EnvelopeAutomation)))
84 {
85         init ();
86         assert (_sources.size() == _master_sources.size());
87 }
88
89 /** Basic AudioRegion constructor (one channel) */
90 AudioRegion::AudioRegion (boost::shared_ptr<AudioSource> src, nframes_t start, nframes_t length)
91         : Region (src, start, length, PBD::basename_nosuffix(src->name()), DataType::AUDIO, 0,  Region::Flag(Region::DefaultFlags|Region::External))
92         , _automatable(src->session())
93         , _fade_in (new AutomationList(Evoral::Parameter(FadeInAutomation)))
94         , _fade_out (new AutomationList(Evoral::Parameter(FadeOutAutomation)))
95         , _envelope (new AutomationList(Evoral::Parameter(EnvelopeAutomation)))
96 {
97         boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (src);
98         if (afs) {
99                 afs->HeaderPositionOffsetChanged.connect_same_thread (*this, boost::bind (&AudioRegion::source_offset_changed, this));
100         }
101
102         init ();
103         assert (_sources.size() == _master_sources.size());
104 }
105
106 /* Basic AudioRegion constructor (one channel) */
107 AudioRegion::AudioRegion (boost::shared_ptr<AudioSource> src, nframes_t start, nframes_t length, const string& name, layer_t layer, Flag flags)
108         : Region (src, start, length, name, DataType::AUDIO, layer, flags)
109         , _automatable(src->session())
110         , _fade_in (new AutomationList(Evoral::Parameter(FadeInAutomation)))
111         , _fade_out (new AutomationList(Evoral::Parameter(FadeOutAutomation)))
112         , _envelope (new AutomationList(Evoral::Parameter(EnvelopeAutomation)))
113 {
114         boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (src);
115         if (afs) {
116                 afs->HeaderPositionOffsetChanged.connect_same_thread (*this, boost::bind (&AudioRegion::source_offset_changed, this));
117         }
118
119         init ();
120         assert (_sources.size() == _master_sources.size());
121 }
122
123 /** Basic AudioRegion constructor (many channels) */
124 AudioRegion::AudioRegion (const SourceList& srcs, nframes_t start, nframes_t length, const string& name, layer_t layer, Flag flags)
125         : Region (srcs, start, length, name, DataType::AUDIO, layer, flags)
126         , _automatable(srcs[0]->session())
127         , _fade_in (new AutomationList(Evoral::Parameter(FadeInAutomation)))
128         , _fade_out (new AutomationList(Evoral::Parameter(FadeOutAutomation)))
129         , _envelope (new AutomationList(Evoral::Parameter(EnvelopeAutomation)))
130 {
131         init ();
132         connect_to_analysis_changed ();
133         assert (_sources.size() == _master_sources.size());
134 }
135
136 /** Create a new AudioRegion, that is part of an existing one */
137 AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other, nframes_t offset, nframes_t length, const string& name, layer_t layer, Flag flags)
138         : Region (other, offset, length, name, layer, flags)
139         , _automatable(other->session())
140         , _fade_in (new AutomationList(*other->_fade_in))
141         , _fade_out (new AutomationList(*other->_fade_out))
142         , _envelope (new AutomationList(*other->_envelope, offset, offset + length))
143 {
144         connect_to_header_position_offset_changed ();
145
146         /* return to default fades if the existing ones are too long */
147
148         if (_flags & LeftOfSplit) {
149                 if (_fade_in->back()->when >= _length) {
150                         set_default_fade_in ();
151                 } else {
152                         _fade_in_disabled = other->_fade_in_disabled;
153                 }
154                 set_default_fade_out ();
155                 _flags = Flag (_flags & ~Region::LeftOfSplit);
156         }
157
158         if (_flags & RightOfSplit) {
159                 if (_fade_out->back()->when >= _length) {
160                         set_default_fade_out ();
161                 } else {
162                         _fade_out_disabled = other->_fade_out_disabled;
163                 }
164                 set_default_fade_in ();
165                 _flags = Flag (_flags & ~Region::RightOfSplit);
166         }
167
168         _scale_amplitude = other->_scale_amplitude;
169
170         assert(_type == DataType::AUDIO);
171
172         listen_to_my_curves ();
173         connect_to_analysis_changed ();
174
175         assert (_sources.size() == _master_sources.size());
176 }
177
178 AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other)
179         : Region (other)
180         , _automatable (other->session())
181         , _fade_in (new AutomationList (*other->_fade_in))
182         , _fade_out (new AutomationList (*other->_fade_out))
183         , _envelope (new AutomationList (*other->_envelope))
184 {
185         assert(_type == DataType::AUDIO);
186         _scale_amplitude = other->_scale_amplitude;
187
188         listen_to_my_curves ();
189         connect_to_analysis_changed ();
190
191         assert (_sources.size() == _master_sources.size());
192 }
193
194 AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other, const SourceList& /*srcs*/,
195                           nframes_t length, const string& name, layer_t layer, Flag flags)
196         : Region (other, length, name, layer, flags)
197         , _automatable (other->session())
198         , _fade_in (new AutomationList (*other->_fade_in))
199         , _fade_out (new AutomationList (*other->_fade_out))
200         , _envelope (new AutomationList (*other->_envelope))
201 {
202         /* make-a-sort-of-copy-with-different-sources constructor (used by audio filter) */
203
204         for (SourceList::const_iterator i = _sources.begin(); i != _sources.end(); ++i) {
205
206                 boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> ((*i));
207                 if (afs) {
208                         afs->HeaderPositionOffsetChanged.connect_same_thread (*this, boost::bind (&AudioRegion::source_offset_changed, this));
209                 }
210         }
211
212         _scale_amplitude = other->_scale_amplitude;
213
214         _fade_in_disabled = 0;
215         _fade_out_disabled = 0;
216
217         listen_to_my_curves ();
218         connect_to_analysis_changed ();
219
220         assert (_sources.size() == _master_sources.size());
221 }
222
223 AudioRegion::AudioRegion (boost::shared_ptr<AudioSource> src, const XMLNode& node)
224         : Region (src, node)
225         , _automatable(src->session())
226         , _fade_in (new AutomationList(Evoral::Parameter(FadeInAutomation)))
227         , _fade_out (new AutomationList(Evoral::Parameter(FadeOutAutomation)))
228         , _envelope (new AutomationList(Evoral::Parameter(EnvelopeAutomation)))
229 {
230         boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (src);
231         if (afs) {
232                 afs->HeaderPositionOffsetChanged.connect_same_thread (*this, boost::bind (&AudioRegion::source_offset_changed, this));
233         }
234
235         init ();
236
237         if (set_state (node, Stateful::loading_state_version)) {
238                 throw failed_constructor();
239         }
240
241         assert(_type == DataType::AUDIO);
242         connect_to_analysis_changed ();
243
244         assert (_sources.size() == _master_sources.size());
245 }
246
247 AudioRegion::AudioRegion (SourceList& srcs, const XMLNode& node)
248         : Region (srcs, node)
249         , _automatable(srcs[0]->session())
250         , _fade_in (new AutomationList(Evoral::Parameter(FadeInAutomation)))
251         , _fade_out (new AutomationList(Evoral::Parameter(FadeOutAutomation)))
252         , _envelope (new AutomationList(Evoral::Parameter(EnvelopeAutomation)))
253 {
254         init ();
255
256         if (set_state (node, Stateful::loading_state_version)) {
257                 throw failed_constructor();
258         }
259
260         assert(_type == DataType::AUDIO);
261         connect_to_analysis_changed ();
262         assert (_sources.size() == _master_sources.size());
263 }
264
265 AudioRegion::~AudioRegion ()
266 {
267 }
268
269 void
270 AudioRegion::connect_to_analysis_changed ()
271 {
272         for (SourceList::const_iterator i = _sources.begin(); i != _sources.end(); ++i) {
273                 (*i)->AnalysisChanged.connect_same_thread (*this, boost::bind (&AudioRegion::invalidate_transients, this));
274         }
275 }
276
277 void
278 AudioRegion::connect_to_header_position_offset_changed ()
279 {
280         set<boost::shared_ptr<Source> > unique_srcs;
281
282         for (SourceList::const_iterator i = _sources.begin(); i != _sources.end(); ++i) {
283
284                 if (unique_srcs.find (*i) == unique_srcs.end ()) {
285                         unique_srcs.insert (*i);
286                         boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (*i);
287                         if (afs) {
288                                 afs->HeaderPositionOffsetChanged.connect_same_thread (*this, boost::bind (&AudioRegion::source_offset_changed, this));
289                         }
290                 }
291         }
292 }
293
294 void
295 AudioRegion::listen_to_my_curves ()
296 {
297         cerr << _name << ": listeing my own curves\n";
298
299         _envelope->StateChanged.connect_same_thread (*this, boost::bind (&AudioRegion::envelope_changed, this));
300         _fade_in->StateChanged.connect_same_thread (*this, boost::bind (&AudioRegion::fade_in_changed, this));
301         _fade_out->StateChanged.connect_same_thread (*this, boost::bind (&AudioRegion::fade_out_changed, this));
302 }
303
304 void
305 AudioRegion::set_envelope_active (bool yn)
306 {
307         if (envelope_active() != yn) {
308                 char buf[64];
309                 if (yn) {
310                         snprintf (buf, sizeof (buf), "envelope active");
311                         _flags = Flag (_flags|EnvelopeActive);
312                 } else {
313                         snprintf (buf, sizeof (buf), "envelope off");
314                         _flags = Flag (_flags & ~EnvelopeActive);
315                 }
316                 send_change (EnvelopeActiveChanged);
317         }
318 }
319
320 ARDOUR::nframes_t
321 AudioRegion::read_peaks (PeakData *buf, nframes_t npeaks, nframes_t offset, nframes_t cnt, uint32_t chan_n, double samples_per_unit) const
322 {
323         if (chan_n >= _sources.size()) {
324                 return 0;
325         }
326
327         if (audio_source(chan_n)->read_peaks (buf, npeaks, offset, cnt, samples_per_unit)) {
328                 return 0;
329         } else {
330                 if (_scale_amplitude != 1.0) {
331                         for (nframes_t n = 0; n < npeaks; ++n) {
332                                 buf[n].max *= _scale_amplitude;
333                                 buf[n].min *= _scale_amplitude;
334                         }
335                 }
336                 return cnt;
337         }
338 }
339
340 nframes_t
341 AudioRegion::read (Sample* buf, sframes_t timeline_position, nframes_t cnt, int channel) const
342 {
343         /* raw read, no fades, no gain, nada */
344         return _read_at (_sources, _length, buf, 0, 0, _position + timeline_position, cnt, channel, 0, 0, ReadOps (0));
345 }
346
347 nframes_t
348 AudioRegion::read_with_ops (Sample* buf, sframes_t file_position, nframes_t cnt, int channel, ReadOps rops) const
349 {
350         return _read_at (_sources, _length, buf, 0, 0, file_position, cnt, channel, 0, 0, rops);
351 }
352
353 nframes_t
354 AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer,
355                 sframes_t file_position, nframes_t cnt, uint32_t chan_n,
356                 nframes_t read_frames, nframes_t skip_frames) const
357 {
358         /* regular diskstream/butler read complete with fades etc */
359         return _read_at (_sources, _length, buf, mixdown_buffer, gain_buffer,
360                         file_position, cnt, chan_n, read_frames, skip_frames, ReadOps (~0));
361 }
362
363 nframes_t
364 AudioRegion::master_read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer,
365                 sframes_t position, nframes_t cnt, uint32_t chan_n) const
366 {
367         /* do not read gain/scaling/fades and do not count this disk i/o in statistics */
368
369         return _read_at (_master_sources, _master_sources.front()->length(_master_sources.front()->timeline_position()),
370                          buf, mixdown_buffer, gain_buffer, position, cnt, chan_n, 0, 0, ReadOps (0));
371 }
372
373 nframes_t
374 AudioRegion::_read_at (const SourceList& /*srcs*/, nframes_t limit,
375                 Sample *buf, Sample *mixdown_buffer, float *gain_buffer,
376                 sframes_t position, nframes_t cnt,
377                 uint32_t chan_n,
378                 nframes_t /*read_frames*/,
379                 nframes_t /*skip_frames*/,
380                 ReadOps rops) const
381 {
382         nframes_t internal_offset;
383         nframes_t buf_offset;
384         nframes_t to_read;
385         bool raw = (rops == ReadOpsNone);
386
387         if (muted() && !raw) {
388                 return 0; /* read nothing */
389         }
390
391         /* precondition: caller has verified that we cover the desired section */
392
393         if (position < _position) {
394                 internal_offset = 0;
395                 buf_offset = _position - position;
396                 cnt -= buf_offset;
397         } else {
398                 internal_offset = position - _position;
399                 buf_offset = 0;
400         }
401
402         if (internal_offset >= limit) {
403                 return 0; /* read nothing */
404         }
405
406         if ((to_read = min (cnt, limit - internal_offset)) == 0) {
407                 return 0; /* read nothing */
408         }
409
410         if (opaque() || raw) {
411                 /* overwrite whatever is there */
412                 mixdown_buffer = buf + buf_offset;
413         } else {
414                 mixdown_buffer += buf_offset;
415         }
416
417         if (rops & ReadOpsCount) {
418                 _read_data_count = 0;
419         }
420
421         if (chan_n < n_channels()) {
422
423                 boost::shared_ptr<AudioSource> src = audio_source(chan_n);
424                 if (src->read (mixdown_buffer, _start + internal_offset, to_read) != to_read) {
425                         return 0; /* "read nothing" */
426                 }
427
428                 if (rops & ReadOpsCount) {
429                         _read_data_count += src->read_data_count();
430                 }
431
432         } else {
433
434                 /* track is N-channel, this region has less channels; silence the ones
435                    we don't have.
436                 */
437
438                 memset (mixdown_buffer, 0, sizeof (Sample) * cnt);
439         }
440
441         if (rops & ReadOpsFades) {
442
443                 /* fade in */
444
445                 if ((_flags & FadeIn) && _session.config.get_use_region_fades()) {
446
447                         nframes_t fade_in_length = (nframes_t) _fade_in->back()->when;
448
449                         /* see if this read is within the fade in */
450
451                         if (internal_offset < fade_in_length) {
452
453                                 nframes_t fi_limit;
454
455                                 fi_limit = min (to_read, fade_in_length - internal_offset);
456
457
458                                 _fade_in->curve().get_vector (internal_offset, internal_offset+fi_limit, gain_buffer, fi_limit);
459
460                                 for (nframes_t n = 0; n < fi_limit; ++n) {
461                                         mixdown_buffer[n] *= gain_buffer[n];
462                                 }
463                         }
464                 }
465
466                 /* fade out */
467
468                 if ((_flags & FadeOut) && _session.config.get_use_region_fades()) {
469
470                         /* see if some part of this read is within the fade out */
471
472                 /* .................        >|            REGION
473                                              limit
474
475                                  {           }            FADE
476                                              fade_out_length
477                                  ^
478                                  limit - fade_out_length
479                         |--------------|
480                         ^internal_offset
481                                        ^internal_offset + to_read
482
483                                        we need the intersection of [internal_offset,internal_offset+to_read] with
484                                        [limit - fade_out_length, limit]
485
486                 */
487
488
489                         nframes_t fade_out_length = (nframes_t) _fade_out->back()->when;
490                         nframes_t fade_interval_start = max(internal_offset, limit-fade_out_length);
491                         nframes_t fade_interval_end   = min(internal_offset + to_read, limit);
492
493                         if (fade_interval_end > fade_interval_start) {
494                                 /* (part of the) the fade out is  in this buffer */
495
496                                 nframes_t fo_limit = fade_interval_end - fade_interval_start;
497                                 nframes_t curve_offset = fade_interval_start - (limit-fade_out_length);
498                                 nframes_t fade_offset = fade_interval_start - internal_offset;
499
500                                 _fade_out->curve().get_vector (curve_offset, curve_offset+fo_limit, gain_buffer, fo_limit);
501
502                                 for (nframes_t n = 0, m = fade_offset; n < fo_limit; ++n, ++m) {
503                                         mixdown_buffer[m] *= gain_buffer[n];
504                                 }
505                         }
506
507                 }
508         }
509
510         /* Regular gain curves and scaling */
511
512         if ((rops & ReadOpsOwnAutomation) && envelope_active())  {
513                 _envelope->curve().get_vector (internal_offset, internal_offset + to_read, gain_buffer, to_read);
514
515                 if ((rops & ReadOpsOwnScaling) && _scale_amplitude != 1.0f) {
516                         for (nframes_t n = 0; n < to_read; ++n) {
517                                 mixdown_buffer[n] *= gain_buffer[n] * _scale_amplitude;
518                         }
519                 } else {
520                         for (nframes_t n = 0; n < to_read; ++n) {
521                                 mixdown_buffer[n] *= gain_buffer[n];
522                         }
523                 }
524         } else if ((rops & ReadOpsOwnScaling) && _scale_amplitude != 1.0f) {
525
526                 // XXX this should be using what in 2.0 would have been:
527                 // Session::apply_gain_to_buffer (mixdown_buffer, to_read, _scale_amplitude);
528
529                 for (nframes_t n = 0; n < to_read; ++n) {
530                         mixdown_buffer[n] *= _scale_amplitude;
531                 }
532         }
533
534         if (!opaque()) {
535
536                 /* gack. the things we do for users.
537                  */
538
539                 buf += buf_offset;
540
541                 for (nframes_t n = 0; n < to_read; ++n) {
542                         buf[n] += mixdown_buffer[n];
543                 }
544         }
545
546         return to_read;
547 }
548
549 XMLNode&
550 AudioRegion::state (bool full)
551 {
552         XMLNode& node (Region::state (full));
553         XMLNode *child;
554         char buf[64];
555         char buf2[64];
556         LocaleGuard lg (X_("POSIX"));
557
558         node.add_property ("flags", enum_2_string (_flags));
559
560         snprintf (buf, sizeof(buf), "%.12g", _scale_amplitude);
561         node.add_property ("scale-gain", buf);
562
563         // XXX these should move into Region
564
565         for (uint32_t n=0; n < _sources.size(); ++n) {
566                 snprintf (buf2, sizeof(buf2), "source-%d", n);
567                 _sources[n]->id().print (buf, sizeof (buf));
568                 node.add_property (buf2, buf);
569         }
570
571         for (uint32_t n=0; n < _master_sources.size(); ++n) {
572                 snprintf (buf2, sizeof(buf2), "master-source-%d", n);
573                 _master_sources[n]->id().print (buf, sizeof (buf));
574                 node.add_property (buf2, buf);
575         }
576
577         snprintf (buf, sizeof (buf), "%u", (uint32_t) _sources.size());
578         node.add_property ("channels", buf);
579
580         if (full) {
581
582                 child = node.add_child (X_("FadeIn"));
583
584                 if ((_flags & DefaultFadeIn)) {
585                         child->add_property (X_("default"), X_("yes"));
586                 } else {
587                         child->add_child_nocopy (_fade_in->get_state ());
588                 }
589
590                 child->add_property (X_("active"), fade_in_active () ? X_("yes") : X_("no"));
591
592                 child = node.add_child (X_("FadeOut"));
593
594                 if ((_flags & DefaultFadeOut)) {
595                         child->add_property (X_("default"), X_("yes"));
596                 } else {
597                         child->add_child_nocopy (_fade_out->get_state ());
598                 }
599
600                 child->add_property (X_("active"), fade_out_active () ? X_("yes") : X_("no"));
601         }
602
603         child = node.add_child ("Envelope");
604
605         if (full) {
606                 bool default_env = false;
607
608                 // If there are only two points, the points are in the start of the region and the end of the region
609                 // so, if they are both at 1.0f, that means the default region.
610
611                 if (_envelope->size() == 2 &&
612                     _envelope->front()->value == 1.0f &&
613                     _envelope->back()->value==1.0f) {
614                         if (_envelope->front()->when == 0 && _envelope->back()->when == _length) {
615                                 default_env = true;
616                         }
617                 }
618
619                 if (default_env) {
620                         child->add_property ("default", "yes");
621                 } else {
622                         child->add_child_nocopy (_envelope->get_state ());
623                 }
624
625         } else {
626                 child->add_property ("default", "yes");
627         }
628
629         if (full && _extra_xml) {
630                 node.add_child_copy (*_extra_xml);
631         }
632
633         return node;
634 }
635
636 int
637 AudioRegion::set_live_state (const XMLNode& node, int version, Change& what_changed, bool send)
638 {
639         const XMLNodeList& nlist = node.children();
640         const XMLProperty *prop;
641         LocaleGuard lg (X_("POSIX"));
642         boost::shared_ptr<Playlist> the_playlist (_playlist.lock());    
643
644         freeze ();
645         if (the_playlist) {
646                 the_playlist->freeze ();
647         }
648
649         Region::set_live_state (node, version, what_changed, false);
650         cerr << "After region SLS, wc = " << what_changed << endl;
651
652         uint32_t old_flags = _flags;
653
654         if ((prop = node.property ("flags")) != 0) {
655                 _flags = Flag (string_2_enum (prop->value(), _flags));
656
657                 //_flags = Flag (strtol (prop->value().c_str(), (char **) 0, 16));
658
659                 _flags = Flag (_flags & ~Region::LeftOfSplit);
660                 _flags = Flag (_flags & ~Region::RightOfSplit);
661         }
662
663         /* leave this flag setting in place, no matter what */
664
665         if ((old_flags & DoNotSendPropertyChanges)) {
666                 _flags = Flag (_flags | DoNotSendPropertyChanges);
667         }
668
669         /* find out if any flags changed that we signal about */
670
671         if ((old_flags ^ _flags) & Muted) {
672                 what_changed = Change (what_changed|MuteChanged);
673                 cerr << _name << " mute changed\n";
674         }
675         if ((old_flags ^ _flags) & Opaque) {
676                 what_changed = Change (what_changed|OpacityChanged);
677                 cerr << _name << " opacity changed\n";
678         }
679         if ((old_flags ^ _flags) & Locked) {
680                 what_changed = Change (what_changed|LockChanged);
681                 cerr << _name << " lock changed\n";
682         }
683
684         if ((prop = node.property ("scale-gain")) != 0) {
685                 float a = atof (prop->value().c_str());
686                 if (a != _scale_amplitude) {
687                         _scale_amplitude = a;
688                         what_changed = Change (what_changed|ScaleAmplitudeChanged);
689                         cerr << _name << " amp changed\n";
690                 }
691         } else {
692                 _scale_amplitude = 1.0;
693         }
694
695         /* Now find envelope description and other misc child items */
696
697         _envelope->freeze ();
698
699         for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
700
701                 XMLNode *child;
702                 XMLProperty *prop;
703
704                 child = (*niter);
705
706 #if 0
707                 if (child->name() == "Envelope") {
708
709                         _envelope->clear ();
710
711                         if ((prop = child->property ("default")) != 0 || _envelope->set_state (*child, version)) {
712                                 set_default_envelope ();
713                         }
714
715                         _envelope->set_max_xval (_length);
716                         _envelope->truncate_end (_length);
717
718                         cerr << _name << " envelope changd\n";
719                 
720
721                 } else if (child->name() == "FadeIn") {
722
723                         _fade_in->clear ();
724
725                         if ((prop = child->property ("default")) != 0 || (prop = child->property ("steepness")) != 0) {
726                                 set_default_fade_in ();
727                         } else {
728                                 XMLNode* grandchild = child->child ("AutomationList");
729                                 if (grandchild) {
730                                         _fade_in->set_state (*grandchild, version);
731                                 }
732                         }
733
734                         if ((prop = child->property ("active")) != 0) {
735                                 if (string_is_affirmative (prop->value())) {
736                                         set_fade_in_active (true);
737                                 } else {
738                                         set_fade_in_active (false);
739                                 }
740                         }
741                         cerr << _name << " fadein changd\n";
742
743                 } else if (child->name() == "FadeOut") {
744
745                         _fade_out->clear ();
746
747                         if ((prop = child->property ("default")) != 0 || (prop = child->property ("steepness")) != 0) {
748                                 set_default_fade_out ();
749                         } else {
750                                 XMLNode* grandchild = child->child ("AutomationList");
751                                 if (grandchild) {
752                                         _fade_out->set_state (*grandchild, version);
753                                 }
754                         }
755
756                         if ((prop = child->property ("active")) != 0) {
757                                 if (string_is_affirmative (prop->value())) {
758                                         set_fade_out_active (true);
759                                 } else {
760                                         set_fade_out_active (false);
761                                 }
762                         }
763                         cerr << _name << " fadeout changd\n";
764
765                 }
766 #endif
767         }
768
769         _envelope->thaw ();
770         thaw ();
771
772         if (send) {
773                 cerr << _name << ": audio final change: " << hex << what_changed << dec << endl;
774                 send_change (what_changed);
775         }
776
777         if (the_playlist) {
778                 the_playlist->thaw ();
779         }
780
781         return 0;
782 }
783
784 int
785 AudioRegion::set_state (const XMLNode& node, int version)
786 {
787         /* Region::set_state() calls the virtual set_live_state(),
788            which will get us back to AudioRegion::set_live_state()
789            to handle the relevant stuff.
790         */
791
792         return Region::set_state (node, version);
793 }
794
795 void
796 AudioRegion::set_fade_in_shape (FadeShape shape)
797 {
798         set_fade_in (shape, (nframes_t) _fade_in->back()->when);
799 }
800
801 void
802 AudioRegion::set_fade_out_shape (FadeShape shape)
803 {
804         set_fade_out (shape, (nframes_t) _fade_out->back()->when);
805 }
806
807 void
808 AudioRegion::set_fade_in (boost::shared_ptr<AutomationList> f)
809 {
810         _fade_in->freeze ();
811         *_fade_in = *f;
812         _fade_in->thaw ();
813         
814         send_change (FadeInChanged);
815 }
816
817 void
818 AudioRegion::set_fade_in (FadeShape shape, nframes_t len)
819 {
820         _fade_in->freeze ();
821         _fade_in->clear ();
822
823         switch (shape) {
824         case Linear:
825                 _fade_in->fast_simple_add (0.0, 0.0);
826                 _fade_in->fast_simple_add (len, 1.0);
827                 break;
828
829         case Fast:
830                 _fade_in->fast_simple_add (0, 0);
831                 _fade_in->fast_simple_add (len * 0.389401, 0.0333333);
832                 _fade_in->fast_simple_add (len * 0.629032, 0.0861111);
833                 _fade_in->fast_simple_add (len * 0.829493, 0.233333);
834                 _fade_in->fast_simple_add (len * 0.9447, 0.483333);
835                 _fade_in->fast_simple_add (len * 0.976959, 0.697222);
836                 _fade_in->fast_simple_add (len, 1);
837                 break;
838
839         case Slow:
840                 _fade_in->fast_simple_add (0, 0);
841                 _fade_in->fast_simple_add (len * 0.0207373, 0.197222);
842                 _fade_in->fast_simple_add (len * 0.0645161, 0.525);
843                 _fade_in->fast_simple_add (len * 0.152074, 0.802778);
844                 _fade_in->fast_simple_add (len * 0.276498, 0.919444);
845                 _fade_in->fast_simple_add (len * 0.481567, 0.980556);
846                 _fade_in->fast_simple_add (len * 0.767281, 1);
847                 _fade_in->fast_simple_add (len, 1);
848                 break;
849
850         case LogA:
851                 _fade_in->fast_simple_add (0, 0);
852                 _fade_in->fast_simple_add (len * 0.0737327, 0.308333);
853                 _fade_in->fast_simple_add (len * 0.246544, 0.658333);
854                 _fade_in->fast_simple_add (len * 0.470046, 0.886111);
855                 _fade_in->fast_simple_add (len * 0.652074, 0.972222);
856                 _fade_in->fast_simple_add (len * 0.771889, 0.988889);
857                 _fade_in->fast_simple_add (len, 1);
858                 break;
859
860         case LogB:
861                 _fade_in->fast_simple_add (0, 0);
862                 _fade_in->fast_simple_add (len * 0.304147, 0.0694444);
863                 _fade_in->fast_simple_add (len * 0.529954, 0.152778);
864                 _fade_in->fast_simple_add (len * 0.725806, 0.333333);
865                 _fade_in->fast_simple_add (len * 0.847926, 0.558333);
866                 _fade_in->fast_simple_add (len * 0.919355, 0.730556);
867                 _fade_in->fast_simple_add (len, 1);
868                 break;
869         }
870
871         _fade_in->thaw ();
872 }
873
874 void
875 AudioRegion::set_fade_out (boost::shared_ptr<AutomationList> f)
876 {
877         _fade_out->freeze ();
878         *_fade_out = *f;
879         _fade_out->thaw ();
880
881         send_change (FadeInChanged);
882 }
883
884 void
885 AudioRegion::set_fade_out (FadeShape shape, nframes_t len)
886 {
887         _fade_out->freeze ();
888         _fade_out->clear ();
889
890         switch (shape) {
891         case Fast:
892                 _fade_out->fast_simple_add (len * 0, 1);
893                 _fade_out->fast_simple_add (len * 0.023041, 0.697222);
894                 _fade_out->fast_simple_add (len * 0.0553,   0.483333);
895                 _fade_out->fast_simple_add (len * 0.170507, 0.233333);
896                 _fade_out->fast_simple_add (len * 0.370968, 0.0861111);
897                 _fade_out->fast_simple_add (len * 0.610599, 0.0333333);
898                 _fade_out->fast_simple_add (len * 1, 0);
899                 break;
900
901         case LogA:
902                 _fade_out->fast_simple_add (len * 0, 1);
903                 _fade_out->fast_simple_add (len * 0.228111, 0.988889);
904                 _fade_out->fast_simple_add (len * 0.347926, 0.972222);
905                 _fade_out->fast_simple_add (len * 0.529954, 0.886111);
906                 _fade_out->fast_simple_add (len * 0.753456, 0.658333);
907                 _fade_out->fast_simple_add (len * 0.9262673, 0.308333);
908                 _fade_out->fast_simple_add (len * 1, 0);
909                 break;
910
911         case Slow:
912                 _fade_out->fast_simple_add (len * 0, 1);
913                 _fade_out->fast_simple_add (len * 0.305556, 1);
914                 _fade_out->fast_simple_add (len * 0.548611, 0.991736);
915                 _fade_out->fast_simple_add (len * 0.759259, 0.931129);
916                 _fade_out->fast_simple_add (len * 0.918981, 0.68595);
917                 _fade_out->fast_simple_add (len * 0.976852, 0.22865);
918                 _fade_out->fast_simple_add (len * 1, 0);
919                 break;
920
921         case LogB:
922                 _fade_out->fast_simple_add (len * 0, 1);
923                 _fade_out->fast_simple_add (len * 0.080645, 0.730556);
924                 _fade_out->fast_simple_add (len * 0.277778, 0.289256);
925                 _fade_out->fast_simple_add (len * 0.470046, 0.152778);
926                 _fade_out->fast_simple_add (len * 0.695853, 0.0694444);
927                 _fade_out->fast_simple_add (len * 1, 0);
928                 break;
929
930         case Linear:
931                 _fade_out->fast_simple_add (len * 0, 1);
932                 _fade_out->fast_simple_add (len * 1, 0);
933                 break;
934         }
935
936         _fade_out->thaw ();
937 }
938
939 void
940 AudioRegion::set_fade_in_length (nframes_t len)
941 {
942         if (len > _length) {
943                 len = _length - 1;
944         }
945
946         bool changed = _fade_in->extend_to (len);
947
948         if (changed) {
949                 _flags = Flag (_flags & ~DefaultFadeIn);
950                 send_change (FadeInChanged);
951         }
952 }
953
954 void
955 AudioRegion::set_fade_out_length (nframes_t len)
956 {
957         if (len > _length) {
958                 len = _length - 1;
959         }
960
961         bool changed =  _fade_out->extend_to (len);
962
963         if (changed) {
964                 _flags = Flag (_flags & ~DefaultFadeOut);
965                 send_change (FadeOutChanged);
966         }
967 }
968
969 void
970 AudioRegion::set_fade_in_active (bool yn)
971 {
972         if (yn == (_flags & FadeIn)) {
973                 return;
974         }
975         if (yn) {
976                 _flags = Flag (_flags|FadeIn);
977         } else {
978                 _flags = Flag (_flags & ~FadeIn);
979         }
980
981         send_change (FadeInActiveChanged);
982 }
983
984 void
985 AudioRegion::set_fade_out_active (bool yn)
986 {
987         if (yn == (_flags & FadeOut)) {
988                 return;
989         }
990         if (yn) {
991                 _flags = Flag (_flags | FadeOut);
992         } else {
993                 _flags = Flag (_flags & ~FadeOut);
994         }
995
996         send_change (FadeOutActiveChanged);
997 }
998
999 bool
1000 AudioRegion::fade_in_is_default () const
1001 {
1002         return _fade_in->size() == 2 && _fade_in->front()->when == 0 && _fade_in->back()->when == 64;
1003 }
1004
1005 bool
1006 AudioRegion::fade_out_is_default () const
1007 {
1008         return _fade_out->size() == 2 && _fade_out->front()->when == 0 && _fade_out->back()->when == 64;
1009 }
1010
1011 void
1012 AudioRegion::set_default_fade_in ()
1013 {
1014         _fade_in_disabled = 0;
1015         set_fade_in (Linear, 64);
1016 }
1017
1018 void
1019 AudioRegion::set_default_fade_out ()
1020 {
1021         _fade_out_disabled = 0;
1022         set_fade_out (Linear, 64);
1023 }
1024
1025 void
1026 AudioRegion::set_default_fades ()
1027 {
1028         set_default_fade_in ();
1029         set_default_fade_out ();
1030 }
1031
1032 void
1033 AudioRegion::set_default_envelope ()
1034 {
1035         _envelope->freeze ();
1036         _envelope->clear ();
1037         _envelope->fast_simple_add (0, 1.0f);
1038         _envelope->fast_simple_add (_length, 1.0f);
1039         _envelope->thaw ();
1040 }
1041
1042 void
1043 AudioRegion::recompute_at_end ()
1044 {
1045         /* our length has changed. recompute a new final point by interpolating
1046            based on the the existing curve.
1047         */
1048
1049         _envelope->freeze ();
1050         _envelope->truncate_end (_length);
1051         _envelope->set_max_xval (_length);
1052         _envelope->thaw ();
1053
1054         if (_fade_in->back()->when > _length) {
1055                 _fade_in->extend_to (_length);
1056                 send_change (FadeInChanged);
1057         }
1058
1059         if (_fade_out->back()->when > _length) {
1060                 _fade_out->extend_to (_length);
1061                 send_change (FadeOutChanged);
1062         }
1063 }
1064
1065 void
1066 AudioRegion::recompute_at_start ()
1067 {
1068         /* as above, but the shift was from the front */
1069
1070         _envelope->truncate_start (_length);
1071
1072         if (_fade_in->back()->when > _length) {
1073                 _fade_in->extend_to (_length);
1074                 send_change (FadeInChanged);
1075         }
1076
1077         if (_fade_out->back()->when > _length) {
1078                 _fade_out->extend_to (_length);
1079                 send_change (FadeOutChanged);
1080         }
1081 }
1082
1083 int
1084 AudioRegion::separate_by_channel (Session& /*session*/, vector<boost::shared_ptr<Region> >& v) const
1085 {
1086         SourceList srcs;
1087         string new_name;
1088         int n = 0;
1089
1090         if (_sources.size() < 2) {
1091                 return 0;
1092         }
1093
1094         for (SourceList::const_iterator i = _sources.begin(); i != _sources.end(); ++i) {
1095                 srcs.clear ();
1096                 srcs.push_back (*i);
1097
1098                 new_name = _name;
1099
1100                 if (_sources.size() == 2) {
1101                         if (n == 0) {
1102                                 new_name += "-L";
1103                         } else {
1104                                 new_name += "-R";
1105                         }
1106                 } else {
1107                         new_name += '-';
1108                         new_name += ('0' + n + 1);
1109                 }
1110
1111                 /* create a copy with just one source. prevent if from being thought of as
1112                    "whole file" even if it covers the entire source file(s).
1113                  */
1114
1115                 Flag f = Flag (_flags & ~WholeFile);
1116
1117                 v.push_back(RegionFactory::create (srcs, _start, _length, new_name, _layer, f));
1118
1119                 ++n;
1120         }
1121
1122         return 0;
1123 }
1124
1125 nframes_t
1126 AudioRegion::read_raw_internal (Sample* buf, sframes_t pos, nframes_t cnt, int channel) const
1127 {
1128         return audio_source()->read (buf, pos, cnt, channel);
1129 }
1130
1131 int
1132 AudioRegion::exportme (Session& /*session*/, ARDOUR::ExportSpecification& /*spec*/)
1133 {
1134         // TODO EXPORT
1135 //      const nframes_t blocksize = 4096;
1136 //      nframes_t to_read;
1137 //      int status = -1;
1138 //
1139 //      spec.channels = _sources.size();
1140 //
1141 //      if (spec.prepare (blocksize, session.frame_rate())) {
1142 //              goto out;
1143 //      }
1144 //
1145 //      spec.pos = 0;
1146 //      spec.total_frames = _length;
1147 //
1148 //      while (spec.pos < _length && !spec.stop) {
1149 //
1150 //
1151 //              /* step 1: interleave */
1152 //
1153 //              to_read = min (_length - spec.pos, blocksize);
1154 //
1155 //              if (spec.channels == 1) {
1156 //
1157 //                      if (read_raw_internal (spec.dataF, _start + spec.pos, to_read) != to_read) {
1158 //                              goto out;
1159 //                      }
1160 //
1161 //              } else {
1162 //
1163 //                      Sample buf[blocksize];
1164 //
1165 //                      for (uint32_t chan = 0; chan < spec.channels; ++chan) {
1166 //
1167 //                              if (audio_source(chan)->read (buf, _start + spec.pos, to_read) != to_read) {
1168 //                                      goto out;
1169 //                              }
1170 //
1171 //                              for (nframes_t x = 0; x < to_read; ++x) {
1172 //                                      spec.dataF[chan+(x*spec.channels)] = buf[x];
1173 //                              }
1174 //                      }
1175 //              }
1176 //
1177 //              if (spec.process (to_read)) {
1178 //                      goto out;
1179 //              }
1180 //
1181 //              spec.pos += to_read;
1182 //              spec.progress = (double) spec.pos /_length;
1183 //
1184 //      }
1185 //
1186 //      status = 0;
1187 //
1188 //  out:
1189 //      spec.running = false;
1190 //      spec.status = status;
1191 //      spec.clear();
1192 //
1193 //      return status;
1194         return 0;
1195 }
1196
1197 void
1198 AudioRegion::set_scale_amplitude (gain_t g)
1199 {
1200         boost::shared_ptr<Playlist> pl (playlist());
1201
1202         _scale_amplitude = g;
1203
1204         /* tell the diskstream we're in */
1205
1206         if (pl) {
1207                 pl->ContentsChanged();
1208         }
1209
1210         /* tell everybody else */
1211
1212         send_change (ScaleAmplitudeChanged);
1213 }
1214
1215 void
1216 AudioRegion::normalize_to (float target_dB)
1217 {
1218         const nframes_t blocksize = 64 * 1024;
1219         Sample buf[blocksize];
1220         nframes_t fpos;
1221         nframes_t fend;
1222         nframes_t to_read;
1223         double maxamp = 0;
1224         gain_t target = dB_to_coefficient (target_dB);
1225
1226         if (target == 1.0f) {
1227                 /* do not normalize to precisely 1.0 (0 dBFS), to avoid making it appear
1228                    that we may have clipped.
1229                 */
1230                 target -= FLT_EPSILON;
1231         }
1232
1233         fpos = _start;
1234         fend = _start + _length;
1235
1236         /* first pass: find max amplitude */
1237
1238         while (fpos < fend) {
1239
1240                 uint32_t n;
1241
1242                 to_read = min (fend - fpos, blocksize);
1243
1244                 for (n = 0; n < n_channels(); ++n) {
1245
1246                         /* read it in */
1247
1248                         if (read_raw_internal (buf, fpos, to_read, 0) != to_read) {
1249                                 return;
1250                         }
1251
1252                         maxamp = compute_peak (buf, to_read, maxamp);
1253                 }
1254
1255                 fpos += to_read;
1256         };
1257
1258         if (maxamp == 0.0f) {
1259                 /* don't even try */
1260                 return;
1261         }
1262
1263         if (maxamp == target) {
1264                 /* we can't do anything useful */
1265                 return;
1266         }
1267
1268         /* compute scale factor */
1269
1270         _scale_amplitude = target/maxamp;
1271
1272         /* tell the diskstream we're in */
1273
1274         boost::shared_ptr<Playlist> pl (playlist());
1275
1276         if (pl) {
1277                 pl->ContentsChanged();
1278         }
1279
1280         /* tell everybody else */
1281
1282         send_change (ScaleAmplitudeChanged);
1283 }
1284
1285 void
1286 AudioRegion::fade_in_changed ()
1287 {
1288         send_change (FadeInChanged);
1289 }
1290
1291 void
1292 AudioRegion::fade_out_changed ()
1293 {
1294         send_change (FadeOutChanged);
1295 }
1296
1297 void
1298 AudioRegion::envelope_changed ()
1299 {
1300         send_change (EnvelopeChanged);
1301 }
1302
1303 void
1304 AudioRegion::suspend_fade_in ()
1305 {
1306         if (++_fade_in_disabled == 1) {
1307                 if (fade_in_is_default()) {
1308                         set_fade_in_active (false);
1309                 }
1310         }
1311 }
1312
1313 void
1314 AudioRegion::resume_fade_in ()
1315 {
1316         if (--_fade_in_disabled == 0 && _fade_in_disabled) {
1317                 set_fade_in_active (true);
1318         }
1319 }
1320
1321 void
1322 AudioRegion::suspend_fade_out ()
1323 {
1324         if (++_fade_out_disabled == 1) {
1325                 if (fade_out_is_default()) {
1326                         set_fade_out_active (false);
1327                 }
1328         }
1329 }
1330
1331 void
1332 AudioRegion::resume_fade_out ()
1333 {
1334         if (--_fade_out_disabled == 0 &&_fade_out_disabled) {
1335                 set_fade_out_active (true);
1336         }
1337 }
1338
1339 bool
1340 AudioRegion::speed_mismatch (float sr) const
1341 {
1342         if (_sources.empty()) {
1343                 /* impossible, but ... */
1344                 return false;
1345         }
1346
1347         float fsr = audio_source()->sample_rate();
1348
1349         return fsr != sr;
1350 }
1351
1352 void
1353 AudioRegion::source_offset_changed ()
1354 {
1355         /* XXX this fixes a crash that should not occur. It does occur
1356            becauses regions are not being deleted when a session
1357            is unloaded. That bug must be fixed.
1358         */
1359
1360         if (_sources.empty()) {
1361                 return;
1362         }
1363
1364         boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(_sources.front());
1365
1366         if (afs && afs->destructive()) {
1367                 // set_start (source()->natural_position(), this);
1368                 set_position (source()->natural_position(), this);
1369         }
1370 }
1371
1372 boost::shared_ptr<AudioSource>
1373 AudioRegion::audio_source (uint32_t n) const
1374 {
1375         // Guaranteed to succeed (use a static cast for speed?)
1376         return boost::dynamic_pointer_cast<AudioSource>(source(n));
1377 }
1378
1379 int
1380 AudioRegion::get_transients (AnalysisFeatureList& results, bool force_new)
1381 {
1382         boost::shared_ptr<Playlist> pl = playlist();
1383
1384         if (!pl) {
1385                 return -1;
1386         }
1387
1388         if (_valid_transients && !force_new) {
1389                 results = _transients;
1390                 return 0;
1391         }
1392
1393         SourceList::iterator s;
1394
1395         for (s = _sources.begin() ; s != _sources.end(); ++s) {
1396                 if (!(*s)->has_been_analysed()) {
1397                         cerr << "For " << name() << " source " << (*s)->name() << " has not been analyzed\n";
1398                         break;
1399                 }
1400         }
1401
1402         if (s == _sources.end()) {
1403                 /* all sources are analyzed, merge data from each one */
1404
1405                 for (s = _sources.begin() ; s != _sources.end(); ++s) {
1406
1407                         /* find the set of transients within the bounds of this region */
1408
1409                         AnalysisFeatureList::iterator low = lower_bound ((*s)->transients.begin(),
1410                                                                          (*s)->transients.end(),
1411                                                                          _start);
1412
1413                         AnalysisFeatureList::iterator high = upper_bound ((*s)->transients.begin(),
1414                                                                           (*s)->transients.end(),
1415                                                                           _start + _length);
1416
1417                         /* and add them */
1418
1419                         results.insert (results.end(), low, high);
1420                 }
1421
1422                 TransientDetector::cleanup_transients (results, pl->session().frame_rate(), 3.0);
1423
1424                 /* translate all transients to current position */
1425
1426                 for (AnalysisFeatureList::iterator x = results.begin(); x != results.end(); ++x) {
1427                         (*x) -= _start;
1428                         (*x) += _position;
1429                 }
1430
1431                 _transients = results;
1432                 _valid_transients = true;
1433
1434                 return 0;
1435         }
1436
1437         /* no existing/complete transient info */
1438
1439         if (!Config->get_auto_analyse_audio()) {
1440                 pl->session().Dialog (_("\
1441 You have requested an operation that requires audio analysis.\n\n\
1442 You currently have \"auto-analyse-audio\" disabled, which means\n\
1443 that transient data must be generated every time it is required.\n\n\
1444 If you are doing work that will require transient data on a\n\
1445 regular basis, you should probably enable \"auto-analyse-audio\"\n\
1446 then quit ardour and restart."));
1447         }
1448
1449         TransientDetector t (pl->session().frame_rate());
1450         bool existing_results = !results.empty();
1451
1452         _transients.clear ();
1453         _valid_transients = false;
1454
1455         for (uint32_t i = 0; i < n_channels(); ++i) {
1456
1457                 AnalysisFeatureList these_results;
1458
1459                 t.reset ();
1460
1461                 if (t.run ("", this, i, these_results)) {
1462                         return -1;
1463                 }
1464
1465                 /* translate all transients to give absolute position */
1466
1467                 for (AnalysisFeatureList::iterator i = these_results.begin(); i != these_results.end(); ++i) {
1468                         (*i) += _position;
1469                 }
1470
1471                 /* merge */
1472
1473                 _transients.insert (_transients.end(), these_results.begin(), these_results.end());
1474         }
1475
1476         if (!results.empty()) {
1477                 if (existing_results) {
1478
1479                         /* merge our transients into the existing ones, then clean up
1480                            those.
1481                         */
1482
1483                         results.insert (results.end(), _transients.begin(), _transients.end());
1484                         TransientDetector::cleanup_transients (results, pl->session().frame_rate(), 3.0);
1485                 }
1486
1487                 /* make sure ours are clean too */
1488
1489                 TransientDetector::cleanup_transients (_transients, pl->session().frame_rate(), 3.0);
1490
1491         } else {
1492
1493                 TransientDetector::cleanup_transients (_transients, pl->session().frame_rate(), 3.0);
1494                 results = _transients;
1495         }
1496
1497         _valid_transients = true;
1498
1499         return 0;
1500 }
1501
1502 /** Find areas of `silence' within a region.
1503  *
1504  *  @param threshold Threshold below which signal is considered silence (as a sample value)
1505  *  @param min_length Minimum length of silent period to be reported.
1506  *  @return Silent periods; first of pair is the offset within the region, second is the length of the period
1507  */
1508
1509 std::list<std::pair<nframes_t, nframes_t> >
1510 AudioRegion::find_silence (Sample threshold, nframes_t min_length) const
1511 {
1512         nframes_t const block_size = 64 * 1024;
1513         Sample loudest[block_size];
1514         Sample buf[block_size];
1515
1516         nframes_t pos = _start;
1517         nframes_t const end = _start + _length - 1;
1518
1519         std::list<std::pair<nframes_t, nframes_t> > silent_periods;
1520
1521         bool in_silence = false;
1522         nframes_t silence_start = 0;
1523         bool silence;
1524
1525         while (pos < end) {
1526
1527                 /* fill `loudest' with the loudest absolute sample at each instant, across all channels */
1528                 memset (loudest, 0, sizeof (Sample) * block_size);
1529                 for (uint32_t n = 0; n < n_channels(); ++n) {
1530
1531                         read_raw_internal (buf, pos, block_size, n);
1532                         for (nframes_t i = 0; i < block_size; ++i) {
1533                                 loudest[i] = max (loudest[i], abs (buf[i]));
1534                         }
1535                 }
1536
1537                 /* now look for silence */
1538                 for (nframes_t i = 0; i < block_size; ++i) {
1539                         silence = abs (loudest[i]) < threshold;
1540                         if (silence && !in_silence) {
1541                                 /* non-silence to silence */
1542                                 in_silence = true;
1543                                 silence_start = pos + i;
1544                         } else if (!silence && in_silence) {
1545                                 /* silence to non-silence */
1546                                 in_silence = false;
1547                                 if (pos + i - 1 - silence_start >= min_length) {
1548                                         silent_periods.push_back (std::make_pair (silence_start, pos + i - 1));
1549                                 }
1550                         }
1551                 }
1552
1553                 pos += block_size;
1554         }
1555
1556         if (in_silence && end - 1 - silence_start >= min_length) {
1557                 /* last block was silent, so finish off the last period */
1558                 silent_periods.push_back (std::make_pair (silence_start, end));
1559         }
1560
1561         return silent_periods;
1562 }
1563
1564
1565 extern "C" {
1566
1567         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)
1568 {
1569         return ((AudioRegion *) arg)->read_peaks ((PeakData *) data, (nframes_t) npeaks, (nframes_t) start, (nframes_t) cnt, n_chan,samples_per_unit);
1570 }
1571
1572 uint32_t region_length_from_c (void *arg)
1573 {
1574
1575         return ((AudioRegion *) arg)->length();
1576 }
1577
1578 uint32_t sourcefile_length_from_c (void *arg, double zoom_factor)
1579 {
1580         return ( (AudioRegion *) arg)->audio_source()->available_peaks (zoom_factor) ;
1581 }
1582
1583 } /* extern "C" */