To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.

Statistics Download as Zip
| Branch: | Revision:

root / OfaVampPlugin.cpp

History | View | Annotate | Download (7.02 KB)

1 1:150ad38c1871 cannam
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
2
3 2:8056c637875b cannam
/*
4 4:370af5759bce cannam
    Vamp feature extraction plugin using MusicIP OFA library.
5 2:8056c637875b cannam

6 4:370af5759bce cannam
    See README for more information and licensing terms.
7 2:8056c637875b cannam
*/
8
9 1:150ad38c1871 cannam
#include "OfaVampPlugin.h"
10
11
#include <vamp/vamp.h>
12
#include <vamp-sdk/PluginAdapter.h>
13
#include <vamp-sdk/RealTime.h>
14
15
#include <cstdlib>
16
#include <cmath>
17
18
#include <ofa1/ofa.h>
19
20
#include <endian.h>
21
22
#include "protocol.h"
23
24
using std::string;
25
26 2:8056c637875b cannam
OfaVampPlugin::OfaVampPlugin(float inputSampleRate, Type type) :
27 1:150ad38c1871 cannam
    Plugin(inputSampleRate),
28 2:8056c637875b cannam
    m_type(type),
29 1:150ad38c1871 cannam
    m_buffer(0),
30
    m_bufsiz(0),
31
    m_bufidx(0),
32
    m_channels(0),
33
    m_blockSize(0),
34
    m_totalCount(0),
35
    m_enough(false)
36
{
37
}
38
39
OfaVampPlugin::~OfaVampPlugin()
40
{
41
    if (m_buffer) free(m_buffer);
42
}
43
44
string
45
OfaVampPlugin::getMaker() const
46
{
47 2:8056c637875b cannam
    return "Chris Cannam, using MusicIP OFA library";
48 1:150ad38c1871 cannam
}
49
50
int
51
OfaVampPlugin::getPluginVersion() const
52
{
53
    return 1;
54
}
55
56
string
57
OfaVampPlugin::getCopyright() const
58
{
59 2:8056c637875b cannam
    return "GPL";
60 1:150ad38c1871 cannam
}
61
62
OfaVampPlugin::ParameterList
63
OfaVampPlugin::getParameterDescriptors() const
64
{
65
    ParameterList list;
66
67
    return list;
68
}
69
70
float
71
OfaVampPlugin::getParameter(std::string name) const
72
{
73
    return 0.0;
74
}
75
76
void
77
OfaVampPlugin::setParameter(std::string name, float value)
78
{
79
}
80
81
size_t
82
OfaVampPlugin::getPreferredStepSize() const
83
{
84
    return 0;
85
}
86
87
size_t
88
OfaVampPlugin::getPreferredBlockSize() const
89
{
90
    return 0;
91
}
92
93
bool
94
OfaVampPlugin::initialise(size_t channels, size_t stepSize, size_t blockSize)
95
{
96
    if (stepSize != blockSize) {
97
        std::cerr << "ERROR: OfaVampPlugin::initialise: stepSize must be equal to blockSize (" << stepSize << " != " << blockSize << ")" << std::endl;
98
        return false;
99
    }
100
101
    m_bufsiz = 1048576;
102
    m_buffer = (int16_t *)malloc(m_bufsiz * sizeof(int16_t));
103
    m_bufidx = 0;
104
    m_channels = channels;
105
    m_blockSize = blockSize;
106
    m_totalCount = 0;
107
    m_enough = false;
108
    return true;
109
}
110
111
void
112
OfaVampPlugin::reset()
113
{
114
    m_bufidx = 0;
115
    m_totalCount = 0;
116
    m_print = "";
117
    m_enough = false;
118
}
119
120
OfaVampPlugin::OutputList
121
OfaVampPlugin::getOutputDescriptors() const
122
{
123
    OutputList list;
124
125
    OutputDescriptor desc;
126
127 2:8056c637875b cannam
    m_fingerprintResultIndex = -1;
128
    m_puidResultIndex = -1;
129
    int index = 0;
130
131
    if (m_type == TypeFingerprint || m_type == TypeBoth) {
132
133
        desc.identifier = "fingerprint";
134
        desc.name = "Fingerprint";
135
        desc.description = "Single result containing the audio fingerprint as its label";
136
        desc.unit = "";
137
        desc.hasFixedBinCount = true;
138
        desc.binCount = 0;
139
        desc.hasKnownExtents = false;
140
        desc.isQuantized = false;
141
        desc.sampleType = OutputDescriptor::VariableSampleRate;
142
        desc.sampleRate = m_inputSampleRate;
143
        list.push_back(desc);
144
145
        m_fingerprintResultIndex = index;
146
        ++index;
147
    }
148
149
    if (m_type == TypePUID || m_type == TypeBoth) {
150
151
        desc.identifier = "puid";
152
        desc.name = "PUID";
153
        desc.description = "Single result containing the MusicIP online PUID for this audio track, if available";
154
        desc.unit = "";
155
        desc.hasFixedBinCount = true;
156
        desc.binCount = 0;
157
        desc.hasKnownExtents = false;
158
        desc.isQuantized = false;
159
        desc.sampleType = OutputDescriptor::VariableSampleRate;
160
        desc.sampleRate = m_inputSampleRate;
161
        list.push_back(desc);
162
163
        m_puidResultIndex = index;
164
        ++index;
165
    }
166 1:150ad38c1871 cannam
167
    return list;
168
}
169
170
// client id: a008bd70c9d3c681e2ff336e3ceaa6dc (limited)
171
172
OfaVampPlugin::FeatureSet
173
OfaVampPlugin::process(const float *const *inputBuffers,
174
                       Vamp::RealTime timestamp)
175
{
176
    m_totalCount += m_blockSize;
177
178
    if (m_enough) return FeatureSet();
179
180
    // libofa requires the first 135 seconds of audio (where available)
181
    size_t reqd = lrintf(ceil(135.f * m_inputSampleRate));
182
183
    size_t effectiveChannels = m_channels;
184
    if (effectiveChannels > 2) effectiveChannels = 2;
185
186
    if (m_bufidx + m_blockSize * effectiveChannels > m_bufsiz) {
187
        m_bufsiz *= 2;
188
        m_buffer = (int16_t *)realloc(m_buffer, m_bufsiz * sizeof(int16_t));
189 7:9b8599d10aa2 cannam
//        std::cerr << "realloc " << m_bufsiz/2 << " -> " << m_bufsiz << std::endl;
190 1:150ad38c1871 cannam
    }
191
192
    for (size_t i = 0; i < m_blockSize; ++i) {
193
        for (size_t c = 0; c < effectiveChannels; ++c) {
194
            m_buffer[m_bufidx + i * effectiveChannels + c] =
195
                int16_t(inputBuffers[c][i] * 32767.0);
196
        }
197
    }
198
199
    m_bufidx += m_blockSize * effectiveChannels;
200
201
    if (m_bufidx >= reqd * effectiveChannels) {
202
203
        m_enough = true;
204
205
        FeatureSet fset;
206
207
        int endian = OFA_LITTLE_ENDIAN;
208
209
#ifdef __BYTE_ORDER
210
#if __BYTE_ORDER == _BIG_ENDIAN
211
        endian = OFA_BIG_ENDIAN;
212
#endif
213
#endif
214
215
        const char *print = ofa_create_print
216
            ((unsigned char *)m_buffer,
217
             endian,
218
             m_bufidx,
219
             lrintf(m_inputSampleRate),
220
             m_channels > 1);
221
222
        if (!print) {
223
            std::cerr << "OfaVampPlugin: ERROR from libofa" << std::endl;
224
            return fset;
225
        }
226
227
        m_print = print;
228
229 2:8056c637875b cannam
        if (m_fingerprintResultIndex >= 0) {
230
231
            Feature feature;
232
            feature.hasTimestamp = true;
233
            feature.timestamp = Vamp::RealTime::zeroTime;
234
            feature.label = m_print;
235
            fset[m_fingerprintResultIndex].push_back(feature);
236
            return fset;
237
        }
238 1:150ad38c1871 cannam
    }
239
240
    return FeatureSet();
241
}
242
243
OfaVampPlugin::FeatureSet
244
OfaVampPlugin::getRemainingFeatures()
245
{
246
    FeatureSet fset;
247
248 2:8056c637875b cannam
    if (m_print == "" || m_puidResultIndex < 0) return fset;
249 1:150ad38c1871 cannam
250
    Feature feature;
251
    feature.hasTimestamp = true;
252
    feature.timestamp = Vamp::RealTime::zeroTime;
253
254
    int endian = OFA_LITTLE_ENDIAN;
255
256
#ifdef __BYTE_ORDER
257
#if __BYTE_ORDER == _BIG_ENDIAN
258
        endian = OFA_BIG_ENDIAN;
259
#endif
260
#endif
261
262
    AudioData data;
263
    data.setData
264
        (0,
265
         endian,
266
         m_bufidx,
267
         lrintf(m_inputSampleRate),
268
         m_channels > 1,
269
         lrintf((m_totalCount * 1000.f) / m_inputSampleRate), //!!! approx
270
         "wav"); //!!!
271
272
    data.info.setPrint(m_print);
273
274
    TrackInformation *info = data.getMetadata
275
        ("a008bd70c9d3c681e2ff336e3ceaa6dc",
276
         "1",
277
         false);
278
279
    if (!info) {
280
        std::cerr << "OfaVampPlugin: ERROR from ofa/protocol, unable to retrieve PUID for fingerprint" << std::endl;
281
        std::cerr << "Fingerprint was: " << m_print << std::endl;
282 7:9b8599d10aa2 cannam
    } else if (info->getPUID() != "") {
283 1:150ad38c1871 cannam
        feature.label = info->getPUID();
284 2:8056c637875b cannam
        fset[m_puidResultIndex].push_back(feature);
285 1:150ad38c1871 cannam
    }
286
287
    return fset;
288
}
289
290 2:8056c637875b cannam
static Vamp::PluginAdapter<OfaFingerprintPlugin> ofaFingerprintAdapter;
291
static Vamp::PluginAdapter<OfaPUIDPlugin> ofaPUIDAdapter;
292 7:9b8599d10aa2 cannam
static Vamp::PluginAdapter<OfaBothPlugin> ofaBothAdapter;
293 1:150ad38c1871 cannam
294
const VampPluginDescriptor *vampGetPluginDescriptor(unsigned int version,
295
                                                    unsigned int index)
296
{
297
    if (version < 1) return 0;
298
299
    switch (index) {
300 2:8056c637875b cannam
    case  0: return ofaFingerprintAdapter.getDescriptor();
301
    case  1: return ofaPUIDAdapter.getDescriptor();
302 7:9b8599d10aa2 cannam
    case  2: return ofaBothAdapter.getDescriptor();
303 1:150ad38c1871 cannam
    default: return 0;
304
    }
305
}