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