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 @ 53:86d8a699dfbe

History | View | Annotate | Download (11.8 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
{
197
    cout << "    Timestamp: " << (!f.hasTimestamp ? "(none)" : f.timestamp.toText()) << endl;
198
    cout << "    Duration: " << (!f.hasDuration ? "(none)" : f.duration.toText()) << endl;
199
    cout << "    Label: " << (f.label == "" ? "(none)" : f.label) << endl;
200
    if (showValues) {
201
        cout << "    Values (" << f.values.size() << "): " << (f.values.empty() ? "(none)" : "");
202
        for (int j = 0; j < (int)f.values.size(); ++j) {
203
            cout << f.values[j] << " ";
204
        }
205
        cout << endl;
206
    } else {
207
        cout << "    Values (" << f.values.size() << "): (elided)" << endl;
208
    }
209
}    
210

    
211
void
212
Test::dump(const Plugin::FeatureSet &fs, bool showValues)
213
{
214
    for (Plugin::FeatureSet::const_iterator fsi = fs.begin();
215
         fsi != fs.end(); ++fsi) {
216
        int output = fsi->first;
217
        cout << "Output " << output << ":" << endl;
218
        const Plugin::FeatureList &fl = fsi->second;
219
        for (int i = 0; i < (int)fl.size(); ++i) {
220
            cout << "  Feature " << i << ":" << endl;
221
            const Plugin::Feature &f = fl[i];
222
            dumpFeature(f, showValues);
223
        }
224
    }
225
}
226

    
227
void
228
Test::dumpTwo(const Result &r,
229
              const Plugin::FeatureSet &a,
230
              const Plugin::FeatureSet &b)
231
{
232
    std::cout << r.message() << std::endl;
233
    std::cout << "\nFirst result set:" << std::endl;
234
    dump(a, false);
235
    std::cout << "\nSecond result set:" << std::endl;
236
    dump(b, false);
237
    std::cout << std::endl;
238
}
239

    
240
void
241
Test::dumpDiff(const Result &r,
242
               const Plugin::FeatureSet &a,
243
               const Plugin::FeatureSet &b)
244
{
245
    cout << r.message() << endl;
246
    cout << "\nDifferences follow:" << endl;
247
    if (a.size() != b.size()) {
248
        cout << "*** First result set has features on " << a.size() 
249
                  << " output(s), second has features on " << b.size()
250
                  << endl;
251
        return;
252
    }
253
    Plugin::FeatureSet::const_iterator ai = a.begin();
254
    Plugin::FeatureSet::const_iterator bi = b.begin();
255
    while (ai != a.end()) {
256
        if (ai->first != bi->first) {
257
            cout << "\n*** Output number mismatch: first result set says "
258
                      << ai->first << " where second says " << bi->first
259
                      << endl;
260
        } else {
261
            cout << "\nOutput " << ai->first << ":" << endl;
262
            if (ai->second.size() != bi->second.size()) {
263
                cout << "*** First result set has " << ai->second.size()
264
                          << " feature(s) on this output, second has "
265
                          << bi->second.size() << endl;
266
            } else {
267
                int fno = 0;
268
                int diffcount = 0;
269
                Plugin::FeatureList::const_iterator afi = ai->second.begin();
270
                Plugin::FeatureList::const_iterator bfi = bi->second.begin();
271
                while (afi != ai->second.end()) {
272
                    if (!(*afi == *bfi)) {
273
                        if (diffcount == 0) {
274
                            bool differInValues = (afi->values != bfi->values);
275
                            if (afi->hasTimestamp != bfi->hasTimestamp) {
276
                                cout << "*** Feature " << fno << " differs in presence of timestamp (" << afi->hasTimestamp << " vs " << bfi->hasTimestamp << ")" << endl;
277
                            }
278
                            if (afi->hasTimestamp && (afi->timestamp != bfi->timestamp)) {
279
                                cout << "*** Feature " << fno << " differs in timestamp (" << afi->timestamp << " vs " << bfi->timestamp << " )" << endl;
280
                            }
281
                            if (afi->hasDuration != bfi->hasDuration) {
282
                                cout << "*** Feature " << fno << " differs in presence of duration (" << afi->hasDuration << " vs " << bfi->hasDuration << ")" << endl;
283
                            }
284
                            if (afi->hasDuration && (afi->duration != bfi->duration)) {
285
                                cout << "*** Feature " << fno << " differs in duration (" << afi->duration << " vs " << bfi->duration << " )" << endl;
286
                            }
287
                            if (afi->label != bfi->label) {
288
                                cout << "*** Feature " << fno << " differs in label" << endl;
289
                            }
290
                            if (differInValues) {
291
                                cout << "*** Feature " << fno << " differs in values" << endl;
292
                            }
293
                            cout << "  First output:" << endl;
294
                            dumpFeature(*afi, differInValues);
295
                            cout << "  Second output:" << endl;
296
                            dumpFeature(*bfi, differInValues);
297
                        }
298
                        ++diffcount;
299
                    }
300
                    ++fno;
301
                    ++afi;
302
                    ++bfi;
303
                }
304
                if (diffcount > 1) {
305
                    cout << diffcount-1 << " subsequent differing feature(s) elided" << endl;
306
                }
307
            }
308
        }                
309
        ++ai;
310
        ++bi;
311
    }
312
    cout << endl;
313
}
314

    
315
bool
316
operator==(const Plugin::FeatureSet &a, const Plugin::FeatureSet &b)
317
{
318
    if (a.size() != b.size()) return false;
319
    for (Plugin::FeatureSet::const_iterator ai = a.begin();
320
         ai != a.end(); ++ai) {
321
        int output = ai->first;
322
        Plugin::FeatureSet::const_iterator bi = b.find(output);
323
        if (bi == b.end()) return false;
324
        if (!(ai->second == bi->second)) return false;
325
    }
326
    return true;
327
}
328

    
329
bool
330
operator==(const Plugin::FeatureList &a, const Plugin::FeatureList &b)
331
{
332
    if (a.size() != b.size()) return false;
333
    for (int i = 0; i < (int)a.size(); ++i) {
334
        if (!(a[i] == b[i])) return false;
335
    }
336
    return true;
337
}
338

    
339
bool
340
operator==(const Plugin::Feature &a, const Plugin::Feature &b)
341
{
342
    if (a.hasTimestamp != b.hasTimestamp) return false;
343
    if (a.hasTimestamp && (a.timestamp != b.timestamp)) return false;
344
    if (a.hasDuration != b.hasDuration) return false;
345
    if (a.hasDuration && (a.duration != b.duration)) return false;
346
    if (a.values != b.values) return false;
347
    if (a.label != b.label) return false;
348
    return true;
349
}
350