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