1 /*
2 * Copyright (C) 2008-2017 Paul Davis <paul@linuxaudiosystems.com>
3 * Copyright (C) 2009-2010 David Robillard <d@drobilla.net>
4 * Copyright (C) 2015-2016 Robin Gareus <robin@gareus.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20
21 #include <cmath>
22 #include "ardour/onset_detector.h"
23
24 #include "pbd/i18n.h"
25
26 using namespace Vamp;
27 using namespace ARDOUR;
28 using namespace std;
29
30 /* need a static initializer function for this */
31
32 string OnsetDetector::_op_id = X_("aubio-onset");
33
OnsetDetector(float sr)34 OnsetDetector::OnsetDetector (float sr)
35 : AudioAnalyser (sr, X_("libardourvampplugins:aubioonset"))
36 , current_results (0)
37 {
38 }
39
~OnsetDetector()40 OnsetDetector::~OnsetDetector()
41 {
42 }
43
44 string
operational_identifier()45 OnsetDetector::operational_identifier()
46 {
47 return _op_id;
48 }
49
50 int
run(const std::string & path,Readable * src,uint32_t channel,AnalysisFeatureList & results)51 OnsetDetector::run (const std::string& path, Readable* src, uint32_t channel, AnalysisFeatureList& results)
52 {
53 current_results = &results;
54 int ret = analyse (path, src, channel);
55
56 current_results = 0;
57 return ret;
58 }
59
60 int
use_features(Plugin::FeatureSet & features,ostream * out)61 OnsetDetector::use_features (Plugin::FeatureSet& features, ostream* out)
62 {
63 const Plugin::FeatureList& fl (features[0]);
64
65 for (Plugin::FeatureList::const_iterator f = fl.begin(); f != fl.end(); ++f) {
66
67 if ((*f).hasTimestamp) {
68
69 if (out) {
70 (*out) << (*f).timestamp.toString() << endl;
71 }
72
73 current_results->push_back (RealTime::realTime2Frame ((*f).timestamp, (samplecnt_t) floor(sample_rate)));
74 }
75 }
76
77 return 0;
78 }
79
80 void
set_silence_threshold(float val)81 OnsetDetector::set_silence_threshold (float val)
82 {
83 if (plugin) {
84 plugin->setParameter ("silencethreshold", val);
85 }
86 }
87
88 void
set_peak_threshold(float val)89 OnsetDetector::set_peak_threshold (float val)
90 {
91 if (plugin) {
92 plugin->setParameter ("peakpickthreshold", val);
93 }
94 }
95
96 void
set_minioi(float val)97 OnsetDetector::set_minioi (float val)
98 {
99 #ifdef HAVE_AUBIO4
100 if (plugin) {
101 plugin->setParameter ("minioi", val);
102 }
103 #endif
104 }
105
106 void
set_function(int val)107 OnsetDetector::set_function (int val)
108 {
109 if (plugin) {
110 plugin->setParameter ("onsettype", (float) val);
111 }
112 }
113
114 void
cleanup_onsets(AnalysisFeatureList & t,float sr,float gap_msecs)115 OnsetDetector::cleanup_onsets (AnalysisFeatureList& t, float sr, float gap_msecs)
116 {
117 if (t.empty()) {
118 return;
119 }
120
121 t.sort ();
122
123 /* remove duplicates or other things that are too close */
124
125 AnalysisFeatureList::iterator i = t.begin();
126 AnalysisFeatureList::iterator f, b;
127 const samplecnt_t gap_samples = (samplecnt_t) floor (gap_msecs * (sr / 1000.0));
128
129 while (i != t.end()) {
130
131 // move front iterator to just past i, and back iterator the same place
132
133 f = i;
134 ++f;
135 b = f;
136
137 // move f until we find a new value that is far enough away
138
139 while ((f != t.end()) && (((*f) - (*i)) < gap_samples)) {
140 ++f;
141 }
142
143 i = f;
144
145 // if f moved forward from b, we had duplicates/too-close points: get rid of them
146
147 if (b != f) {
148 t.erase (b, f);
149 }
150 }
151 }
152