2 Copyright (C) 2009-2010 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include "pbd/property_list.h"
22 #include "ardour/strip_silence.h"
23 #include "ardour/audioregion.h"
24 #include "ardour/region_factory.h"
25 #include "ardour/session.h"
26 #include "ardour/dB.h"
27 #include "ardour/progress.h"
29 using namespace ARDOUR
;
31 /** Construct a StripSilence filter.
33 * @param threshold Threshold below which audio is considered silence, in dBFS.
34 * @param minimum_length Minimum length of silence period to recognise, in samples.
35 * @param fade_length Length of fade in/out to apply to trimmed regions, in samples.
38 StripSilence::StripSilence (Session
& s
, const AudioIntervalMap
& sm
, framecnt_t fade_length
)
41 , _fade_length (fade_length
)
47 StripSilence::run (boost::shared_ptr
<Region
> r
, Progress
* progress
)
51 /* we only operate on AudioRegions, for now, though this could be adapted to MIDI
54 boost::shared_ptr
<AudioRegion
> region
= boost::dynamic_pointer_cast
<AudioRegion
> (r
);
56 AudioIntervalMap::const_iterator sm
;
59 results
.push_back (r
);
63 if ((sm
= _smap
.find (r
)) == _smap
.end()) {
64 results
.push_back (r
);
68 const AudioIntervalResult
& silence
= sm
->second
;
70 if (silence
.size () == 1 && silence
.front().first
== 0 && silence
.front().second
== region
->length() - 1) {
71 /* the region is all silence, so just return with nothing */
75 if (silence
.empty()) {
76 /* no silence in this region */
77 results
.push_back (region
);
81 /* Turn the silence list into an `audible' list */
82 AudioIntervalResult audible
;
84 /* Add the possible audible section at the start of the region */
85 AudioIntervalResult::const_iterator first_silence
= silence
.begin ();
86 if (first_silence
->first
!= region
->start()) {
87 audible
.push_back (std::make_pair (r
->start(), first_silence
->first
));
90 /* Add audible sections in the middle of the region */
91 for (AudioIntervalResult::const_iterator i
= silence
.begin (); i
!= silence
.end(); ++i
) {
92 AudioIntervalResult::const_iterator j
= i
;
95 if (j
!= silence
.end ()) {
96 audible
.push_back (std::make_pair (i
->second
, j
->first
));
100 /* Add the possible audible section at the end of the region */
101 AudioIntervalResult::const_iterator last_silence
= silence
.end ();
104 frameoffset_t
const end_of_region
= r
->start() + r
->length();
106 if (last_silence
->second
!= end_of_region
- 1) {
107 audible
.push_back (std::make_pair (last_silence
->second
, end_of_region
- 1));
111 int const N
= audible
.size ();
113 for (AudioIntervalResult::const_iterator i
= audible
.begin(); i
!= audible
.end(); ++i
) {
115 PBD::PropertyList plist
;
116 boost::shared_ptr
<AudioRegion
> copy
;
118 plist
.add (Properties::length
, i
->second
- i
->first
);
119 plist
.add (Properties::position
, r
->position() + (i
->first
- r
->start()));
121 copy
= boost::dynamic_pointer_cast
<AudioRegion
> (
122 RegionFactory::create (region
, (i
->first
- r
->start()), plist
)
125 copy
->set_name (RegionFactory::new_region_name (region
->name ()));
127 framecnt_t
const f
= std::min (_fade_length
, (i
->second
- i
->first
));
129 copy
->set_fade_in_active (true);
130 copy
->set_fade_in (FadeLinear
, f
);
131 copy
->set_fade_out (FadeLinear
, f
);
132 results
.push_back (copy
);
134 if (progress
&& (n
<= N
)) {
135 progress
->set_progress (float (n
) / N
);