First cut of option to strip silence from audio regions, as per mantis #1623
git-svn-id: svn://localhost/ardour2/branches/3.0@5010 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
@@ -242,6 +242,7 @@ simplerect.cc
|
||||
splash.cc
|
||||
startup.cc
|
||||
streamview.cc
|
||||
strip_silence_dialog.cc
|
||||
tape_region_view.cc
|
||||
tempo_dialog.cc
|
||||
tempo_lines.cc
|
||||
|
||||
@@ -2052,6 +2052,7 @@ Editor::add_region_context_items (StreamView* sv, boost::shared_ptr<Region> regi
|
||||
items.push_back (SeparatorElem());
|
||||
}
|
||||
|
||||
items.push_back (MenuElem (_("Strip silence..."), mem_fun (*this, &Editor::strip_region_silence)));
|
||||
items.push_back (MenuElem (_("Reverse"), mem_fun(*this, &Editor::reverse_region)));
|
||||
items.push_back (SeparatorElem());
|
||||
|
||||
|
||||
@@ -1191,6 +1191,7 @@ class Editor : public PublicEditor
|
||||
void audition_playlist_region_via_route (boost::shared_ptr<ARDOUR::Region>, ARDOUR::Route&);
|
||||
void split_multichannel_region();
|
||||
void reverse_region ();
|
||||
void strip_region_silence ();
|
||||
void normalize_region ();
|
||||
void denormalize_region ();
|
||||
void adjust_region_scale_amplitude (bool up);
|
||||
|
||||
@@ -54,6 +54,7 @@
|
||||
#include "ardour/transient_detector.h"
|
||||
#include "ardour/dB.h"
|
||||
#include "ardour/quantize.h"
|
||||
#include "ardour/strip_silence.h"
|
||||
|
||||
#include "ardour_ui.h"
|
||||
#include "editor.h"
|
||||
@@ -73,6 +74,7 @@
|
||||
#include "gui_thread.h"
|
||||
#include "keyboard.h"
|
||||
#include "utils.h"
|
||||
#include "strip_silence_dialog.h"
|
||||
|
||||
#include "i18n.h"
|
||||
|
||||
@@ -4660,6 +4662,22 @@ Editor::reverse_region ()
|
||||
apply_filter (rev, _("reverse regions"));
|
||||
}
|
||||
|
||||
void
|
||||
Editor::strip_region_silence ()
|
||||
{
|
||||
if (!session) {
|
||||
return;
|
||||
}
|
||||
|
||||
StripSilenceDialog d;
|
||||
int const r = d.run ();
|
||||
|
||||
if (r == Gtk::RESPONSE_OK) {
|
||||
StripSilence s (*session, d.threshold (), d.minimum_length (), d.fade_length ());
|
||||
apply_filter (s, _("strip silence"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Editor::quantize_region ()
|
||||
@@ -4707,7 +4725,28 @@ Editor::apply_filter (Filter& filter, string command)
|
||||
if (arv->audio_region()->apply (filter) == 0) {
|
||||
|
||||
XMLNode &before = playlist->get_state();
|
||||
playlist->replace_region (arv->region(), filter.results.front(), arv->region()->position());
|
||||
|
||||
if (filter.results.empty ()) {
|
||||
|
||||
/* no regions returned; remove the old one */
|
||||
playlist->remove_region (arv->region ());
|
||||
|
||||
} else {
|
||||
|
||||
std::vector<boost::shared_ptr<Region> >::iterator res = filter.results.begin ();
|
||||
|
||||
/* first region replaces the old one */
|
||||
playlist->replace_region (arv->region(), *res, (*res)->position());
|
||||
++res;
|
||||
|
||||
/* add the rest */
|
||||
while (res != filter.results.end()) {
|
||||
playlist->add_region (*res, (*res)->position());
|
||||
++res;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
XMLNode &after = playlist->get_state();
|
||||
session->add_command(new MementoCommand<Playlist>(*playlist, &before, &after));
|
||||
} else {
|
||||
|
||||
@@ -197,6 +197,7 @@ def build(bld):
|
||||
splash.cc
|
||||
startup.cc
|
||||
streamview.cc
|
||||
strip_silence_dialog.cc
|
||||
tape_region_view.cc
|
||||
tempo_dialog.cc
|
||||
tempo_lines.cc
|
||||
|
||||
@@ -159,6 +159,7 @@ sndfileimportable.cc
|
||||
sndfilesource.cc
|
||||
source.cc
|
||||
source_factory.cc
|
||||
strip_silence.cc
|
||||
svn_revision.cc
|
||||
tape_file_matcher.cc
|
||||
template_utils.cc
|
||||
|
||||
@@ -106,7 +106,7 @@ class AudioRegion : public Region
|
||||
virtual nframes_t master_read_at (Sample *buf, Sample *mixdown_buf, float *gain_buf,
|
||||
sframes_t position, nframes_t cnt, uint32_t chan_n=0) const;
|
||||
|
||||
virtual nframes_t read_raw_internal (Sample*, sframes_t, nframes_t) const;
|
||||
virtual nframes_t read_raw_internal (Sample*, sframes_t, nframes_t, int channel) const;
|
||||
|
||||
XMLNode& state (bool);
|
||||
int set_state (const XMLNode&);
|
||||
@@ -162,6 +162,7 @@ class AudioRegion : public Region
|
||||
void resume_fade_out ();
|
||||
|
||||
int get_transients (AnalysisFeatureList&, bool force_new = false);
|
||||
std::list<std::pair<nframes_t, nframes_t> > find_silence (Sample, nframes_t) const;
|
||||
|
||||
private:
|
||||
friend class RegionFactory;
|
||||
|
||||
@@ -170,7 +170,7 @@ class Crossfade : public ARDOUR::AudioRegion
|
||||
bool update ();
|
||||
|
||||
protected:
|
||||
nframes_t read_raw_internal (Sample*, sframes_t, nframes_t) const;
|
||||
nframes_t read_raw_internal (Sample*, sframes_t, nframes_t, int) const;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -1062,9 +1062,9 @@ AudioRegion::separate_by_channel (Session& session, vector<boost::shared_ptr<Reg
|
||||
}
|
||||
|
||||
nframes_t
|
||||
AudioRegion::read_raw_internal (Sample* buf, sframes_t pos, nframes_t cnt) const
|
||||
AudioRegion::read_raw_internal (Sample* buf, sframes_t pos, nframes_t cnt, int channel) const
|
||||
{
|
||||
return audio_source()->read (buf, pos, cnt);
|
||||
return audio_source()->read (buf, pos, cnt, channel);
|
||||
}
|
||||
|
||||
int
|
||||
@@ -1184,7 +1184,7 @@ AudioRegion::normalize_to (float target_dB)
|
||||
|
||||
/* read it in */
|
||||
|
||||
if (read_raw_internal (buf, fpos, to_read) != to_read) {
|
||||
if (read_raw_internal (buf, fpos, to_read, 0) != to_read) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1438,6 +1438,71 @@ then quit ardour and restart."));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Find areas of `silence' within a region.
|
||||
*
|
||||
* @param threshold Threshold below which signal is considered silence (as a sample value)
|
||||
* @param min_length Minimum length of silent period to be reported.
|
||||
* @return Silent periods; first of pair is the offset within the region, second is the length of the period
|
||||
*/
|
||||
|
||||
std::list<std::pair<nframes_t, nframes_t> >
|
||||
AudioRegion::find_silence (Sample threshold, nframes_t min_length) const
|
||||
{
|
||||
nframes_t const block_size = 64 * 1024;
|
||||
Sample loudest[block_size];
|
||||
Sample buf[block_size];
|
||||
|
||||
nframes_t pos = _start;
|
||||
nframes_t const end = _start + _length - 1;
|
||||
|
||||
std::list<std::pair<nframes_t, nframes_t> > silent_periods;
|
||||
|
||||
bool in_silence = false;
|
||||
nframes_t silence_start = 0;
|
||||
bool silence;
|
||||
|
||||
while (pos < end) {
|
||||
|
||||
nframes_t const to_read = min (end - pos, block_size);
|
||||
|
||||
/* fill `loudest' with the loudest absolute sample at each instant, across all channels */
|
||||
memset (loudest, 0, sizeof (Sample) * block_size);
|
||||
for (uint32_t n = 0; n < n_channels(); ++n) {
|
||||
|
||||
read_raw_internal (buf, pos, block_size, n);
|
||||
for (nframes_t i = 0; i < block_size; ++i) {
|
||||
loudest[i] = max (loudest[i], abs (buf[i]));
|
||||
}
|
||||
}
|
||||
|
||||
/* now look for silence */
|
||||
for (nframes_t i = 0; i < block_size; ++i) {
|
||||
silence = abs (loudest[i]) < threshold;
|
||||
if (silence && !in_silence) {
|
||||
/* non-silence to silence */
|
||||
in_silence = true;
|
||||
silence_start = pos + i;
|
||||
} else if (!silence && in_silence) {
|
||||
/* silence to non-silence */
|
||||
in_silence = false;
|
||||
if (pos + i - 1 - silence_start >= min_length) {
|
||||
silent_periods.push_back (std::make_pair (silence_start, pos + i - 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pos += block_size;
|
||||
}
|
||||
|
||||
if (in_silence && end - 1 - silence_start >= min_length) {
|
||||
/* last block was silent, so finish off the last period */
|
||||
silent_periods.push_back (std::make_pair (silence_start, end));
|
||||
}
|
||||
|
||||
return silent_periods;
|
||||
}
|
||||
|
||||
|
||||
extern "C" {
|
||||
|
||||
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)
|
||||
|
||||
@@ -271,7 +271,7 @@ Crossfade::initialize ()
|
||||
}
|
||||
|
||||
nframes_t
|
||||
Crossfade::read_raw_internal (Sample* buf, sframes_t start, nframes_t cnt) const
|
||||
Crossfade::read_raw_internal (Sample* buf, sframes_t start, nframes_t cnt, int channel) const
|
||||
{
|
||||
// FIXME: Why is this disabled?
|
||||
#if 0
|
||||
|
||||
@@ -1638,3 +1638,4 @@ Region::invalidate_transients ()
|
||||
_transients.clear ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -198,6 +198,7 @@ def build(bld):
|
||||
sndfilesource.cc
|
||||
source.cc
|
||||
source_factory.cc
|
||||
strip_silence.cc
|
||||
svn_revision.cc
|
||||
tape_file_matcher.cc
|
||||
template_utils.cc
|
||||
|
||||
Reference in New Issue
Block a user