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 @ 4:370af5759bce

History | View | Annotate | Download (6.89 KB)

1
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
2

    
3
/*
4
    Vamp feature extraction plugin using MusicIP OFA library.
5

6
    See README for more information and licensing terms.
7
*/
8

    
9
#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
OfaVampPlugin::OfaVampPlugin(float inputSampleRate, Type type) :
27
    Plugin(inputSampleRate),
28
    m_type(type),
29
    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
    return "Chris Cannam, using MusicIP OFA library";
48
}
49

    
50
int
51
OfaVampPlugin::getPluginVersion() const
52
{
53
    return 1;
54
}
55

    
56
string
57
OfaVampPlugin::getCopyright() const
58
{
59
    return "GPL";
60
}
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
    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

    
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
        std::cerr << "realloc " << m_bufsiz/2 << " -> " << m_bufsiz << std::endl;
190
    }
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
        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
    }
239

    
240
    return FeatureSet();
241
}
242

    
243
OfaVampPlugin::FeatureSet
244
OfaVampPlugin::getRemainingFeatures()
245
{
246
    FeatureSet fset;
247

    
248
    if (m_print == "" || m_puidResultIndex < 0) return fset;
249

    
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
    } else {
283
        feature.label = info->getPUID();
284
        fset[m_puidResultIndex].push_back(feature);
285
    }
286

    
287
    return fset;
288
}
289

    
290
static Vamp::PluginAdapter<OfaFingerprintPlugin> ofaFingerprintAdapter;
291
static Vamp::PluginAdapter<OfaPUIDPlugin> ofaPUIDAdapter;
292

    
293
const VampPluginDescriptor *vampGetPluginDescriptor(unsigned int version,
294
                                                    unsigned int index)
295
{
296
    if (version < 1) return 0;
297

    
298
    switch (index) {
299
    case  0: return ofaFingerprintAdapter.getDescriptor();
300
    case  1: return ofaPUIDAdapter.getDescriptor();
301
    default: return 0;
302
    }
303
}
304