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: | Tag: | Revision:

root / Test.cpp @ 63:d19bbfc055ab

History | View | Annotate | Download (13.1 KB)

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

    
3
/*
4
    Vamp Plugin Fuzz Tester
5
    Chris Cannam, cannam@all-day-breakfast.com
6
    Centre for Digital Music, Queen Mary, University of London.
7
    Copyright 2009-2014 QMUL.
8

9
    This program loads a Vamp plugin and tests its susceptibility to a
10
    number of common pitfalls, including handling of extremes of input
11
    data.  If you can think of any additional useful tests that are
12
    easily added, please send them to me.
13
  
14
    Permission is hereby granted, free of charge, to any person
15
    obtaining a copy of this software and associated documentation
16
    files (the "Software"), to deal in the Software without
17
    restriction, including without limitation the rights to use, copy,
18
    modify, merge, publish, distribute, sublicense, and/or sell copies
19
    of the Software, and to permit persons to whom the Software is
20
    furnished to do so, subject to the following conditions:
21

22
    The above copyright notice and this permission notice shall be
23
    included in all copies or substantial portions of the Software.
24

25
    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26
    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27
    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28
    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
29
    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
30
    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31
    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32

33
    Except as contained in this notice, the names of the Centre for
34
    Digital Music; Queen Mary, University of London; and Chris Cannam
35
    shall not be used in advertising or otherwise to promote the sale,
36
    use or other dealings in this Software without prior written
37
    authorization.
38
*/
39

    
40
#include "Test.h"
41

    
42
#include <vamp-hostsdk/PluginLoader.h>
43

    
44
using namespace Vamp;
45
using namespace Vamp::HostExt;
46

    
47
#include <math.h>
48

    
49
#ifdef __SUNPRO_CC
50
#include <ieeefp.h>
51
#define isinf(x) (!finite(x))
52
#endif
53

    
54
Test::Test() { }
55
Test::~Test() { }
56

    
57
using std::cerr;
58
using std::cout;
59
using std::endl;
60
using std::string;
61

    
62
Plugin *
63
Test::load(string key, float rate)
64
{
65
    Plugin *p = PluginLoader::getInstance()->loadPlugin
66
        (key, rate, PluginLoader::ADAPT_ALL);
67
    if (!p) throw FailedToLoadPlugin();
68
    return p;
69
}
70

    
71
float **
72
Test::createBlock(size_t channels, size_t blocksize)
73
{
74
    float **b = new float *[channels];
75
    for (size_t c = 0; c < channels; ++c) {
76
        b[c] = new float[blocksize];
77
    }
78
    return b;
79
}
80

    
81
void
82
Test::destroyBlock(float **blocks, size_t channels)
83
{
84
    for (size_t c = 0; c < channels; ++c) {
85
        delete[] blocks[c];
86
    }
87
    delete[] blocks;
88
}
89

    
90
float **
91
Test::createTestAudio(size_t channels, size_t blocksize, size_t blocks)
92
{
93
    float **b = new float *[channels];
94
    for (size_t c = 0; c < channels; ++c) {
95
        b[c] = new float[blocksize * blocks];
96
        for (int i = 0; i < int(blocksize * blocks); ++i) {
97
            b[c][i] = sinf(float(i) / 10.f);
98
            if (i == 5005 || i == 20002) {
99
                b[c][i-2] = 0;
100
                b[c][i-1] = -1;
101
                b[c][i] = 1;
102
            }
103
        }
104
    }
105
    return b;
106
}
107

    
108
void
109
Test::destroyTestAudio(float **b, size_t channels)
110
{
111
    for (size_t c = 0; c < channels; ++c) {
112
        delete[] b[c];
113
    }
114
    delete[] b;
115
}
116

    
117
bool
118
Test::initDefaults(Plugin *p, size_t &channels, size_t &step, size_t &block,
119
                   Results &r)
120
{
121
    channels = p->getMinChannelCount();
122
    block = p->getPreferredBlockSize();
123
    step = p->getPreferredStepSize();
124
    if (block == 0) block = 1024;
125
    if (step == 0) {
126
        if (p->getInputDomain() == Plugin::FrequencyDomain) step = block/2;
127
        else step = block;
128
    }
129
    if (!p->initialise(channels, step, block)) {
130
        r.push_back(error("initialisation with default values failed"));
131
        return false;
132
    }
133
    return true;
134
}
135

    
136
bool
137
Test::initAdapted(Plugin *p, size_t &channels, size_t step, size_t block,
138
                  Results &r)
139
{
140
    channels = p->getMinChannelCount();
141
    if (!p->initialise(channels, step, block)) {
142
        r.push_back(error("initialisation failed"));
143
        return false;
144
    }
145
    return true;
146
}
147

    
148
void
149
Test::appendFeatures(Plugin::FeatureSet &a, const Plugin::FeatureSet &b)
150
{
151
    for (Plugin::FeatureSet::const_iterator i = b.begin(); i != b.end(); ++i) {
152
        int output = i->first;
153
        const Plugin::FeatureList &fl = i->second;
154
        Plugin::FeatureList &target = a[output];
155
        for (Plugin::FeatureList::const_iterator j = fl.begin(); j != fl.end(); ++j) {
156
            target.push_back(*j);
157
        }
158
    }
159
}
160

    
161
bool
162
Test::allFeaturesValid(const Plugin::FeatureSet &b)
163
{
164
    for (Plugin::FeatureSet::const_iterator i = b.begin(); i != b.end(); ++i) {
165
        for (int j = 0; j < (int)i->second.size(); ++j) {
166
            if (i->second[j].values.empty()) continue;
167
            for (int k = 0; k < (int)i->second[j].values.size(); ++k) {
168
                if (isnan(i->second[j].values[k]) ||
169
                    isinf(i->second[j].values[k])) {
170
                    return false;
171
                }
172
            }
173
        }
174
    }
175
    return true;
176
}
177

    
178
bool
179
Test::containsTimestamps(const Plugin::FeatureSet &b)
180
{
181
    for (Plugin::FeatureSet::const_iterator i = b.begin(); i != b.end(); ++i) {
182
        for (int j = 0; j < (int)i->second.size(); ++j) {
183
            if (i->second[j].values.empty()) continue;
184
            for (int k = 0; k < (int)i->second[j].values.size(); ++k) {
185
                if (i->second[j].hasTimestamp) {
186
                    return true;
187
                }
188
            }
189
        }
190
    }
191
    return false;
192
}
193

    
194
void
195
Test::dumpFeature(const Plugin::Feature &f, bool showValues,
196
                  const Plugin::Feature *other)
197
{
198
    cout << "    Timestamp: " << (!f.hasTimestamp ? "(none)" : f.timestamp.toText()) << endl;
199
    cout << "    Duration: " << (!f.hasDuration ? "(none)" : f.duration.toText()) << endl;
200
    cout << "    Label: " << (f.label == "" ? "(none)" : f.label) << endl;
201
    if (showValues) {
202
        cout << "    Values (" << f.values.size() << "): " << (f.values.empty() ? "(none)" : "");
203
        int n = f.values.size();
204
        if (!other) {
205
            for (int j = 0; j < n; ++j) {
206
                cout << f.values[j] << " ";
207
            }
208
        } else {
209
            int samecount = 0;
210
            int diffcount = 0;
211
            for (int j = 0; j <= n; ++j) {
212
                if (j < n && f.values[j] == other->values[j]) {
213
                    ++samecount;
214
                } else {
215
                    if (samecount > 0) {
216
                        cout << "(" << samecount << " identical) ";
217
                    }
218
                    samecount = 0;
219
                    if (j < n) {
220
                        ++diffcount;
221
                        if (diffcount > 20 && j + 10 < n) {
222
                            cout << "(remaining " << n - j << " values elided)";
223
                            break;
224
                        } else {
225
                            cout << f.values[j] << " [diff "
226
                                 << f.values[j] - other->values[j] << "] ";
227
                        }
228
                    }
229
                }
230
            }
231
        }
232
        cout << endl;
233
    } else {
234
        cout << "    Values (" << f.values.size() << "): (elided)" << endl;
235
    }
236
}    
237

    
238
void
239
Test::dump(const Plugin::FeatureSet &fs, bool showValues)
240
{
241
    for (Plugin::FeatureSet::const_iterator fsi = fs.begin();
242
         fsi != fs.end(); ++fsi) {
243
        int output = fsi->first;
244
        cout << "Output " << output << ":" << endl;
245
        const Plugin::FeatureList &fl = fsi->second;
246
        for (int i = 0; i < (int)fl.size(); ++i) {
247
            cout << "  Feature " << i << ":" << endl;
248
            const Plugin::Feature &f = fl[i];
249
            dumpFeature(f, showValues);
250
        }
251
    }
252
}
253

    
254
void
255
Test::dumpTwo(const Result &r,
256
              const Plugin::FeatureSet &a,
257
              const Plugin::FeatureSet &b)
258
{
259
    std::cout << r.message() << std::endl;
260
    std::cout << "\nFirst result set:" << std::endl;
261
    dump(a, false);
262
    std::cout << "\nSecond result set:" << std::endl;
263
    dump(b, false);
264
    std::cout << std::endl;
265
}
266

    
267
void
268
Test::dumpDiff(const Result &r,
269
               const Plugin::FeatureSet &a,
270
               const Plugin::FeatureSet &b)
271
{
272
    cout << r.message() << endl;
273
    cout << "\nDifferences follow:" << endl;
274
    if (a.size() != b.size()) {
275
        cout << "*** First result set has features on " << a.size() 
276
                  << " output(s), second has features on " << b.size()
277
                  << endl;
278
        return;
279
    }
280
    Plugin::FeatureSet::const_iterator ai = a.begin();
281
    Plugin::FeatureSet::const_iterator bi = b.begin();
282
    while (ai != a.end()) {
283
        if (ai->first != bi->first) {
284
            cout << "\n*** Output number mismatch: first result set says "
285
                      << ai->first << " where second says " << bi->first
286
                      << endl;
287
        } else {
288
            cout << "\nOutput " << ai->first << ":" << endl;
289
            if (ai->second.size() != bi->second.size()) {
290
                cout << "*** First result set has " << ai->second.size()
291
                          << " feature(s) on this output, second has "
292
                          << bi->second.size() << endl;
293
            } else {
294
                int fno = 0;
295
                int diffcount = 0;
296
                Plugin::FeatureList::const_iterator afi = ai->second.begin();
297
                Plugin::FeatureList::const_iterator bfi = bi->second.begin();
298
                while (afi != ai->second.end()) {
299
                    if (!(*afi == *bfi)) {
300
                        if (diffcount == 0) {
301
                            bool differInValues =
302
                                (afi->values.size() == bfi->values.size() &&
303
                                 afi->values != bfi->values);
304
                            if (afi->hasTimestamp != bfi->hasTimestamp) {
305
                                cout << "*** Feature " << fno << " differs in presence of timestamp (" << afi->hasTimestamp << " vs " << bfi->hasTimestamp << ")" << endl;
306
                            }
307
                            if (afi->hasTimestamp && (afi->timestamp != bfi->timestamp)) {
308
                                cout << "*** Feature " << fno << " differs in timestamp (" << afi->timestamp << " vs " << bfi->timestamp << " )" << endl;
309
                            }
310
                            if (afi->hasDuration != bfi->hasDuration) {
311
                                cout << "*** Feature " << fno << " differs in presence of duration (" << afi->hasDuration << " vs " << bfi->hasDuration << ")" << endl;
312
                            }
313
                            if (afi->hasDuration && (afi->duration != bfi->duration)) {
314
                                cout << "*** Feature " << fno << " differs in duration (" << afi->duration << " vs " << bfi->duration << " )" << endl;
315
                            }
316
                            if (afi->label != bfi->label) {
317
                                cout << "*** Feature " << fno << " differs in label" << endl;
318
                            }
319
                            if (afi->values.size() != bfi->values.size()) {
320
                                cout << "*** Feature " << fno << " differs in number of values (" << afi->values.size() << " vs " << bfi->values.size() << ")" << endl;
321
                            }
322
                            if (differInValues) {
323
                                cout << "*** Feature " << fno << " differs in values" << endl;
324
                            }
325
                            cout << "  First output:" << endl;
326
                            dumpFeature(*afi, differInValues);
327
                            cout << "  Second output:" << endl;
328
                            dumpFeature(*bfi, differInValues, &(*afi));
329
                        }
330
                        ++diffcount;
331
                    }
332
                    ++fno;
333
                    ++afi;
334
                    ++bfi;
335
                }
336
                if (diffcount > 1) {
337
                    cout << diffcount-1 << " subsequent differing feature(s) elided" << endl;
338
                }
339
            }
340
        }                
341
        ++ai;
342
        ++bi;
343
    }
344
    cout << endl;
345
}
346

    
347
bool
348
operator==(const Plugin::FeatureSet &a, const Plugin::FeatureSet &b)
349
{
350
    if (a.size() != b.size()) return false;
351
    for (Plugin::FeatureSet::const_iterator ai = a.begin();
352
         ai != a.end(); ++ai) {
353
        int output = ai->first;
354
        Plugin::FeatureSet::const_iterator bi = b.find(output);
355
        if (bi == b.end()) return false;
356
        if (!(ai->second == bi->second)) return false;
357
    }
358
    return true;
359
}
360

    
361
bool
362
operator==(const Plugin::FeatureList &a, const Plugin::FeatureList &b)
363
{
364
    if (a.size() != b.size()) return false;
365
    for (int i = 0; i < (int)a.size(); ++i) {
366
        if (!(a[i] == b[i])) return false;
367
    }
368
    return true;
369
}
370

    
371
bool
372
operator==(const Plugin::Feature &a, const Plugin::Feature &b)
373
{
374
    if (a.hasTimestamp != b.hasTimestamp) return false;
375
    if (a.hasTimestamp && (a.timestamp != b.timestamp)) return false;
376
    if (a.hasDuration != b.hasDuration) return false;
377
    if (a.hasDuration && (a.duration != b.duration)) return false;
378
    if (a.values != b.values) return false;
379
    if (a.label != b.label) return false;
380
    return true;
381
}
382