Fixes for GCC 4.3.
[ardour.git] / libs / ardour / audioanalyser.cc
1 #include <cstring>
2 #include <vamp-sdk/hostext/PluginLoader.h>
3 #include <glibmm/miscutils.h>
4 #include <glibmm/fileutils.h>
5 #include <glib/gstdio.h> // for g_remove()
6
7 #include <pbd/error.h>
8
9 #include <ardour/audioanalyser.h>
10 #include <ardour/readable.h>
11 #include <ardour/readable.h>
12
13 #include "i18n.h"
14
15 using namespace std;
16 using namespace Vamp;
17 using namespace PBD;
18 using namespace ARDOUR;
19
20 AudioAnalyser::AudioAnalyser (float sr, AnalysisPluginKey key)
21         : sample_rate (sr)
22         , plugin_key (key)
23 {
24         /* create VAMP plugin and initialize */
25         
26         if (initialize_plugin (plugin_key, sample_rate)) {
27                 error << string_compose (_("cannot load VAMP plugin \"%1\""), key) << endmsg;
28                 throw failed_constructor();
29         } 
30 }
31
32 AudioAnalyser::~AudioAnalyser ()
33 {
34         delete plugin;
35 }
36
37 int
38 AudioAnalyser::initialize_plugin (AnalysisPluginKey key, float sr)
39 {
40         using namespace Vamp::HostExt;
41
42         PluginLoader* loader (PluginLoader::getInstance());
43
44         plugin = loader->loadPlugin (key, sr, PluginLoader::ADAPT_ALL);
45
46         if (!plugin) {
47                 error << string_compose (_("VAMP Plugin \"%1\" could not be loaded"), key) << endmsg;
48                 return -1;
49         } 
50
51         /* we asked for the buffering adapter, so set the blocksize to
52            something that makes for efficient disk i/o
53         */
54
55         bufsize = 65536;
56         stepsize = bufsize;
57
58         if (plugin->getMinChannelCount() > 1) {
59                 delete plugin;
60                 return -1;
61         }
62
63         if (!plugin->initialise (1, stepsize, bufsize)) {
64                 delete plugin;
65                 return -1;
66         }
67
68         return 0;
69 }
70
71 void
72 AudioAnalyser::reset ()
73 {
74         if (plugin) {
75                 plugin->reset ();
76         }
77 }
78         
79 int
80 AudioAnalyser::analyse (const string& path, Readable* src, uint32_t channel)
81 {
82         ofstream ofile;
83         Plugin::FeatureSet features;
84         int ret = -1;
85         bool done = false;
86         Sample* data = 0;
87         nframes64_t len = src->readable_length();
88         nframes64_t pos = 0;
89         float* bufs[1] = { 0 };
90         string tmp_path;
91
92         if (!path.empty()) {
93
94                 /* store data in tmp file, not the real one */
95                 
96                 tmp_path = path;
97                 tmp_path += ".tmp";
98
99                 ofile.open (tmp_path.c_str());
100                 if (!ofile) {
101                         goto out;
102                 }
103         }
104
105         data = new Sample[bufsize];
106         bufs[0] = data;
107
108         while (!done) {
109
110                 nframes64_t to_read;
111                 
112                 /* read from source */
113
114                 to_read = min ((len - pos), bufsize);
115                 
116                 if (src->read (data, pos, to_read, channel) != to_read) {
117                         goto out;
118                 }
119
120                 /* zero fill buffer if necessary */
121
122                 if (to_read != bufsize) {
123                         memset (data + to_read, 0, (bufsize - to_read) * sizeof (Sample));
124                 }
125                 
126                 features = plugin->process (bufs, RealTime::fromSeconds ((double) pos / sample_rate));
127
128                 if (use_features (features, (path.empty() ? 0 : &ofile))) {
129                         goto out;
130                 }
131
132                 pos += min (stepsize, to_read);
133
134                 if (pos >= len) {
135                         done = true;
136                 }
137         }
138
139         /* finish up VAMP plugin */
140
141         features = plugin->getRemainingFeatures ();
142
143         if (use_features (features, (path.empty() ? &ofile : 0))) {
144                 goto out;
145         }
146
147         ret = 0;
148
149   out:
150         /* works even if it has not been opened */
151         ofile.close ();
152
153         if (ret) {
154                 g_remove (tmp_path.c_str());
155         } else if (!path.empty()) {
156                 /* move the data file to the requested path */
157                 g_rename (tmp_path.c_str(), path.c_str());
158         }
159
160         if (data) {
161                 delete [] data;
162         }
163
164         return ret;
165 }
166