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