Merge with 2.0-ongoing R2885.
[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
24 #include <set>
25
26 #include <sigc++/bind.h>
27 #include <sigc++/class_slot.h>
28
29 #include <glibmm/thread.h>
30
31 #include <pbd/basename.h>
32 #include <pbd/xml++.h>
33 #include <pbd/stacktrace.h>
34 #include <pbd/enumwriter.h>
35 #include <pbd/convert.h>
36
37 #include <ardour/audioregion.h>
38 #include <ardour/session.h>
39 #include <ardour/gain.h>
40 #include <ardour/dB.h>
41 #include <ardour/playlist.h>
42 #include <ardour/audiofilesource.h>
43 #include <ardour/region_factory.h>
44 #include <ardour/runtime_functions.h>
45
46 #include "i18n.h"
47 #include <locale.h>
48
49 using namespace std;
50 using namespace ARDOUR;
51 using namespace PBD;
52
53 /* a Session will reset these to its chosen defaults by calling AudioRegion::set_default_fade() */
54
55 Change AudioRegion::FadeInChanged         = ARDOUR::new_change();
56 Change AudioRegion::FadeOutChanged        = ARDOUR::new_change();
57 Change AudioRegion::FadeInActiveChanged   = ARDOUR::new_change();
58 Change AudioRegion::FadeOutActiveChanged  = ARDOUR::new_change();
59 Change AudioRegion::EnvelopeActiveChanged = ARDOUR::new_change();
60 Change AudioRegion::ScaleAmplitudeChanged = ARDOUR::new_change();
61 Change AudioRegion::EnvelopeChanged       = ARDOUR::new_change();
62
63 void
64 AudioRegion::init ()
65 {
66         _scale_amplitude = 1.0;
67
68         set_default_fades ();
69         set_default_envelope ();
70
71         listen_to_my_curves ();
72 }
73
74 /* constructor for use by derived types only */
75 AudioRegion::AudioRegion (Session& s, nframes_t start, nframes_t length, string name)
76         : Region (s, start, length, name, DataType::AUDIO)
77         , _fade_in (new AutomationList(Parameter(FadeInAutomation), 0.0, 2.0, 1.0))
78         , _fade_out (new AutomationList(Parameter(FadeOutAutomation), 0.0, 2.0, 1.0))
79         , _envelope (new AutomationList(Parameter(EnvelopeAutomation), 0.0, 2.0, 1.0))
80 {
81         init ();
82 }
83
84 /** Basic AudioRegion constructor (one channel) */
85 AudioRegion::AudioRegion (boost::shared_ptr<AudioSource> src, nframes_t start, nframes_t length)
86         : Region (src, start, length, PBD::basename_nosuffix(src->name()), DataType::AUDIO, 0,  Region::Flag(Region::DefaultFlags|Region::External))
87         , _fade_in (new AutomationList(Parameter(FadeInAutomation), 0.0, 2.0, 1.0))
88         , _fade_out (new AutomationList(Parameter(FadeOutAutomation), 0.0, 2.0, 1.0))
89         , _envelope (new AutomationList(Parameter(EnvelopeAutomation), 0.0, 2.0, 1.0))
90 {
91         boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (src);
92         if (afs) {
93                 afs->HeaderPositionOffsetChanged.connect (mem_fun (*this, &AudioRegion::source_offset_changed));
94         }
95
96         init ();
97 }
98
99 /* Basic AudioRegion constructor (one channel) */
100 AudioRegion::AudioRegion (boost::shared_ptr<AudioSource> src, nframes_t start, nframes_t length, const string& name, layer_t layer, Flag flags)
101         : Region (src, start, length, name, DataType::AUDIO, layer, flags)
102         , _fade_in (new AutomationList(Parameter(FadeInAutomation), 0.0, 2.0, 1.0))
103         , _fade_out (new AutomationList(Parameter(FadeOutAutomation), 0.0, 2.0, 1.0))
104         , _envelope (new AutomationList(Parameter(EnvelopeAutomation), 0.0, 2.0, 1.0))
105 {
106         boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (src);
107         if (afs) {
108                 afs->HeaderPositionOffsetChanged.connect (mem_fun (*this, &AudioRegion::source_offset_changed));
109         }
110
111         init ();
112 }
113
114 /* Basic AudioRegion constructor (many channels) */
115 AudioRegion::AudioRegion (SourceList& srcs, nframes_t start, nframes_t length, const string& name, layer_t layer, Flag flags)
116         : Region (srcs, start, length, name, DataType::AUDIO, layer, flags)
117         , _fade_in (new AutomationList(Parameter(FadeInAutomation), 0.0, 2.0, 1.0))
118         , _fade_out (new AutomationList(Parameter(FadeOutAutomation), 0.0, 2.0, 1.0))
119         , _envelope (new AutomationList(Parameter(EnvelopeAutomation), 0.0, 2.0, 1.0))
120 {
121         init ();
122 }
123
124
125 /** Create a new AudioRegion, that is part of an existing one */
126 AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other, nframes_t offset, nframes_t length, const string& name, layer_t layer, Flag flags)
127         : Region (other, offset, length, name, layer, flags)
128         , _fade_in (new AutomationList(Parameter(FadeInAutomation), 0.0, 2.0, 1.0))
129         , _fade_out (new AutomationList(Parameter(FadeOutAutomation), 0.0, 2.0, 1.0))
130         , _envelope (new AutomationList(Parameter(EnvelopeAutomation), 0.0, 2.0, 1.0))
131 {
132         set<boost::shared_ptr<Source> > unique_srcs;
133
134         for (SourceList::const_iterator i= other->_sources.begin(); i != other->_sources.end(); ++i) {
135                 _sources.push_back (*i);
136
137                 pair<set<boost::shared_ptr<Source> >::iterator,bool> result;
138
139                 result = unique_srcs.insert (*i);
140                 
141                 if (result.second) {
142                         boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (*i);
143                         if (afs) {
144                                 afs->HeaderPositionOffsetChanged.connect (mem_fun (*this, &AudioRegion::source_offset_changed));
145                         }
146                 }
147         }
148
149         /* return to default fades if the existing ones are too long */
150         init ();
151
152         if (_flags & LeftOfSplit) {
153                 if (_fade_in->back()->when >= _length) {
154                         set_default_fade_in ();
155                 } else {
156                         _fade_in_disabled = other->_fade_in_disabled;
157                 }
158                 set_default_fade_out ();
159                 _flags = Flag (_flags & ~Region::LeftOfSplit);
160         }
161
162         if (_flags & RightOfSplit) {
163                 if (_fade_out->back()->when >= _length) {
164                         set_default_fade_out ();
165                 } else {
166                         _fade_out_disabled = other->_fade_out_disabled;
167                 }
168                 set_default_fade_in ();
169                 _flags = Flag (_flags & ~Region::RightOfSplit);
170         }
171
172         _scale_amplitude = other->_scale_amplitude;
173
174         assert(_type == DataType::AUDIO);
175 }
176
177 AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other)
178         : Region (other)
179         , _fade_in (new AutomationList(Parameter(FadeInAutomation), 0.0, 2.0, 1.0))
180         , _fade_out (new AutomationList(Parameter(FadeOutAutomation), 0.0, 2.0, 1.0))
181         , _envelope (new AutomationList(Parameter(EnvelopeAutomation), 0.0, 2.0, 1.0))
182 {
183         _scale_amplitude = other->_scale_amplitude;
184         _envelope = other->_envelope;
185
186         set_default_fades ();
187         
188         listen_to_my_curves ();
189
190         assert(_type == DataType::AUDIO);
191 }
192
193 AudioRegion::AudioRegion (boost::shared_ptr<AudioSource> src, const XMLNode& node)
194         : Region (src, node)
195         , _fade_in (new AutomationList(Parameter(FadeInAutomation), 0.0, 2.0, 1.0))
196         , _fade_out (new AutomationList(Parameter(FadeOutAutomation), 0.0, 2.0, 1.0))
197         , _envelope (new AutomationList(Parameter(EnvelopeAutomation), 0.0, 2.0, 1.0))
198 {
199         boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (src);
200         if (afs) {
201                 afs->HeaderPositionOffsetChanged.connect (mem_fun (*this, &AudioRegion::source_offset_changed));
202         }
203
204         init ();
205
206         if (set_state (node)) {
207                 throw failed_constructor();
208         }
209
210         assert(_type == DataType::AUDIO);
211 }
212
213 AudioRegion::AudioRegion (SourceList& srcs, const XMLNode& node)
214         : Region (srcs, node)
215         , _fade_in (new AutomationList(Parameter(FadeInAutomation), 0.0, 2.0, 1.0))
216         , _fade_out (new AutomationList(Parameter(FadeOutAutomation), 0.0, 2.0, 1.0))
217         , _envelope (new AutomationList(Parameter(EnvelopeAutomation), 0.0, 2.0, 1.0))
218 {
219         init ();
220
221         if (set_state (node)) {
222                 throw failed_constructor();
223         }
224
225         assert(_type == DataType::AUDIO);
226 }
227
228 AudioRegion::~AudioRegion ()
229 {
230 }
231
232 void
233 AudioRegion::listen_to_my_curves ()
234 {
235         _envelope->StateChanged.connect (mem_fun (*this, &AudioRegion::envelope_changed));
236         _fade_in->StateChanged.connect (mem_fun (*this, &AudioRegion::fade_in_changed));
237         _fade_out->StateChanged.connect (mem_fun (*this, &AudioRegion::fade_out_changed));
238 }
239
240 void
241 AudioRegion::set_envelope_active (bool yn)
242 {
243         if (envelope_active() != yn) {
244                 char buf[64];
245                 if (yn) {
246                         snprintf (buf, sizeof (buf), "envelope active");
247                         _flags = Flag (_flags|EnvelopeActive);
248                 } else {
249                         snprintf (buf, sizeof (buf), "envelope off");
250                         _flags = Flag (_flags & ~EnvelopeActive);
251                 }
252                 send_change (EnvelopeActiveChanged);
253         }
254 }
255
256 ARDOUR::nframes_t
257 AudioRegion::read_peaks (PeakData *buf, nframes_t npeaks, nframes_t offset, nframes_t cnt, uint32_t chan_n, double samples_per_unit) const
258 {
259         if (chan_n >= _sources.size()) {
260                 return 0; 
261         }
262
263         if (audio_source(chan_n)->read_peaks (buf, npeaks, offset, cnt, samples_per_unit)) {
264                 return 0;
265         } else {
266                 if (_scale_amplitude != 1.0) {
267                         for (nframes_t n = 0; n < npeaks; ++n) {
268                                 buf[n].max *= _scale_amplitude;
269                                 buf[n].min *= _scale_amplitude;
270                         }
271                 }
272                 return cnt;
273         }
274 }
275
276 nframes_t
277 AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, nframes_t position, 
278                       nframes_t cnt, 
279                       uint32_t chan_n, nframes_t read_frames, nframes_t skip_frames) const
280 {
281         return _read_at (_sources, buf, mixdown_buffer, gain_buffer, position, cnt, chan_n, read_frames, skip_frames);
282 }
283
284 nframes_t
285 AudioRegion::master_read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, nframes_t position, 
286                              nframes_t cnt, uint32_t chan_n) const
287 {
288         return _read_at (_master_sources, buf, mixdown_buffer, gain_buffer, position, cnt, chan_n, 0, 0);
289 }
290
291 nframes_t
292 AudioRegion::_read_at (const SourceList& srcs, Sample *buf, Sample *mixdown_buffer, float *gain_buffer,
293                        nframes_t position, nframes_t cnt, 
294                        uint32_t chan_n, nframes_t read_frames, nframes_t skip_frames) const
295 {
296         nframes_t internal_offset;
297         nframes_t buf_offset;
298         nframes_t to_read;
299
300         if (muted()) {
301                 return 0; /* read nothing */
302         }
303
304         /* precondition: caller has verified that we cover the desired section */
305
306         if (position < _position) {
307                 internal_offset = 0;
308                 buf_offset = _position - position;
309                 cnt -= buf_offset;
310         } else {
311                 internal_offset = position - _position;
312                 buf_offset = 0;
313         }
314
315         if (internal_offset >= _length) {
316                 return 0; /* read nothing */
317         }
318
319         if ((to_read = min (cnt, _length - internal_offset)) == 0) {
320                 return 0; /* read nothing */
321         }
322
323         if (opaque()) {
324                 /* overwrite whatever is there */
325                 mixdown_buffer = buf + buf_offset;
326         } else {
327                 mixdown_buffer += buf_offset;
328         }
329
330         _read_data_count = 0;
331
332         if (chan_n < n_channels()) {
333
334                 boost::shared_ptr<AudioSource> src = audio_source(chan_n);
335                 if (src->read (mixdown_buffer, _start + internal_offset, to_read) != to_read) {
336                         return 0; /* "read nothing" */
337                 }
338                 
339                 _read_data_count += src->read_data_count();
340
341         } else {
342                 
343                 /* track is N-channel, this region has less channels; silence the ones
344                    we don't have.
345                 */
346
347                 memset (mixdown_buffer, 0, sizeof (Sample) * cnt);
348
349                 /* no fades required */
350
351                 goto merge;
352         }
353
354         /* fade in */
355
356         if (_flags & FadeIn) {
357
358                 nframes_t fade_in_length = (nframes_t) _fade_in->back()->when;
359                 
360                 /* see if this read is within the fade in */
361
362                 if (internal_offset < fade_in_length) {
363                 
364                         nframes_t limit;
365
366                         limit = min (to_read, fade_in_length - internal_offset);
367
368                         _fade_in->curve().get_vector (internal_offset, internal_offset+limit, gain_buffer, limit);
369
370                         for (nframes_t n = 0; n < limit; ++n) {
371                                 mixdown_buffer[n] *= gain_buffer[n];
372                         }
373                 }
374         }
375         
376         /* fade out */
377
378         if (_flags & FadeOut) {
379         
380                 /* see if some part of this read is within the fade out */
381
382                 /* .................        >|            REGION
383                                             _length
384                                             
385                                  {           }            FADE
386                                              fade_out_length
387                                  ^                                           
388                                _length - fade_out_length
389                         |--------------|
390                         ^internal_offset
391                                        ^internal_offset + to_read
392
393                   we need the intersection of [internal_offset,internal_offset+to_read] with
394                   [_length - fade_out_length, _length]
395
396                 */
397
398         
399                 nframes_t fade_out_length = (nframes_t) _fade_out->back()->when;
400                 nframes_t fade_interval_start = max(internal_offset, _length-fade_out_length);
401                 nframes_t fade_interval_end   = min(internal_offset + to_read, _length);
402
403                 if (fade_interval_end > fade_interval_start) {
404                         /* (part of the) the fade out is  in this buffer */
405                         
406                         nframes_t limit = fade_interval_end - fade_interval_start;
407                         nframes_t curve_offset = fade_interval_start - (_length-fade_out_length);
408                         nframes_t fade_offset = fade_interval_start - internal_offset;
409                                                                        
410                         _fade_out->curve().get_vector (curve_offset,curve_offset+limit, gain_buffer, limit);
411
412                         for (nframes_t n = 0, m = fade_offset; n < limit; ++n, ++m) {
413                                 mixdown_buffer[m] *= gain_buffer[n];
414                         }
415                 } 
416
417         }
418
419         /* Regular gain curves */
420
421         if (envelope_active())  {
422                 _envelope->curve().get_vector (internal_offset, internal_offset + to_read, gain_buffer, to_read);
423                 
424                 if (_scale_amplitude != 1.0f) {
425                         for (nframes_t n = 0; n < to_read; ++n) {
426                                 mixdown_buffer[n] *= gain_buffer[n] * _scale_amplitude;
427                         }
428                 } else {
429                         for (nframes_t n = 0; n < to_read; ++n) {
430                                 mixdown_buffer[n] *= gain_buffer[n];
431                         }
432                 }
433         } else if (_scale_amplitude != 1.0f) {
434                 apply_gain_to_buffer (mixdown_buffer, to_read, _scale_amplitude);
435         }
436
437   merge:
438
439         if (!opaque()) {
440
441                 /* gack. the things we do for users.
442                  */
443
444                 buf += buf_offset;
445                 
446                 for (nframes_t n = 0; n < to_read; ++n) {
447                         buf[n] += mixdown_buffer[n];
448                 }
449         } 
450         
451         return to_read;
452 }
453         
454 XMLNode&
455 AudioRegion::state (bool full)
456 {
457         XMLNode& node (Region::state (full));
458         XMLNode *child;
459         char buf[64];
460         char buf2[64];
461         LocaleGuard lg (X_("POSIX"));
462         
463         node.add_property ("flags", enum_2_string (_flags));
464
465         snprintf (buf, sizeof(buf), "%.12g", _scale_amplitude);
466         node.add_property ("scale-gain", buf);
467
468         // XXX these should move into Region
469
470         for (uint32_t n=0; n < _sources.size(); ++n) {
471                 snprintf (buf2, sizeof(buf2), "source-%d", n);
472                 _sources[n]->id().print (buf, sizeof (buf));
473                 node.add_property (buf2, buf);
474         }
475
476         for (uint32_t n=0; n < _master_sources.size(); ++n) {
477                 snprintf (buf2, sizeof(buf2), "master-source-%d", n);
478                 _master_sources[n]->id().print (buf, sizeof (buf));
479                 node.add_property (buf2, buf);
480         }
481
482         snprintf (buf, sizeof (buf), "%u", (uint32_t) _sources.size());
483         node.add_property ("channels", buf);
484
485         if (full) {
486         
487                 child = node.add_child (X_("FadeIn"));
488                 
489                 if ((_flags & DefaultFadeIn)) {
490                         child->add_property (X_("default"), X_("yes"));
491                 } else {
492                         child->add_child_nocopy (_fade_in->get_state ());
493                 }
494
495                 child->add_property (X_("active"), _fade_in_disabled ? X_("no") : X_("yes"));
496                 
497                 child = node.add_child (X_("FadeOut"));
498                 
499                 if ((_flags & DefaultFadeOut)) {
500                         child->add_property (X_("default"), X_("yes"));
501                 } else {
502                         child->add_child_nocopy (_fade_out->get_state ());
503                 }
504                 
505                 child->add_property (X_("active"), _fade_out_disabled ? X_("no") : X_("yes"));
506         }
507         
508         child = node.add_child ("Envelope");
509
510         if (full) {
511                 bool default_env = false;
512                 
513                 // If there are only two points, the points are in the start of the region and the end of the region
514                 // so, if they are both at 1.0f, that means the default region.
515
516                 if (_envelope->size() == 2 &&
517                     _envelope->front()->value == 1.0f &&
518                     _envelope->back()->value==1.0f) {
519                         if (_envelope->front()->when == 0 && _envelope->back()->when == _length) {
520                                 default_env = true;
521                         }
522                 } 
523
524                 if (default_env) {
525                         child->add_property ("default", "yes");
526                 } else {
527                         child->add_child_nocopy (_envelope->get_state ());
528                 }
529
530         } else {
531                 child->add_property ("default", "yes");
532         }
533
534         if (full && _extra_xml) {
535                 node.add_child_copy (*_extra_xml);
536         }
537
538         return node;
539 }
540
541 int
542 AudioRegion::set_live_state (const XMLNode& node, Change& what_changed, bool send)
543 {
544         const XMLNodeList& nlist = node.children();
545         const XMLProperty *prop;
546         LocaleGuard lg (X_("POSIX"));
547
548         Region::set_live_state (node, what_changed, false);
549
550         uint32_t old_flags = _flags;
551
552         if ((prop = node.property ("flags")) != 0) {
553                 _flags = Flag (string_2_enum (prop->value(), _flags));
554
555                 //_flags = Flag (strtol (prop->value().c_str(), (char **) 0, 16));
556
557                 _flags = Flag (_flags & ~Region::LeftOfSplit);
558                 _flags = Flag (_flags & ~Region::RightOfSplit);
559         }
560
561         if ((old_flags ^ _flags) & Muted) {
562                 what_changed = Change (what_changed|MuteChanged);
563         }
564         if ((old_flags ^ _flags) & Opaque) {
565                 what_changed = Change (what_changed|OpacityChanged);
566         }
567         if ((old_flags ^ _flags) & Locked) {
568                 what_changed = Change (what_changed|LockChanged);
569         }
570
571         if ((prop = node.property ("scale-gain")) != 0) {
572                 _scale_amplitude = atof (prop->value().c_str());
573                 what_changed = Change (what_changed|ScaleAmplitudeChanged);
574         } else {
575                 _scale_amplitude = 1.0;
576         }
577         
578         /* Now find envelope description and other misc child items */
579                                 
580         for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
581                 
582                 XMLNode *child;
583                 XMLProperty *prop;
584                 
585                 child = (*niter);
586                 
587                 if (child->name() == "Envelope") {
588
589                         _envelope->clear ();
590
591                         if ((prop = child->property ("default")) != 0 || _envelope->set_state (*child)) {
592                                 set_default_envelope ();
593                         }
594
595                         _envelope->set_max_xval (_length);
596                         _envelope->truncate_end (_length);
597
598                 } else if (child->name() == "FadeIn") {
599                         
600                         _fade_in->clear ();
601                         
602                         if ((prop = child->property ("default")) != 0 || (prop = child->property ("steepness")) != 0) {
603                                 set_default_fade_in ();
604                         } else {
605                                 XMLNode* grandchild = child->child ("AutomationList");
606                                 if (grandchild) {
607                                         _fade_in->set_state (*grandchild);
608                                 }
609                         }
610
611                         if ((prop = child->property ("active")) != 0) {
612                                 if (prop->value() == "yes") {
613                                         set_fade_in_active (true);
614                                 } else {
615                                         set_fade_in_active (true);
616                                 }
617                         }
618
619                 } else if (child->name() == "FadeOut") {
620                         
621                         _fade_out->clear ();
622
623                         if ((prop = child->property ("default")) != 0 || (prop = child->property ("steepness")) != 0) {
624                                 set_default_fade_out ();
625                         } else {
626                                 XMLNode* grandchild = child->child ("AutomationList");
627                                 if (grandchild) {
628                                         _fade_out->set_state (*grandchild);
629                                 } 
630                         }
631
632                         if ((prop = child->property ("active")) != 0) {
633                                 if (prop->value() == "yes") {
634                                         set_fade_out_active (true);
635                                 } else {
636                                         set_fade_out_active (false);
637                                 }
638                         }
639
640                 } 
641         }
642
643         if (send) {
644                 send_change (what_changed);
645         }
646
647         return 0;
648 }
649
650 int
651 AudioRegion::set_state (const XMLNode& node)
652 {
653         /* Region::set_state() calls the virtual set_live_state(),
654            which will get us back to AudioRegion::set_live_state()
655            to handle the relevant stuff.
656         */
657
658         return Region::set_state (node);
659 }
660
661 void
662 AudioRegion::set_fade_in_shape (FadeShape shape)
663 {
664         set_fade_in (shape, (nframes_t) _fade_in->back()->when);
665 }
666
667 void
668 AudioRegion::set_fade_out_shape (FadeShape shape)
669 {
670         set_fade_out (shape, (nframes_t) _fade_out->back()->when);
671 }
672
673 void
674 AudioRegion::set_fade_in (FadeShape shape, nframes_t len)
675 {
676         _fade_in->freeze ();
677         _fade_in->clear ();
678
679         switch (shape) {
680         case Linear:
681                 _fade_in->fast_simple_add (0.0, 0.0);
682                 _fade_in->fast_simple_add (len, 1.0);
683                 break;
684
685         case Fast:
686                 _fade_in->fast_simple_add (0, 0);
687                 _fade_in->fast_simple_add (len * 0.389401, 0.0333333);
688                 _fade_in->fast_simple_add (len * 0.629032, 0.0861111);
689                 _fade_in->fast_simple_add (len * 0.829493, 0.233333);
690                 _fade_in->fast_simple_add (len * 0.9447, 0.483333);
691                 _fade_in->fast_simple_add (len * 0.976959, 0.697222);
692                 _fade_in->fast_simple_add (len, 1);
693                 break;
694
695         case Slow:
696                 _fade_in->fast_simple_add (0, 0);
697                 _fade_in->fast_simple_add (len * 0.0207373, 0.197222);
698                 _fade_in->fast_simple_add (len * 0.0645161, 0.525);
699                 _fade_in->fast_simple_add (len * 0.152074, 0.802778);
700                 _fade_in->fast_simple_add (len * 0.276498, 0.919444);
701                 _fade_in->fast_simple_add (len * 0.481567, 0.980556);
702                 _fade_in->fast_simple_add (len * 0.767281, 1);
703                 _fade_in->fast_simple_add (len, 1);
704                 break;
705
706         case LogA:
707                 _fade_in->fast_simple_add (0, 0);
708                 _fade_in->fast_simple_add (len * 0.0737327, 0.308333);
709                 _fade_in->fast_simple_add (len * 0.246544, 0.658333);
710                 _fade_in->fast_simple_add (len * 0.470046, 0.886111);
711                 _fade_in->fast_simple_add (len * 0.652074, 0.972222);
712                 _fade_in->fast_simple_add (len * 0.771889, 0.988889);
713                 _fade_in->fast_simple_add (len, 1);
714                 break;
715
716         case LogB:
717                 _fade_in->fast_simple_add (0, 0);
718                 _fade_in->fast_simple_add (len * 0.304147, 0.0694444);
719                 _fade_in->fast_simple_add (len * 0.529954, 0.152778);
720                 _fade_in->fast_simple_add (len * 0.725806, 0.333333);
721                 _fade_in->fast_simple_add (len * 0.847926, 0.558333);
722                 _fade_in->fast_simple_add (len * 0.919355, 0.730556);
723                 _fade_in->fast_simple_add (len, 1);
724                 break;
725         }
726
727         _fade_in->thaw ();
728         _fade_in_shape = shape;
729
730         send_change (FadeInChanged);
731 }
732
733 void
734 AudioRegion::set_fade_out (FadeShape shape, nframes_t len)
735 {
736         _fade_out->freeze ();
737         _fade_out->clear ();
738
739         switch (shape) {
740         case Fast:
741                 _fade_out->fast_simple_add (len * 0, 1);
742                 _fade_out->fast_simple_add (len * 0.023041, 0.697222);
743                 _fade_out->fast_simple_add (len * 0.0553,   0.483333);
744                 _fade_out->fast_simple_add (len * 0.170507, 0.233333);
745                 _fade_out->fast_simple_add (len * 0.370968, 0.0861111);
746                 _fade_out->fast_simple_add (len * 0.610599, 0.0333333);
747                 _fade_out->fast_simple_add (len * 1, 0);
748                 break;
749
750         case LogA:
751                 _fade_out->fast_simple_add (len * 0, 1);
752                 _fade_out->fast_simple_add (len * 0.228111, 0.988889);
753                 _fade_out->fast_simple_add (len * 0.347926, 0.972222);
754                 _fade_out->fast_simple_add (len * 0.529954, 0.886111);
755                 _fade_out->fast_simple_add (len * 0.753456, 0.658333);
756                 _fade_out->fast_simple_add (len * 0.9262673, 0.308333);
757                 _fade_out->fast_simple_add (len * 1, 0);
758                 break;
759
760         case Slow:
761                 _fade_out->fast_simple_add (len * 0, 1);
762                 _fade_out->fast_simple_add (len * 0.305556, 1);
763                 _fade_out->fast_simple_add (len * 0.548611, 0.991736);
764                 _fade_out->fast_simple_add (len * 0.759259, 0.931129);
765                 _fade_out->fast_simple_add (len * 0.918981, 0.68595);
766                 _fade_out->fast_simple_add (len * 0.976852, 0.22865);
767                 _fade_out->fast_simple_add (len * 1, 0);
768                 break;
769
770         case LogB:
771                 _fade_out->fast_simple_add (len * 0, 1);
772                 _fade_out->fast_simple_add (len * 0.080645, 0.730556);
773                 _fade_out->fast_simple_add (len * 0.277778, 0.289256);
774                 _fade_out->fast_simple_add (len * 0.470046, 0.152778);
775                 _fade_out->fast_simple_add (len * 0.695853, 0.0694444);
776                 _fade_out->fast_simple_add (len * 1, 0);
777                 break;
778
779         case Linear:
780                 _fade_out->fast_simple_add (len * 0, 1);
781                 _fade_out->fast_simple_add (len * 1, 0);
782                 break;
783         }
784
785         _fade_out->thaw ();
786         _fade_out_shape = shape;
787
788         send_change (FadeOutChanged);
789 }
790
791 void
792 AudioRegion::set_fade_in_length (nframes_t len)
793 {
794         if (len > _length) {
795                 len = _length - 1;
796         }
797
798         bool changed = _fade_in->extend_to (len);
799
800         if (changed) {
801                 _flags = Flag (_flags & ~DefaultFadeIn);
802                 send_change (FadeInChanged);
803         }
804 }
805
806 void
807 AudioRegion::set_fade_out_length (nframes_t len)
808 {
809         if (len > _length) {
810                 len = _length - 1;
811         }
812
813         bool changed =  _fade_out->extend_to (len);
814
815         if (changed) {
816                 _flags = Flag (_flags & ~DefaultFadeOut);
817                 send_change (FadeOutChanged);
818         }
819 }
820
821 void
822 AudioRegion::set_fade_in_active (bool yn)
823 {
824         if (yn == (_flags & FadeIn)) {
825                 return;
826         }
827         if (yn) {
828                 _flags = Flag (_flags|FadeIn);
829         } else {
830                 _flags = Flag (_flags & ~FadeIn);
831         }
832
833         send_change (FadeInActiveChanged);
834 }
835
836 void
837 AudioRegion::set_fade_out_active (bool yn)
838 {
839         if (yn == (_flags & FadeOut)) {
840                 return;
841         }
842         if (yn) {
843                 _flags = Flag (_flags | FadeOut);
844         } else {
845                 _flags = Flag (_flags & ~FadeOut);
846         }
847
848         send_change (FadeOutActiveChanged);
849 }
850
851 bool
852 AudioRegion::fade_in_is_default () const
853 {
854         return _fade_in_shape == Linear && _fade_in->back()->when == 64;
855 }
856
857 bool
858 AudioRegion::fade_out_is_default () const
859 {
860         return _fade_out_shape == Linear && _fade_out->back()->when == 64;
861 }
862
863 void
864 AudioRegion::set_default_fade_in ()
865 {
866         set_fade_in (Linear, 64);
867 }
868
869 void
870 AudioRegion::set_default_fade_out ()
871 {
872         set_fade_out (Linear, 64);
873 }
874
875 void
876 AudioRegion::set_default_fades ()
877 {
878         _fade_in_disabled = 0;
879         _fade_out_disabled = 0;
880         set_default_fade_in ();
881         set_default_fade_out ();
882 }
883
884 void
885 AudioRegion::set_default_envelope ()
886 {
887         _envelope->freeze ();
888         _envelope->clear ();
889         _envelope->fast_simple_add (0, 1.0f);
890         _envelope->fast_simple_add (_length, 1.0f);
891         _envelope->thaw ();
892 }
893
894 void
895 AudioRegion::recompute_at_end ()
896 {
897         /* our length has changed. recompute a new final point by interpolating 
898            based on the the existing curve.
899         */
900         
901         _envelope->freeze ();
902         _envelope->truncate_end (_length);
903         _envelope->set_max_xval (_length);
904         _envelope->thaw ();
905
906         if (_fade_in->back()->when > _length) {
907                 _fade_in->extend_to (_length);
908                 send_change (FadeInChanged);
909         }
910
911         if (_fade_out->back()->when > _length) {
912                 _fade_out->extend_to (_length);
913                 send_change (FadeOutChanged);
914         }
915 }       
916
917 void
918 AudioRegion::recompute_at_start ()
919 {
920         /* as above, but the shift was from the front */
921
922         _envelope->truncate_start (_length);
923
924         if (_fade_in->back()->when > _length) {
925                 _fade_in->extend_to (_length);
926                 send_change (FadeInChanged);
927         }
928
929         if (_fade_out->back()->when > _length) {
930                 _fade_out->extend_to (_length);
931                 send_change (FadeOutChanged);
932         }
933 }
934
935 int
936 AudioRegion::separate_by_channel (Session& session, vector<boost::shared_ptr<AudioRegion> >& v) const
937 {
938         SourceList srcs;
939         string new_name;
940         int n;
941
942         if (_sources.size() < 2) {
943                 return 0;
944         }
945
946         n = 0;
947
948         for (SourceList::const_iterator i = _sources.begin(); i != _sources.end(); ++i) {
949
950                 srcs.clear ();
951                 srcs.push_back (*i);
952
953                 new_name = _name;
954
955                 if (_sources.size() == 2) {
956                         if (n == 0) {
957                                 new_name += "-L";
958                         } else {
959                                 new_name += "-R";
960                         }
961                 } else {
962                         new_name += '-';
963                         new_name += ('0' + n + 1);
964                 }
965
966                 /* create a copy with just one source. prevent if from being thought of as "whole file" even if 
967                    it covers the entire source file(s).
968                  */
969
970                 Flag f = Flag (_flags & ~WholeFile);
971
972                 boost::shared_ptr<Region> r = RegionFactory::create (srcs, _start, _length, new_name, _layer, f);
973                 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion> (r);
974
975                 v.push_back (ar);
976                 
977                 ++n;
978         }
979
980         return 0;
981 }
982
983 nframes_t
984 AudioRegion::read_raw_internal (Sample* buf, nframes_t pos, nframes_t cnt) const
985 {
986         return audio_source()->read  (buf, pos, cnt);
987 }
988
989
990 int
991 AudioRegion::exportme (Session& session, AudioExportSpecification& spec)
992 {
993         const nframes_t blocksize = 4096;
994         nframes_t to_read;
995         int status = -1;
996
997         spec.channels = _sources.size();
998
999         if (spec.prepare (blocksize, session.frame_rate())) {
1000                 goto out;
1001         }
1002
1003         spec.pos = 0;
1004         spec.total_frames = _length;
1005
1006         while (spec.pos < _length && !spec.stop) {
1007                 
1008                 
1009                 /* step 1: interleave */
1010                 
1011                 to_read = min (_length - spec.pos, blocksize);
1012                 
1013                 if (spec.channels == 1) {
1014
1015                         if (read_raw_internal (spec.dataF, _start + spec.pos, to_read) != to_read) {
1016                                 goto out;
1017                         }
1018
1019                 } else {
1020
1021                         Sample buf[blocksize];
1022
1023                         for (uint32_t chan = 0; chan < spec.channels; ++chan) {
1024                                 
1025                                 if (audio_source(chan)->read (buf, _start + spec.pos, to_read) != to_read) {
1026                                         goto out;
1027                                 }
1028                                 
1029                                 for (nframes_t x = 0; x < to_read; ++x) {
1030                                         spec.dataF[chan+(x*spec.channels)] = buf[x];
1031                                 }
1032                         }
1033                 }
1034                 
1035                 if (spec.process (to_read)) {
1036                         goto out;
1037                 }
1038                 
1039                 spec.pos += to_read;
1040                 spec.progress = (double) spec.pos /_length;
1041                 
1042         }
1043         
1044         status = 0;
1045
1046   out:  
1047         spec.running = false;
1048         spec.status = status;
1049         spec.clear();
1050         
1051         return status;
1052 }
1053
1054 void
1055 AudioRegion::set_scale_amplitude (gain_t g)
1056 {
1057         boost::shared_ptr<Playlist> pl (playlist());
1058
1059         _scale_amplitude = g;
1060
1061         /* tell the diskstream we're in */
1062         
1063         if (pl) {
1064                 pl->Modified();
1065         }
1066
1067         /* tell everybody else */
1068
1069         send_change (ScaleAmplitudeChanged);
1070 }
1071
1072 void
1073 AudioRegion::normalize_to (float target_dB)
1074 {
1075         const nframes_t blocksize = 64 * 1024;
1076         Sample buf[blocksize];
1077         nframes_t fpos;
1078         nframes_t fend;
1079         nframes_t to_read;
1080         double maxamp = 0;
1081         gain_t target = dB_to_coefficient (target_dB);
1082
1083         if (target == 1.0f) {
1084                 /* do not normalize to precisely 1.0 (0 dBFS), to avoid making it appear
1085                    that we may have clipped.
1086                 */
1087                 target -= FLT_EPSILON;
1088         }
1089
1090         fpos = _start;
1091         fend = _start + _length;
1092
1093         /* first pass: find max amplitude */
1094
1095         while (fpos < fend) {
1096
1097                 uint32_t n;
1098
1099                 to_read = min (fend - fpos, blocksize);
1100
1101                 for (n = 0; n < n_channels(); ++n) {
1102
1103                         /* read it in */
1104
1105                         if (read_raw_internal (buf, fpos, to_read) != to_read) {
1106                                 return;
1107                         }
1108                         
1109                         maxamp = compute_peak (buf, to_read, maxamp);
1110                 }
1111
1112                 fpos += to_read;
1113         };
1114
1115         if (maxamp == 0.0f) {
1116                 /* don't even try */
1117                 return;
1118         }
1119
1120         if (maxamp == target) {
1121                 /* we can't do anything useful */
1122                 return;
1123         }
1124
1125         /* compute scale factor */
1126
1127         _scale_amplitude = target/maxamp;
1128
1129         /* tell the diskstream we're in */
1130
1131         boost::shared_ptr<Playlist> pl (playlist());
1132
1133         if (pl) {
1134                 pl->Modified();
1135         }
1136
1137         /* tell everybody else */
1138
1139         send_change (ScaleAmplitudeChanged);
1140 }
1141
1142 void
1143 AudioRegion::fade_in_changed ()
1144 {
1145         send_change (FadeInChanged);
1146 }
1147
1148 void
1149 AudioRegion::fade_out_changed ()
1150 {
1151         send_change (FadeOutChanged);
1152 }
1153
1154 void
1155 AudioRegion::envelope_changed ()
1156 {
1157         send_change (EnvelopeChanged);
1158 }
1159
1160 void
1161 AudioRegion::suspend_fade_in ()
1162 {
1163         if (++_fade_in_disabled == 1) {
1164                 if (fade_in_is_default()) {
1165                         set_fade_in_active (false);
1166                 }
1167         }
1168 }
1169
1170 void
1171 AudioRegion::resume_fade_in ()
1172 {
1173         if (--_fade_in_disabled == 0 && _fade_in_disabled) {
1174                 set_fade_in_active (true);
1175         }
1176 }
1177
1178 void
1179 AudioRegion::suspend_fade_out ()
1180 {
1181         if (++_fade_out_disabled == 1) {
1182                 if (fade_out_is_default()) {
1183                         set_fade_out_active (false);
1184                 }
1185         }
1186 }
1187
1188 void
1189 AudioRegion::resume_fade_out ()
1190 {
1191         if (--_fade_out_disabled == 0 &&_fade_out_disabled) {
1192                 set_fade_out_active (true);
1193         }
1194 }
1195
1196 bool
1197 AudioRegion::speed_mismatch (float sr) const
1198 {
1199         if (_sources.empty()) {
1200                 /* impossible, but ... */
1201                 return false;
1202         }
1203
1204         float fsr = audio_source()->sample_rate();
1205
1206         return fsr != sr;
1207 }
1208
1209 void
1210 AudioRegion::source_offset_changed ()
1211 {
1212         boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(_sources.front());
1213
1214         if (afs && afs->destructive()) {
1215                 // set_start (source()->natural_position(), this);
1216                 set_position (source()->natural_position(), this);
1217         } 
1218 }
1219
1220 boost::shared_ptr<AudioSource>
1221 AudioRegion::audio_source (uint32_t n) const
1222 {
1223         // Guaranteed to succeed (use a static cast for speed?)
1224         return boost::dynamic_pointer_cast<AudioSource>(source(n));
1225 }
1226
1227 extern "C" {
1228
1229         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) 
1230 {
1231         return ((AudioRegion *) arg)->read_peaks ((PeakData *) data, (nframes_t) npeaks, (nframes_t) start, (nframes_t) cnt, n_chan,samples_per_unit);
1232 }
1233
1234 uint32_t region_length_from_c (void *arg)
1235 {
1236
1237         return ((AudioRegion *) arg)->length();
1238 }
1239
1240 uint32_t sourcefile_length_from_c (void *arg, double zoom_factor)
1241 {
1242         return ( (AudioRegion *) arg)->audio_source()->available_peaks (zoom_factor) ;
1243 }
1244
1245 } /* extern "C" */