X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;ds=sidebyside;f=libs%2Fardour%2Ftransient_detector.cc;h=6eed8369a777c9c0ea4c19a8d2685f37999bb301;hb=b25cd7683b25a502094a2ecefbadb4b7d6e6db09;hp=b92bf5fb2de61a2034154c901f79881efca0b4db;hpb=80c3677c837cc9eb432df3d65a34aba543fa7258;p=ardour.git diff --git a/libs/ardour/transient_detector.cc b/libs/ardour/transient_detector.cc index b92bf5fb2d..6eed8369a7 100644 --- a/libs/ardour/transient_detector.cc +++ b/libs/ardour/transient_detector.cc @@ -1,23 +1,41 @@ -#include +/* + Copyright (C) 2012 Paul Davis -#include "i18n.h" + 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include + +#include "ardour/readable.h" +#include "ardour/transient_detector.h" + +#include "pbd/i18n.h" using namespace Vamp; using namespace ARDOUR; using namespace std; -string TransientDetector::_op_id; +/* need a static initializer function for this */ + +string TransientDetector::_op_id = X_("qm-onset"); TransientDetector::TransientDetector (float sr) - : AudioAnalyser (sr, X_("libardourvampplugins:percussiononsets")) + : AudioAnalyser (sr, X_("libardourvampplugins:qm-onsetdetector")) { - if (_op_id.empty()) { - _op_id = X_("libardourvampplugins:percussiononsets"); - - // XXX this should load the above-named plugin and get the current version - - _op_id += ":2"; - } + threshold = 0.00; } TransientDetector::~TransientDetector() @@ -37,6 +55,7 @@ TransientDetector::run (const std::string& path, Readable* src, uint32_t channel int ret = analyse (path, src, channel); current_results = 0; + return ret; } @@ -46,14 +65,14 @@ TransientDetector::use_features (Plugin::FeatureSet& features, ostream* out) const Plugin::FeatureList& fl (features[0]); for (Plugin::FeatureList::const_iterator f = fl.begin(); f != fl.end(); ++f) { - - if ((*f).hasTimestamp) { + + if (f->hasTimestamp) { if (out) { (*out) << (*f).timestamp.toString() << endl; - } + } - current_results->push_back (RealTime::realTime2Frame ((*f).timestamp, (nframes_t) floor(sample_rate))); + current_results->push_back (RealTime::realTime2Frame (f->timestamp, (framecnt_t) floor(sample_rate))); } } @@ -63,16 +82,19 @@ TransientDetector::use_features (Plugin::FeatureSet& features, ostream* out) void TransientDetector::set_threshold (float val) { - if (plugin) { - plugin->setParameter ("threshold", val); - } + threshold = val; } void -TransientDetector::set_sensitivity (float val) +TransientDetector::set_sensitivity (uint32_t mode, float val) { if (plugin) { - plugin->setParameter ("sensitivity", val); + // see libs/vamp-plugins/OnsetDetect.cpp + //plugin->selectProgram ("General purpose"); // dftype = 3, sensitivity = 50, whiten = 0 (default) + //plugin->selectProgram ("Percussive onsets"); // dftype = 4, sensitivity = 40, whiten = 0 + plugin->setParameter ("dftype", mode); + plugin->setParameter ("sensitivity", std::min (100.f, std::max (0.f, val))); + plugin->setParameter ("whiten", 0); } } @@ -84,24 +106,24 @@ TransientDetector::cleanup_transients (AnalysisFeatureList& t, float sr, float g } t.sort (); - + /* remove duplicates or other things that are too close */ - + AnalysisFeatureList::iterator i = t.begin(); AnalysisFeatureList::iterator f, b; - const nframes64_t gap_frames = (nframes64_t) floor (gap_msecs * (sr / 1000.0)); - + const framecnt_t gap_frames = (framecnt_t) floor (gap_msecs * (sr / 1000.0)); + while (i != t.end()) { // move front iterator to just past i, and back iterator the same place - + f = i; ++f; b = f; // move f until we find a new value that is far enough away - - while ((f != t.end()) && (((*f) - (*i)) < gap_frames)) { + + while ((f != t.end()) && gap_frames > 0 && (((*f) - (*i)) < gap_frames)) { ++f; } @@ -114,3 +136,44 @@ TransientDetector::cleanup_transients (AnalysisFeatureList& t, float sr, float g } } } + +void +TransientDetector::update_positions (Readable* src, uint32_t channel, AnalysisFeatureList& positions) +{ + int const buff_size = 1024; + int const step_size = 64; + + Sample* data = new Sample[buff_size]; + + AnalysisFeatureList::iterator i = positions.begin(); + + while (i != positions.end()) { + + /* read from source */ + framecnt_t const to_read = buff_size; + + if (src->read (data, (*i) - buff_size, to_read, channel) != to_read) { + break; + } + + // Simple heuristic for locating approx correct cut position. + + for (int j = 0; j < (buff_size - step_size); ) { + + Sample const s = abs (data[j]); + Sample const s2 = abs (data[j + step_size]); + + if ((s2 - s) > threshold) { + //cerr << "Thresh exceeded. Moving pos from: " << (*i) << " to: " << (*i) - buff_size + (j + 16) << endl; + (*i) = (*i) - buff_size + (j + 24); + break; + } + + j += step_size; + } + + ++i; + } + + delete [] data; +}