X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;ds=sidebyside;f=libs%2Fardour%2Fstrip_silence.cc;h=1cbb81a3edd7c43a49f2a5a49fc54d785cbb2579;hb=5ec3e036ff2c3fffe1fcdfea1c8da07c2342bd92;hp=ae35eebd8f537f431494313953a0f32b133f7d36;hpb=c2c224727eee4c16bd64ca4a5b5bb2d276f5afe3;p=ardour.git diff --git a/libs/ardour/strip_silence.cc b/libs/ardour/strip_silence.cc index ae35eebd8f..1cbb81a3ed 100644 --- a/libs/ardour/strip_silence.cc +++ b/libs/ardour/strip_silence.cc @@ -1,5 +1,5 @@ /* - 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 @@ -17,54 +17,52 @@ */ +#include "pbd/property_list.h" + #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 r) +StripSilence::run (boost::shared_ptr 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 region = boost::dynamic_pointer_cast (r); InterThreadInfo itt; - + AudioIntervalMap::const_iterator sm; + if (!region) { results.push_back (r); return -1; } - /* we don't care about this but we need to fill out the fields - anyway. XXX should really be a default constructor for ITT - */ - - itt.done = false; - itt.cancel = false; - itt.progress = 0.0; - itt.thread = 0; + if ((sm = _smap.find (r)) == _smap.end()) { + results.push_back (r); + return -1; + } - /* find periods of silence in the region */ - std::list > const silence = - region->find_silence (dB_to_coefficient (_threshold), _minimum_length, itt); + 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 */ @@ -77,60 +75,69 @@ StripSilence::run (boost::shared_ptr r) return 0; } - std::list >::const_iterator s = silence.begin (); - framepos_t const pos = region->position (); - framepos_t const end = region->start () + region->length() - 1; - framepos_t const start = region->start (); - - region = boost::dynamic_pointer_cast (RegionFactory::create (region)); - region->set_name (session.new_region_name (region->name ())); - boost::shared_ptr last_region = region; - results.push_back (region); - - if (s->first == 0) { - /* the region starts with some silence */ - - /* we must set length to an intermediate value here, otherwise the call - ** to set_start will fail */ - region->set_length (region->length() - s->second + _fade_length, 0); - region->set_start (start + s->second - _fade_length, 0); - region->set_position (pos + s->second - _fade_length, 0); - region->set_fade_in_active (true); - region->set_fade_in (AudioRegion::Linear, _fade_length); - s++; + /* Turn the silence list into an `audible' list */ + AudioIntervalResult audible; + + /* 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)); } - while (s != silence.end()) { + /* 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; - /* trim the end of this region */ - region->trim_end (pos + s->first + _fade_length, 0); - region->set_fade_out_active (true); - region->set_fade_out (AudioRegion::Linear, _fade_length); + if (j != silence.end ()) { + audible.push_back (std::make_pair (i->second, j->first)); + } + } - /* make a new region and trim its start */ - region = boost::dynamic_pointer_cast (RegionFactory::create (region)); - region->set_name (session.new_region_name (region->name ())); - last_region = region; - assert (region); - results.push_back (region); + /* Add the possible audible section at the end of the region */ + AudioIntervalResult::const_iterator last_silence = silence.end (); + --last_silence; - /* set length here for the same reasons as above */ - region->set_length (region->length() - s->second + _fade_length, 0); - region->set_start (start + s->second - _fade_length, 0); - region->set_position (pos + s->second - _fade_length, 0); - region->set_fade_in_active (true); - region->set_fade_in (AudioRegion::Linear, _fade_length); + frameoffset_t const end_of_region = r->start() + r->length(); - s++; + if (last_silence->second < end_of_region - 1) { + audible.push_back (std::make_pair (last_silence->second, end_of_region - 1)); } - if (silence.back().second == end) { - /* the last region we created is zero-sized, so just remove it */ - results.pop_back (); - } else { - /* finish off the last region */ - last_region->trim_end (end, 0); - } + int n = 0; + int const N = audible.size (); + + for (AudioIntervalResult::const_iterator i = audible.begin(); i != audible.end(); ++i, ++n) { + + PBD::PropertyList plist; + boost::shared_ptr copy; + + plist.add (Properties::length, i->second - i->first); + plist.add (Properties::position, r->position() + (i->first - r->start())); + + copy = boost::dynamic_pointer_cast ( + RegionFactory::create (region, MusicFrame (i->first - r->start(), 0), plist) + ); + + copy->set_name (RegionFactory::new_region_name (region->name ())); + + framecnt_t const f = std::min (_fade_length, (i->second - i->first) / 2); + + if (f > 0) { + copy->set_fade_in_active (true); + copy->set_fade_out_active (true); + copy->set_fade_in (FadeLinear, f); + copy->set_fade_out (FadeLinear, f); + } else { + copy->set_fade_in_active (false); + copy->set_fade_out_active (false); + } + results.push_back (copy); + + if (progress && (n <= N)) { + progress->set_progress (float (n) / N); + } + } return 0; }