/*
- Copyright (C) 2009 Paul Davis
+ Copyright (C) 2009-2010 Paul Davis
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
#include "ardour/strip_silence.h"
#include "ardour/audioregion.h"
#include "ardour/region_factory.h"
-#include "ardour/session.h"
-#include "ardour/dB.h"
+#include "ardour/progress.h"
using namespace ARDOUR;
/** Construct a StripSilence filter.
* @param s Session.
- * @param threshold Threshold below which audio is considered silence, in dBFS.
- * @param minimum_length Minimum length of silence period to recognise, in samples.
+ * @param sm Silences to remove.
* @param fade_length Length of fade in/out to apply to trimmed regions, in samples.
*/
-StripSilence::StripSilence (Session & s, double threshold, nframes_t minimum_length, nframes_t fade_length)
- : Filter (s), _threshold (threshold), _minimum_length (minimum_length), _fade_length (fade_length)
+StripSilence::StripSilence (Session & s, const AudioIntervalMap& sm, framecnt_t fade_length)
+ : Filter (s)
+ , _smap (sm)
+ , _fade_length (fade_length)
{
}
int
-StripSilence::run (boost::shared_ptr<Region> r)
+StripSilence::run (boost::shared_ptr<Region> r, Progress* progress)
{
results.clear ();
/* we only operate on AudioRegions, for now, though this could be adapted to MIDI
- as well I guess
+ as well I guess
*/
boost::shared_ptr<AudioRegion> region = boost::dynamic_pointer_cast<AudioRegion> (r);
InterThreadInfo itt;
-
+ AudioIntervalMap::const_iterator sm;
+
if (!region) {
results.push_back (r);
return -1;
}
- /* find periods of silence in the region */
- std::list<std::pair<frameoffset_t, framecnt_t> > const silence =
- region->find_silence (dB_to_coefficient (_threshold), _minimum_length, itt);
+ if ((sm = _smap.find (r)) == _smap.end()) {
+ results.push_back (r);
+ return -1;
+ }
+
+ const AudioIntervalResult& silence = sm->second;
if (silence.size () == 1 && silence.front().first == 0 && silence.front().second == region->length() - 1) {
/* the region is all silence, so just return with nothing */
return 0;
}
- std::list<std::pair<framepos_t, framecnt_t > >::const_iterator s = silence.begin ();
- PBD::PropertyList plist;
- framepos_t start = 0;
- framepos_t end;
- bool in_silence;
- boost::shared_ptr<AudioRegion> copy;
-
- if (s->first == 0) {
- /* initial segment, starting at zero, is silent */
- end = s->second;
- in_silence = true;
- } else {
- /* initial segment, starting at zero, is audible */
- end = s->first;
- in_silence = false;
- }
+ /* Turn the silence list into an `audible' list */
+ AudioIntervalResult audible;
- while (s != silence.end()) {
+ /* Add the possible audible section at the start of the region */
+ AudioIntervalResult::const_iterator first_silence = silence.begin ();
+ if (first_silence->first != region->start()) {
+ audible.push_back (std::make_pair (r->start(), first_silence->first));
+ }
- framecnt_t interval_duration;
+ /* Add audible sections in the middle of the region */
+ for (AudioIntervalResult::const_iterator i = silence.begin (); i != silence.end(); ++i) {
+ AudioIntervalResult::const_iterator j = i;
+ ++j;
+
+ if (j != silence.end ()) {
+ audible.push_back (std::make_pair (i->second, j->first));
+ }
+ }
+
+ /* Add the possible audible section at the end of the region */
+ AudioIntervalResult::const_iterator last_silence = silence.end ();
+ --last_silence;
+
+ frameoffset_t const end_of_region = r->start() + r->length();
+
+ if (last_silence->second != end_of_region - 1) {
+ audible.push_back (std::make_pair (last_silence->second, end_of_region - 1));
+ }
- interval_duration = end - start;
+ int n = 0;
+ int const N = audible.size ();
+ for (AudioIntervalResult::const_iterator i = audible.begin(); i != audible.end(); ++i) {
- if (!in_silence && interval_duration > 0) {
+ PBD::PropertyList plist;
+ boost::shared_ptr<AudioRegion> copy;
- plist.clear ();
- plist.add (Properties::length, interval_duration);
- plist.add (Properties::position, region->position() + start);
+ plist.add (Properties::length, i->second - i->first);
+ plist.add (Properties::position, r->position() + (i->first - r->start()));
- copy = boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create
- (region, start, plist));
+ copy = boost::dynamic_pointer_cast<AudioRegion> (
+ RegionFactory::create (region, (i->first - r->start()), plist)
+ );
- copy->set_name (RegionFactory::new_region_name (region->name ()));
+ copy->set_name (RegionFactory::new_region_name (region->name ()));
- std::cerr << "New silent delineated region called " << copy->name()
- << " @ " << copy->start() << " length = " << copy->length() << " pos = " <<
- copy->position() << std::endl;
+ framecnt_t const f = std::min (_fade_length, (i->second - i->first));
- copy->set_fade_in_active (true);
- copy->set_fade_in (AudioRegion::Linear, _fade_length);
- results.push_back (copy);
- }
+ copy->set_fade_in_active (true);
+ copy->set_fade_in (FadeLinear, f);
+ copy->set_fade_out (FadeLinear, f);
+ results.push_back (copy);
- start = end;
- ++s;
- end = s->first;
- in_silence = !in_silence;
+ if (progress && (n <= N)) {
+ progress->set_progress (float (n) / N);
+ }
}
return 0;