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 @ 1:150ad38c1871

History | View | Annotate | Download (6.32 KB)

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

    
3
#include "OfaVampPlugin.h"
4

    
5
#include <vamp/vamp.h>
6
#include <vamp-sdk/PluginAdapter.h>
7
#include <vamp-sdk/RealTime.h>
8

    
9
#include <cstdlib>
10
#include <cmath>
11

    
12
#include <ofa1/ofa.h>
13

    
14
#include <endian.h>
15

    
16
#include "protocol.h"
17

    
18
using std::string;
19

    
20
OfaVampPlugin::OfaVampPlugin(float inputSampleRate) :
21
    Plugin(inputSampleRate),
22
    m_buffer(0),
23
    m_bufsiz(0),
24
    m_bufidx(0),
25
    m_channels(0),
26
    m_blockSize(0),
27
    m_totalCount(0),
28
    m_enough(false)
29
{
30
}
31

    
32
OfaVampPlugin::~OfaVampPlugin()
33
{
34
    if (m_buffer) free(m_buffer);
35
}
36

    
37
string
38
OfaVampPlugin::getIdentifier() const
39
{
40
    return "ofa";
41
}
42

    
43
string
44
OfaVampPlugin::getName() const
45
{
46
    return "MusicIP OFA Audio Fingerprinter";
47
}
48

    
49
string
50
OfaVampPlugin::getDescription() const
51
{
52
    return "Calculates an audio fingerprint using the MusicIP fingerprinting library";
53
}
54

    
55
string
56
OfaVampPlugin::getMaker() const
57
{
58
    return "Chris Cannam";
59
}
60

    
61
int
62
OfaVampPlugin::getPluginVersion() const
63
{
64
    return 1;
65
}
66

    
67
string
68
OfaVampPlugin::getCopyright() const
69
{
70
    return ""; //!!!
71
}
72

    
73
OfaVampPlugin::ParameterList
74
OfaVampPlugin::getParameterDescriptors() const
75
{
76
    ParameterList list;
77

    
78
    return list;
79
}
80

    
81
float
82
OfaVampPlugin::getParameter(std::string name) const
83
{
84
    return 0.0;
85
}
86

    
87
void
88
OfaVampPlugin::setParameter(std::string name, float value)
89
{
90
}
91

    
92
size_t
93
OfaVampPlugin::getPreferredStepSize() const
94
{
95
    return 0;
96
}
97

    
98
size_t
99
OfaVampPlugin::getPreferredBlockSize() const
100
{
101
    return 0;
102
}
103

    
104
bool
105
OfaVampPlugin::initialise(size_t channels, size_t stepSize, size_t blockSize)
106
{
107
    if (stepSize != blockSize) {
108
        std::cerr << "ERROR: OfaVampPlugin::initialise: stepSize must be equal to blockSize (" << stepSize << " != " << blockSize << ")" << std::endl;
109
        return false;
110
    }
111

    
112
    m_bufsiz = 1048576;
113
    m_buffer = (int16_t *)malloc(m_bufsiz * sizeof(int16_t));
114
    m_bufidx = 0;
115
    m_channels = channels;
116
    m_blockSize = blockSize;
117
    m_totalCount = 0;
118
    m_enough = false;
119
    return true;
120
}
121

    
122
void
123
OfaVampPlugin::reset()
124
{
125
    m_bufidx = 0;
126
    m_totalCount = 0;
127
    m_print = "";
128
    m_enough = false;
129
}
130

    
131
OfaVampPlugin::OutputList
132
OfaVampPlugin::getOutputDescriptors() const
133
{
134
    OutputList list;
135

    
136
    OutputDescriptor desc;
137
    desc.identifier = "fingerprint";
138
    desc.name = "Fingerprint";
139
    desc.description = "Single result containing the audio fingerprint as its label";
140
    desc.unit = "";
141
    desc.hasFixedBinCount = true;
142
    desc.binCount = 0;
143
    desc.hasKnownExtents = false;
144
    desc.isQuantized = false;
145
    desc.sampleType = OutputDescriptor::VariableSampleRate;
146
    desc.sampleRate = m_inputSampleRate;
147
    list.push_back(desc);
148

    
149
    desc.identifier = "puid";
150
    desc.name = "PUID";
151
    desc.description = "Single result containing the MusicIP online PUID for this audio track, if available";
152
    desc.unit = "";
153
    desc.hasFixedBinCount = true;
154
    desc.binCount = 0;
155
    desc.hasKnownExtents = false;
156
    desc.isQuantized = false;
157
    desc.sampleType = OutputDescriptor::VariableSampleRate;
158
    desc.sampleRate = m_inputSampleRate;
159
    list.push_back(desc);
160

    
161
    return list;
162
}
163

    
164
// client id: a008bd70c9d3c681e2ff336e3ceaa6dc (limited)
165

    
166
OfaVampPlugin::FeatureSet
167
OfaVampPlugin::process(const float *const *inputBuffers,
168
                       Vamp::RealTime timestamp)
169
{
170
    m_totalCount += m_blockSize;
171

    
172
    if (m_enough) return FeatureSet();
173

    
174
    // libofa requires the first 135 seconds of audio (where available)
175
    size_t reqd = lrintf(ceil(135.f * m_inputSampleRate));
176

    
177
    size_t effectiveChannels = m_channels;
178
    if (effectiveChannels > 2) effectiveChannels = 2;
179

    
180
    if (m_bufidx + m_blockSize * effectiveChannels > m_bufsiz) {
181
        m_bufsiz *= 2;
182
        m_buffer = (int16_t *)realloc(m_buffer, m_bufsiz * sizeof(int16_t));
183
        std::cerr << "realloc " << m_bufsiz/2 << " -> " << m_bufsiz << std::endl;
184
    }
185

    
186
    for (size_t i = 0; i < m_blockSize; ++i) {
187
        for (size_t c = 0; c < effectiveChannels; ++c) {
188
            m_buffer[m_bufidx + i * effectiveChannels + c] = 
189
                int16_t(inputBuffers[c][i] * 32767.0);
190
        }
191
    }
192
    
193
    m_bufidx += m_blockSize * effectiveChannels;
194

    
195
    if (m_bufidx >= reqd * effectiveChannels) {
196

    
197
        m_enough = true;
198

    
199
        FeatureSet fset;
200

    
201
        int endian = OFA_LITTLE_ENDIAN;
202

    
203
#ifdef __BYTE_ORDER
204
#if __BYTE_ORDER == _BIG_ENDIAN
205
        endian = OFA_BIG_ENDIAN;
206
#endif
207
#endif
208

    
209
        const char *print = ofa_create_print
210
            ((unsigned char *)m_buffer,
211
             endian,
212
             m_bufidx,
213
             lrintf(m_inputSampleRate),
214
             m_channels > 1);
215
        
216
        if (!print) {
217
            std::cerr << "OfaVampPlugin: ERROR from libofa" << std::endl;
218
            return fset;
219
        }
220

    
221
        m_print = print;
222

    
223
        Feature feature;
224
        feature.hasTimestamp = true;
225
        feature.timestamp = Vamp::RealTime::zeroTime;
226
        feature.label = m_print;
227
        fset[0].push_back(feature);
228
        return fset;
229
    }
230

    
231
    return FeatureSet();
232
}
233

    
234
OfaVampPlugin::FeatureSet
235
OfaVampPlugin::getRemainingFeatures()
236
{
237
    FeatureSet fset;
238

    
239
    if (m_print == "") return fset;
240

    
241
    Feature feature;
242
    feature.hasTimestamp = true;
243
    feature.timestamp = Vamp::RealTime::zeroTime;
244

    
245
    int endian = OFA_LITTLE_ENDIAN;
246

    
247
#ifdef __BYTE_ORDER
248
#if __BYTE_ORDER == _BIG_ENDIAN
249
        endian = OFA_BIG_ENDIAN;
250
#endif
251
#endif
252

    
253
    AudioData data;
254
    data.setData
255
        (0, 
256
         endian,
257
         m_bufidx,
258
         lrintf(m_inputSampleRate),
259
         m_channels > 1,
260
         lrintf((m_totalCount * 1000.f) / m_inputSampleRate), //!!! approx
261
         "wav"); //!!!
262

    
263
    data.info.setPrint(m_print);
264

    
265
    TrackInformation *info = data.getMetadata
266
        ("a008bd70c9d3c681e2ff336e3ceaa6dc",
267
         "1",
268
         false);
269
    
270
    if (!info) {
271
        std::cerr << "OfaVampPlugin: ERROR from ofa/protocol, unable to retrieve PUID for fingerprint" << std::endl;
272
        std::cerr << "Fingerprint was: " << m_print << std::endl;
273
    } else {
274
        feature.label = info->getPUID();
275
        fset[1].push_back(feature);
276
    }
277

    
278
    return fset;
279
}
280

    
281
static Vamp::PluginAdapter<OfaVampPlugin> ofaAdapter;
282

    
283
const VampPluginDescriptor *vampGetPluginDescriptor(unsigned int version,
284
                                                    unsigned int index)
285
{
286
    if (version < 1) return 0;
287

    
288
    switch (index) {
289
    case  0: return ofaAdapter.getDescriptor();
290
    default: return 0;
291
    }
292
}
293