ardour
audioanalyser.cc
Go to the documentation of this file.
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 <cstring>
21 
22 #include <vamp-hostsdk/PluginLoader.h>
23 
24 #include <glibmm/miscutils.h>
25 #include <glibmm/fileutils.h>
26 #include <glib/gstdio.h> // for g_remove()
27 
28 #include "pbd/error.h"
29 #include "pbd/failed_constructor.h"
30 
31 #include "ardour/audioanalyser.h"
32 #include "ardour/readable.h"
33 
34 #include <cstring>
35 
36 #include "i18n.h"
37 
38 using namespace std;
39 using namespace Vamp;
40 using namespace PBD;
41 using namespace ARDOUR;
42 
43 AudioAnalyser::AudioAnalyser (float sr, AnalysisPluginKey key)
44  : sample_rate (sr)
45  , plugin_key (key)
46 {
47  /* create VAMP plugin and initialize */
48 
50  error << string_compose (_("cannot load VAMP plugin \"%1\""), key) << endmsg;
51  throw failed_constructor();
52  }
53 }
54 
56 {
57  delete plugin;
58 }
59 
60 int
62 {
63  using namespace Vamp::HostExt;
64 
65  PluginLoader* loader (PluginLoader::getInstance());
66 
67  plugin = loader->loadPlugin (key, sr, PluginLoader::ADAPT_ALL_SAFE);
68 
69  if (!plugin) {
70  error << string_compose (_("VAMP Plugin \"%1\" could not be loaded"), key) << endmsg;
71  return -1;
72  }
73 
74  /* we asked for the buffering adapter, so set the blocksize to
75  something that makes for efficient disk i/o
76  */
77 
78  bufsize = 1024;
79  stepsize = 512;
80 
81  if (plugin->getMinChannelCount() > 1) {
82  delete plugin;
83  return -1;
84  }
85 
86  if (!plugin->initialise (1, stepsize, bufsize)) {
87  delete plugin;
88  return -1;
89  }
90 
91  return 0;
92 }
93 
94 void
96 {
97  if (plugin) {
98  plugin->reset ();
99  }
100 }
101 
102 int
103 AudioAnalyser::analyse (const string& path, Readable* src, uint32_t channel)
104 {
105  ofstream ofile;
106  Plugin::FeatureSet features;
107  int ret = -1;
108  bool done = false;
109  Sample* data = 0;
110  framecnt_t len = src->readable_length();
111  framepos_t pos = 0;
112  float* bufs[1] = { 0 };
113  string tmp_path;
114 
115  if (!path.empty()) {
116 
117  /* store data in tmp file, not the real one */
118 
119  tmp_path = path;
120  tmp_path += ".tmp";
121 
122  ofile.open (tmp_path.c_str());
123  if (!ofile) {
124  goto out;
125  }
126  }
127 
128  data = new Sample[bufsize];
129  bufs[0] = data;
130 
131  while (!done) {
132 
133  framecnt_t to_read;
134 
135  /* read from source */
136 
137  to_read = min ((len - pos), (framecnt_t) bufsize);
138 
139  if (src->read (data, pos, to_read, channel) != to_read) {
140  goto out;
141  }
142 
143  /* zero fill buffer if necessary */
144 
145  if (to_read != bufsize) {
146  memset (data + to_read, 0, (bufsize - to_read) * sizeof (Sample));
147  }
148 
149  features = plugin->process (bufs, RealTime::fromSeconds ((double) pos / sample_rate));
150 
151  if (use_features (features, (path.empty() ? 0 : &ofile))) {
152  goto out;
153  }
154 
155  pos += min (stepsize, to_read);
156 
157  if (pos >= len) {
158  done = true;
159  }
160  }
161 
162  /* finish up VAMP plugin */
163 
164  features = plugin->getRemainingFeatures ();
165 
166  if (use_features (features, (path.empty() ? &ofile : 0))) {
167  goto out;
168  }
169 
170  ret = 0;
171 
172  out:
173  /* works even if it has not been opened */
174  ofile.close ();
175 
176  if (ret) {
177  g_remove (tmp_path.c_str());
178  } else if (!path.empty()) {
179  /* move the data file to the requested path */
180  g_rename (tmp_path.c_str(), path.c_str());
181  }
182 
183  delete [] data;
184 
185  return ret;
186 }
187 
virtual int use_features(Vamp::Plugin::FeatureSet &, std::ostream *)=0
int initialize_plugin(AnalysisPluginKey name, float sample_rate)
int analyse(const std::string &path, Readable *, uint32_t channel)
Definition: Beats.hpp:239
LIBPBD_API Transmitter error
std::ostream & endmsg(std::ostream &ostr)
Definition: transmitter.h:71
virtual framecnt_t read(Sample *, framepos_t pos, framecnt_t cnt, int channel) const =0
AnalysisPluginKey plugin_key
Definition: audioanalyser.h:58
#define _(Text)
Definition: i18n.h:11
virtual framecnt_t readable_length() const =0
int64_t framecnt_t
Definition: types.h:76
float Sample
Definition: types.h:54
Definition: amp.h:29
AnalysisPlugin * plugin
Definition: audioanalyser.h:57
int64_t framepos_t
Definition: types.h:66
std::string AnalysisPluginKey
Definition: audioanalyser.h:41
Definition: debug.h:30
std::string string_compose(const std::string &fmt, const T1 &o1)
Definition: compose.h:208