Revision 0:f89128a316e7

View differences:

.hgignore
1
syntax: glob
2
*.o
3
*~
4
*.so
5
*.dll
6
*.exe
7
vamp-plugin-tester
.hgsub
1
vamp-plugin-sdk = https://code.soundsoftware.ac.uk/hg/vamp-plugin-sdk
.hgsubstate
1
5d9af3140f050e99c9ac6c99290dcb55014baf37 vamp-plugin-sdk
.hgtags
1
b1bc4d045a4be1dc802043d90c54538454fcb2d9 vamp-plugin-tester-v1.0
2
eff1772ba3974c163681387c1455bcc9aa853e1f vamp-plugin-tester-v1.0-erroneous
3
d19bbfc055abb6c7733f9f808b2bd1cd6dfa80c9 vamp-plugin-tester-v1.1
CHANGELOG
1

  
2
Changes in Vamp Plugin Tester v1.1 since the previous release v1.0:
3

  
4
Features
5

  
6
 * Add mechanism for listing the available tests and running only a
7
   single test at a time
8
 
9
 * Add test for reset() changing effective parameter values
10

  
11
 * Add test for fixed-sample-rate output defined without sample rate
12
 
13
 * Add test for existence of .cat file
14

  
15
 * Add test for boilerplate description text still in place for VamPy
16
   plugins
17
 
18
 * Make output more informative for some tests, and make some tests faster
19

  
20
Bug fixes
21

  
22
 * Fix erroneous verbose timestamp output for some tests
23

  
24
 * Don't complain when two consecutive runs with different starting
25
   times produce the same results, if neither set of results has any
26
   timestamps anyway
27

  
28
 * Link against pthread library on Linux, to support plugins with
29
   threading
COPYING
1
  
2
    Permission is hereby granted, free of charge, to any person
3
    obtaining a copy of this software and associated documentation
4
    files (the "Software"), to deal in the Software without
5
    restriction, including without limitation the rights to use, copy,
6
    modify, merge, publish, distribute, sublicense, and/or sell copies
7
    of the Software, and to permit persons to whom the Software is
8
    furnished to do so, subject to the following conditions:
9

  
10
    The above copyright notice and this permission notice shall be
11
    included in all copies or substantial portions of the Software.
12

  
13
    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
14
    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
15
    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
16
    NONINFRINGEMENT. IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR
17
    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
18
    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
19
    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20

  
21
    Except as contained in this notice, the names of the Centre for
22
    Digital Music; Queen Mary, University of London; and Chris Cannam
23
    shall not be used in advertising or otherwise to promote the sale,
24
    use or other dealings in this Software without prior written
25
    authorization.
26

  
Makefile
1 1

  
2
ARCHFLAGS	?=
2
LDFLAGS 	+= -lvamp-hostsdk -ldl
3
CXXFLAGS	+= -Wall -Wextra
3 4

  
4
LDFLAGS 	+= $(ARCHFLAGS) -ldl -pthread
5
CXXFLAGS	+= $(ARCHFLAGS) -g -Wall -Wextra -Ivamp-plugin-sdk -pthread
5
OBJECTS		:= vamp-plugin-tester.o Tester.o Test.o TestStaticData.o
6 6

  
7
# We include the Vamp Host SDK sources in the build here, so that we
8
# can build the entire thing with debug symbols even though the SDK
9
# would not normally have them
10

  
11
VAMP_SRCDIR	:= vamp-plugin-sdk/src/vamp-hostsdk
12

  
13
VAMP_OBJECTS	:= \
14
	$(VAMP_SRCDIR)/PluginHostAdapter.o \
15
	$(VAMP_SRCDIR)/RealTime.o \
16
	$(VAMP_SRCDIR)/PluginBufferingAdapter.o \
17
	$(VAMP_SRCDIR)/PluginChannelAdapter.o \
18
	$(VAMP_SRCDIR)/PluginInputDomainAdapter.o \
19
	$(VAMP_SRCDIR)/PluginLoader.o \
20
	$(VAMP_SRCDIR)/PluginSummarisingAdapter.o \
21
	$(VAMP_SRCDIR)/PluginWrapper.o \
22
	$(VAMP_SRCDIR)/Files.o \
23
	$(VAMP_SRCDIR)/acsymbols.o
24

  
25
OBJECTS		:= \
26
	$(VAMP_OBJECTS) \
27
	vamp-plugin-tester.o \
28
	Tester.o \
29
	Test.o \
30
	TestStaticData.o \
31
	TestInputExtremes.o \
32
	TestMultipleRuns.o \
33
	TestOutputs.o \
34
	TestDefaults.o \
35
	TestInitialise.o
36

  
37
vamp-plugin-tester:	$(OBJECTS) $(VAMP_OBJECTS)
38
	$(CXX) $(OBJECTS) -o $@ $(LDFLAGS)
7
vamp-plugin-tester:	$(OBJECTS)
39 8

  
40 9
clean:
41
	rm -f $(OBJECTS) $(VAMP_OBJECTS)
10
	rm -f $(OBJECTS)
42 11

  
43 12
distclean:	clean
44 13
	rm -f *~ vamp-plugin-tester
45 14

  
46 15
depend:
47
	makedepend -Y *.cpp *.h $(VAMP_SRCDIR)/*.cpp
16
	makedepend -Y *.cpp *.h
48 17

  
49 18
# DO NOT DELETE
50 19

  
51 20
Test.o: Test.h
52
TestDefaults.o: TestDefaults.h Test.h Tester.h
21
TestStaticData.o: TestStaticData.h Test.h Tester.h
53 22
Tester.o: Tester.h Test.h
54
TestInitialise.o: TestInitialise.h Test.h Tester.h
55
TestInputExtremes.o: TestInputExtremes.h Test.h Tester.h
56
TestMultipleRuns.o: TestMultipleRuns.h Test.h Tester.h
57
TestOutputs.o: TestOutputs.h Test.h Tester.h
58
TestStaticData.o: TestStaticData.h Test.h Tester.h
59 23
vamp-plugin-tester.o: Tester.h Test.h
60
TestDefaults.o: Test.h Tester.h
24
TestStaticData.o: Test.h Tester.h
61 25
Tester.o: Test.h
62
TestInitialise.o: Test.h Tester.h
63
TestInputExtremes.o: Test.h Tester.h
64
TestMultipleRuns.o: Test.h Tester.h
65
TestOutputs.o: Test.h Tester.h
66
TestStaticData.o: Test.h Tester.h
67
vamp-plugin-sdk/src/vamp-hostsdk/PluginInputDomainAdapter.o: vamp-plugin-sdk/src/vamp-hostsdk/Window.h
68
vamp-plugin-sdk/src/vamp-hostsdk/PluginInputDomainAdapter.o: vamp-plugin-sdk/src/vamp-sdk/FFTimpl.cpp
69
vamp-plugin-sdk/src/vamp-hostsdk/RealTime.o: vamp-plugin-sdk/src/vamp-sdk/RealTime.cpp
README
1

  
2
Vamp Plugin Tester
3
==================
4

  
5
This program tests Vamp audio feature extraction plugins
6
(http://vamp-plugins.org/) for certain common failure cases.
7

  
8
To test a single plugin, run vamp-plugin-tester with the name of your
9
plugin library and plugin identifier, separated by a colon.  For example,
10

  
11
  $ vamp-plugin-tester vamp-example-plugins:amplitudefollower
12

  
13
The plugin library must be installed in the Vamp plugin path (you
14
cannot give the path to the library file).
15

  
16

  
17
Options
18
=======
19

  
20
Supply the -a or --all option to tell vamp-plugin-tester to test all
21
plugins found in your Vamp path.
22

  
23
Supply the -v or --verbose option to tell vamp-plugin-tester to print
24
out the whole content of its returned feature log for diagnostic
25
purposes each time it prints an error or warning that arises from the
26
contents of a returned feature.
27

  
28
Supply the -n or --nondeterministic option to tell vamp-plugin-tester
29
that your plugins are expected to return different results each time
30
they are run.  The default behaviour is to treat different results on
31
separate runs with the same input data as an error.
32

  
33
Supply the -t or --test option with a test ID argument to tell
34
vamp-plugin-tester to run only a single test, rather than the complete
35
test suite. To find out what test ID to use for a given test, run
36
vamp-plugin-tester with the --list-tests or -l option.
37

  
38

  
39
Errors and Warnings
40
===================
41

  
42
Each test may cause one or several notes, warnings, or errors to be
43
printed.  A note is printed when behaviour is observed that may be
44
correct behaviour but that is not always anticipated by the plugin
45
developer.  A warning is printed when behaviour is observed that is
46
technically legal but that in practice most often happens by mistake.
47
An error is printed when behaviour is observed that cannot be correct.
48

  
49
vamp-plugin-tester prints all of its commentary to the standard
50
output.  Standard error is usually used for diagnostic output printed
51
by the plugins themselves.
52

  
53
In addition to reports, vamp-plugin-tester runs some tests that are
54
intended to provoke the plugin into unexpected behaviour such as
55
memory errors.  If vamp-plugin-tester crashes during a test, this may
56
be why.  If you have access to a memory checker utility such as
57
valgrind, you are advised to run vamp-plugin-tester under it so as to
58
be informed of any memory errors that do not happen to cause crashes
59
(as well as memory leaks).  The vamp-plugin-tester binaries
60
distributed by QMUL have been compiled with debug information
61
included, in order to facilitate this type of use.
62

  
63

  
64
Error and Warning Reference
65
===========================
66

  
67
 ** ERROR: Failed to load plugin
68

  
69
 The plugin could not be loaded.  Remember that the plugin must be
70
 installed in the Vamp plugin path.
71

  
72
 Normally this message will be preceded by one of the following
73
 errors:
74

  
75
   Invalid plugin key <key> in loadPlugin
76

  
77
    - The argument given to vamp-plugin-tester could not be split
78
      into library name and plugin identifier.  Check the usage
79
      description above.
80

  
81
   No library found in Vamp path for plugin <key>
82

  
83
    - No Vamp plugin library of that name was found in the Vamp path.
84
      This message will often be accompanied by one of the following
85
      errors; if it isn't, then that probably means the file did not
86
      exist at all.
87

  
88
   Plugin <id> not found in library <name>
89

  
90
    - The library was found and loaded and was apparently a valid
91
      Vamp plugin library, but it didn't contain a plugin of that id.
92
      Check you typed the id correctly, and if this is your library,
93
      check that the vampGetPluginDescriptor function returns the
94
      plugin descriptor properly.
95

  
96
   Unable to load library <name>
97

  
98
    - A dynamic library of that name was found, but the system library
99
      loader could not load it.  Perhaps it depends on another library
100
      that is not available, or it was built for the wrong architecture.
101
      There may be more information in the error message.
102

  
103
   No vampGetPluginDescriptor function found in library <name>
104

  
105
    - A dynamic library of that name was found and loaded, but it
106
      lacked the necessary public vampGetPluginDescriptor function.
107

  
108
      * Are you sure this is a Vamp plugin library?
109
      * If you made it, did you remember to include the global
110
        vampGetPluginDescriptor function in your library along with
111
	your plugin classes?
112
      * If you are using Visual C++, did you remember to mark the
113
        vampGetPluginDescriptor symbol exported, as described in
114
        the README.msvc file in the SDK?
115

  
116
 ** ERROR: (plugin|parameter|output) identifier <x> contains invalid characters
117

  
118
 An identifier contains characters other than the permitted set (ASCII
119
 lower and upper case letters, digits, "-" and "_" only).
120

  
121
 ** ERROR: <field> is empty
122

  
123
 A mandatory field, such as the name of a parameter or output,
124
 contains no text.
125

  
126
 ** WARNING: <field> is empty
127

  
128
 An optional field, such as the description of a parameter or output,
129
 contains no text.
130

  
131
 ** ERROR: Plugin parameter <x> maxValue <= minValue
132

  
133
 The minimum and maximum values given for a parameter are equal or in
134
 the wrong order.
135

  
136
 ** ERROR: Plugin parameter <x> defaultValue out of range
137

  
138
 The default value for a parameter is not within the range defined by
139
 the minimum and maximum values for the parameter.
140

  
141
 ** ERROR: Plugin parameter <x> is quantized, but quantize step is zero
142

  
143
 The quantizeStep value in a parameter with isQuantized true is set to
144
 zero.
145

  
146
 ** WARNING: Plugin parameter <x> value range is not a multiple of quantize step
147

  
148
 A parameter's stated maximum value is not one of the possible values
149
 obtained by adding multiples of the quantize step on to the minimum
150
 value.
151

  
152
 ** WARNING: Plugin parameter <x> has (more|fewer) value names than quantize steps
153

  
154
 A quantized parameter lists some value names for its quantize steps,
155
 but not the right number.
156
 
157
 ** WARNING: Plugin parameter <x> default value is not a multiple of quantize
158
 step beyond minimum
159

  
160
 The default value for a parameter is not a value that the user could
161
 actually obtain, if only offered the quantized values to choose from.
162

  
163
 ** ERROR: Data returned on nonexistent output
164

  
165
 The output number key for a returned feature is outside the range of
166
 outputs listed in the plugin's output descriptor list.
167

  
168
 ** NOTE: No results returned for output <x>
169

  
170
 The plugin returned no features on one of its outputs, when given a
171
 simple test file.  This may be perfectly reasonable behaviour, but
172
 you might like to know about it.
173

  
174
 ** ERROR: Plugin output <x> has FixedSampleRate but gives sample rate as 0
175

  
176
 A plugin output that has a sample type of FixedSampleRate must have a
177
 non-zero sample rate. See
178
 https://code.soundsoftware.ac.uk/projects/vamp-plugin-sdk/wiki/SampleType
179

  
180
 ** NOTE: Plugin returns features with timestamps on OneSamplePerStep output
181
 ** NOTE: Plugin returns features with durations on OneSamplePerStep output
182

  
183
 Hosts will usually ignore timestamps and durations attached to any
184
 feature returned on a OneSamplePerStep output. See
185
 https://code.soundsoftware.ac.uk/projects/vamp-plugin-sdk/wiki/SampleType
186

  
187
 ** ERROR: Plugin returns features with no timestamps on VariableSampleRate output
188

  
189
 Timestamps are mandatory on all features associated with a
190
 VariableSampleRate output. See
191
 https://code.soundsoftware.ac.uk/projects/vamp-plugin-sdk/wiki/SampleType
192

  
193
 ** WARNING: Plugin returned one or more NaN/inf values
194

  
195
 The plugin returned features containing floating-point not-a-number
196
 or infinity values.  This warning may be associated with a test
197
 involving feeding some unexpected type of data to the plugin.
198
 
199
 ** ERROR: Consecutive runs with separate instances produce different results
200

  
201
 The plugin was constructed and run twice against the same input data,
202
 and returned different features each time.
203

  
204
 If you give the -n or --nondeterministic option, vamp-plugin-tester
205
 will downgrade this error to a note.
206

  
207
 ** ERROR: Consecutive runs with the same instance (using reset) produce different results
208

  
209
 The plugin was constructed, initialised, run against some input data,
210
 reset with a call to its reset() function, and run again against the
211
 same data; and it returned different features on each run.  This is
212
 often a sign of some simple error such as forgetting to implement
213
 reset().
214

  
215
 If you give the -n or --nondeterministic option, vamp-plugin-tester
216
 will downgrade this error to a note.
217

  
218
 ** ERROR: Simultaneous runs with separate instances produce different results
219

  
220
 Two instances of the plugin were constructed and run against the same
221
 input data, giving each block of data to one plugin's process call
222
 and then to the other's, "interleaving" the processing between the
223
 two instances (but within a single application thread); and the two
224
 instances returned different features.  This may indicate ill-advised
225
 use of static data shared between plugin instances.
226

  
227
 If you give the -n or --nondeterministic option, vamp-plugin-tester
228
 will downgrade this error to a note.
229

  
230
 ** WARNING: Consecutive runs with different starting timestamps produce the same result
231

  
232
 The plugin was run twice on the same audio data, but with different
233
 input timestamps, and it returned the same results each time.  While
234
 this is often unproblematic, it can indicate that a plugin failed to
235
 take the input timestamp into account when calculating its output
236
 timestamps (if any).
237

  
238
 If you give the -n or --nondeterministic option, vamp-plugin-tester
239
 will downgrade this warning to a note.
240

  
241
 ** ERROR: Explicitly setting current program to its supposed current value changes the results
242

  
243
 The plugin was constructed and run twice on the same data, once
244
 without changing its "program" setting, and again having set the
245
 program to the vaule returned by getCurrentProgram() (i.e. the same
246
 program that was supposed to be in effect already).  It returned
247
 different results for the two runs, suggesting that some internal
248
 data was changed in selectProgram in a way that differed from its
249
 default.
250

  
251
 If you give the -n or --nondeterministic option, vamp-plugin-tester
252
 will downgrade this error to a note.
253

  
254
 ** ERROR: Explicitly setting parameters to their supposed default values changes the results
255

  
256
 The plugin was constructed and run twice on the same data, once
257
 without changing any of its parameters, and again having set the
258
 parameters to their specified default values.  It returned different
259
 results for the two runs, suggesting that some internal data was
260
 changed when a parameter was set to its default, in a way that
261
 differed from the plugin's initially constructed state.
262

  
263
 If you give the -n or --nondeterministic option, vamp-plugin-tester
264
 will downgrade this error to a note.
265

  
266
 ** ERROR: Call to reset after setting parameters, but before processing, changes the results (parameter values not retained through reset?)
267

  
268
 The plugin was constructed and run twice on the same data. The first
269
 time, its parameters were set to some arbitrary values and it was
270
 initialised and run. The second time, its parameters were set to the
271
 same values and it was initialised, then reset(), then run. The two
272
 runs returned different results, suggesting that perhaps some
273
 parameter value was being modified within the reset() function. (This
274
 function should reset internal state within the plugin, but not
275
 parameter configuration.)
276

  
277
 If you give the -n or --nondeterministic option, vamp-plugin-tester
278
 will downgrade this error to a note.
279

  
280
 ** WARNING: Constructor takes some time to run: work should be deferred to initialise?
281

  
282
 The plugin took a long time to construct.  You should ensure that the
283
 constructor for the plugin runs as quickly as possible, because it
284
 may be called by a host that is only scanning the properties of all
285
 available plugins on startup.  Any serious initialisation work should
286
 be done in the initialise() function rather than the constructor.
287

  
288

  
289
Authors
290
=======
291

  
292
This program was written at the Centre for Digital Music at Queen
293
Mary, University of London, by Chris Cannam.  Copyright (c) 2009-2015 QMUL.
294

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

  
9 9
    This program loads a Vamp plugin and tests its susceptibility to a
10 10
    number of common pitfalls, including handling of extremes of input
......
44 44
using namespace Vamp;
45 45
using namespace Vamp::HostExt;
46 46

  
47
#include <math.h>
48

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

  
54 47
Test::Test() { }
55 48
Test::~Test() { }
56 49

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

  
62 50
Plugin *
63
Test::load(string key, float rate)
51
Test::load(std::string key, float rate)
64 52
{
65
    Plugin *p = PluginLoader::getInstance()->loadPlugin
53
    return PluginLoader::getInstance()->loadPlugin
66 54
        (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 55
}
147 56

  
148 57
void
......
159 68
}
160 69

  
161 70
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 71
operator==(const Plugin::FeatureSet &a, const Plugin::FeatureSet &b)
349 72
{
350 73
    if (a.size() != b.size()) return false;
Test.h
4 4
    Vamp Plugin Tester
5 5
    Chris Cannam, cannam@all-day-breakfast.com
6 6
    Centre for Digital Music, Queen Mary, University of London.
7
    Copyright 2009-2014 QMUL.
7
    Copyright 2009 QMUL.
8 8

  
9 9
    This program loads a Vamp plugin and tests its susceptibility to a
10 10
    number of common pitfalls, including handling of extremes of input
......
48 48
{
49 49
public:
50 50
    virtual ~Test();
51

  
52
    enum Option {
53
        NoOption           = 0x0,
54
        NonDeterministic   = 0x1,
55
        Verbose            = 0x2,
56
        SingleTest         = 0x4
57
    };
58
    typedef int Options;
59 51
    
60 52
    class Result {
61 53

  
62 54
    public:
63
        enum Code { Success, Note, Warning, Error };
55
        enum Code { Success, Warning, Error };
64 56

  
65
        Result() : m_code(Success) { }
66 57
        Result(Code c, std::string m) : m_code(c), m_message(m) { }
67 58

  
68
        Code code() const { return m_code; }
69
        std::string message() const { return m_message; }
70
        
59
        Code code() { return m_code; }
60
        std::string message() { return m_message; }
61

  
71 62
    protected:
72 63
        Code m_code;
73 64
        std::string m_message;
74 65
    };
75 66

  
76 67
    static Result success() { return Result(Result::Success, ""); }
77
    static Result note(std::string m) { return Result(Result::Note, m); }
78 68
    static Result warning(std::string m) { return Result(Result::Warning, m); }
79 69
    static Result error(std::string m) { return Result(Result::Error, m); }
80 70

  
......
83 73
    class FailedToLoadPlugin { };
84 74

  
85 75
    // may throw FailedToLoadPlugin
86
    virtual Results test(std::string key, Options) = 0;
76
    virtual Results test(std::string key) = 0;
87 77

  
88 78
protected:
89 79
    Test();
......
91 81
    // may throw FailedToLoadPlugin
92 82
    Vamp::Plugin *load(std::string key, float rate = 44100);
93 83

  
94
    float **createBlock(size_t channels, size_t blocksize);
95
    void destroyBlock(float **blocks, size_t channels);
96

  
97
    float **createTestAudio(size_t channels, size_t blocksize, size_t blocks);
98
    void destroyTestAudio(float **audio, size_t channels);
99

  
100
    // use plugin's preferred step/block size, return them:
101
    bool initDefaults(Vamp::Plugin *, size_t &channels,
102
                      size_t &step, size_t &block, Results &r);
103

  
104
    // use the given step/block size and an adapter:
105
    bool initAdapted(Vamp::Plugin *, size_t &channels,
106
                     size_t step, size_t block, Results &r);
107

  
108 84
    void appendFeatures(Vamp::Plugin::FeatureSet &a,
109 85
                        const Vamp::Plugin::FeatureSet &b);
110

  
111
    bool allFeaturesValid(const Vamp::Plugin::FeatureSet &); // i.e. no NaN/inf
112

  
113
    bool containsTimestamps(const Vamp::Plugin::FeatureSet &);
114

  
115
    void dumpFeature(const Vamp::Plugin::Feature &, bool showValues,
116
                     const Vamp::Plugin::Feature *other = 0);
117
    void dump(const Vamp::Plugin::FeatureSet &, bool showValues = true);
118
    void dumpTwo(const Result &r,
119
                 const Vamp::Plugin::FeatureSet &,
120
                 const Vamp::Plugin::FeatureSet &);
121
    void dumpDiff(const Result &r,
122
                  const Vamp::Plugin::FeatureSet &,
123
                  const Vamp::Plugin::FeatureSet &);
124 86
};
125 87

  
126 88
extern bool operator==(const Vamp::Plugin::FeatureSet &a,
TestDefaults.cpp
1
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
2

  
3
/*
4
    Vamp Plugin 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 "TestDefaults.h"
41

  
42
#include <vamp-hostsdk/Plugin.h>
43
using namespace Vamp;
44

  
45
#include <memory>
46
using namespace std;
47

  
48
#include <cmath>
49
#include <time.h>
50

  
51
#ifndef __GNUC__
52
#include <alloca.h>
53
#endif
54

  
55
Tester::TestRegistrar<TestDefaultProgram>
56
TestDefaultProgram::m_registrar("E1", "Inconsistent default program");
57

  
58
Tester::TestRegistrar<TestDefaultParameters>
59
TestDefaultParameters::m_registrar("E2", "Inconsistent default parameters");
60

  
61
Tester::TestRegistrar<TestParametersOnReset>
62
TestParametersOnReset::m_registrar("E3", "Parameter retention through reset");
63

  
64
static const size_t _step = 1000;
65

  
66
Test::Results
67
TestDefaultProgram::test(string key, Options options)
68
{
69
    Plugin::FeatureSet f[2];
70
    int rate = 44100;
71
    Results r;
72
    float **data = 0;
73
    size_t channels = 0;
74
    size_t count = 100;
75

  
76
    for (int run = 0; run < 2; ++run) {
77
        auto_ptr<Plugin> p(load(key, rate));
78
	if (p->getPrograms().empty()) return r;
79
	if (run == 1) {
80
            p->selectProgram(p->getCurrentProgram());
81
        }
82
        if (!initAdapted(p.get(), channels, _step, _step, r)) return r;
83
        if (!data) data = createTestAudio(channels, _step, count);
84
        for (size_t i = 0; i < count; ++i) {
85
#ifdef __GNUC__
86
            float *ptr[channels];
87
#else
88
            float **ptr = (float **)alloca(channels * sizeof(float));
89
#endif
90
            size_t idx = i * _step;
91
            for (size_t c = 0; c < channels; ++c) ptr[c] = data[c] + idx;
92
            RealTime timestamp = RealTime::frame2RealTime(idx, rate);
93
            Plugin::FeatureSet fs = p->process(ptr, timestamp);
94
            appendFeatures(f[run], fs);
95
        }
96
        Plugin::FeatureSet fs = p->getRemainingFeatures();
97
        appendFeatures(f[run], fs);
98
    }
99
    if (data) destroyTestAudio(data, channels);
100

  
101
    if (!(f[0] == f[1])) {
102
        string message = "Explicitly setting current program to its supposed current value changes the results";
103
        Result res;
104
        if (options & NonDeterministic) res = note(message);
105
        else res = error(message);
106
        if (options & Verbose) dumpDiff(res, f[0], f[1]);
107
        r.push_back(res);
108
    } else {
109
        r.push_back(success());
110
    }
111

  
112
    return r;
113
}
114

  
115
Test::Results
116
TestDefaultParameters::test(string key, Options options)
117
{
118
    Plugin::FeatureSet f[2];
119
    int rate = 44100;
120
    Results r;
121
    float **data = 0;
122
    size_t channels = 0;
123
    size_t count = 100;
124

  
125
    for (int run = 0; run < 2; ++run) {
126
        auto_ptr<Plugin> p(load(key, rate));
127
	if (p->getParameterDescriptors().empty()) return r;
128
	if (run == 1) {
129
            Plugin::ParameterList pl = p->getParameterDescriptors();
130
            for (int i = 0; i < (int)pl.size(); ++i) {
131
                if (p->getParameter(pl[i].identifier) != pl[i].defaultValue) {
132
                    if (options & Verbose) {
133
                        cout << "Parameter: " << pl[i].identifier << endl;
134
                        cout << "Expected: " << pl[i].defaultValue << endl;
135
                        cout << "Actual: " << p->getParameter(pl[i].identifier) << endl;
136
                    }
137
                    r.push_back(error("Not all parameters have their default values when queried directly after construction"));
138
                }
139
                p->setParameter(pl[i].identifier, pl[i].defaultValue);
140
            }
141
        }
142
        if (!initAdapted(p.get(), channels, _step, _step, r)) return r;
143
        if (!data) data = createTestAudio(channels, _step, count);
144
        for (size_t i = 0; i < count; ++i) {
145
#ifdef __GNUC__
146
            float *ptr[channels];
147
#else
148
            float **ptr = (float **)alloca(channels * sizeof(float));
149
#endif
150
            size_t idx = i * _step;
151
            for (size_t c = 0; c < channels; ++c) ptr[c] = data[c] + idx;
152
            RealTime timestamp = RealTime::frame2RealTime(idx, rate);
153
            Plugin::FeatureSet fs = p->process(ptr, timestamp);
154
            appendFeatures(f[run], fs);
155
        }
156
        Plugin::FeatureSet fs = p->getRemainingFeatures();
157
        appendFeatures(f[run], fs);
158
    }
159
    if (data) destroyTestAudio(data, channels);
160

  
161
    if (!(f[0] == f[1])) {
162
        string message = "Explicitly setting parameters to their supposed default values changes the results";
163
        Result res;
164
        if (options & NonDeterministic) res = note(message);
165
        else res = error(message);
166
        if (options & Verbose) dumpDiff(res, f[0], f[1]);
167
        r.push_back(res);
168
    } else {
169
        r.push_back(success());
170
    }
171

  
172
    return r;
173
}
174

  
175
Test::Results
176
TestParametersOnReset::test(string key, Options options)
177
{
178
    Plugin::FeatureSet f[2];
179
    int rate = 44100;
180
    Results r;
181
    float **data = 0;
182
    size_t channels = 0;
183
    size_t count = 100;
184

  
185
    for (int run = 0; run < 2; ++run) {
186
        auto_ptr<Plugin> p(load(key, rate));
187
	if (p->getParameterDescriptors().empty()) return r;
188

  
189
        // Set all parameters to non-default values
190

  
191
        Plugin::ParameterList pl = p->getParameterDescriptors();
192

  
193
        for (int i = 0; i < (int)pl.size(); ++i) {
194

  
195
            // Half-way between default and max value, seems a
196
            // reasonable guess for something to set it to. We want to
197
            // avoid the real extremes because they can sometimes be
198
            // very slow, and we want to avoid setting everything to
199
            // the same values (e.g. min) because plugins will
200
            // sometimes legitimately reject that.
201

  
202
            // Remember to take into account quantization
203

  
204
            float value = (pl[i].defaultValue + pl[i].maxValue) / 2;
205

  
206
            if (pl[i].isQuantized) {
207
                value = round(value / pl[i].quantizeStep) * pl[i].quantizeStep;
208
            }
209

  
210
            if (value > pl[i].maxValue) {
211
                value = pl[i].maxValue;
212
            }
213
            if (value < pl[i].minValue) {
214
                value = pl[i].minValue;
215
            }
216
            if (value == pl[i].defaultValue) {
217
                if (pl[i].defaultValue == pl[i].minValue) {
218
                    value = pl[i].maxValue;
219
                } else {
220
                    value = pl[i].minValue;
221
                }
222
            }
223

  
224
            p->setParameter(pl[i].identifier, value);
225
        }
226

  
227
        if (!initAdapted(p.get(), channels, _step, _step, r)) {
228

  
229
            // OK, plugin didn't like that. Let's try a different tack
230
            // -- set everything to min except those parameters whose
231
            // default is min, and set those to half way instead
232
            
233
            for (int i = 0; i < (int)pl.size(); ++i) {
234
                float value = pl[i].minValue;
235
                if (value == pl[i].defaultValue) {
236
                    value = (pl[i].maxValue + pl[i].minValue) / 2;
237
                    value = ceil(value / pl[i].quantizeStep) * pl[i].quantizeStep;
238
                    if (value > pl[i].maxValue) {
239
                        value = pl[i].maxValue;
240
                    }
241
                }
242
                p->setParameter(pl[i].identifier, value);
243
            }
244

  
245
            r = Results();
246
            if (!initAdapted(p.get(), channels, _step, _step, r)) {
247
                // Still didn't work, give up
248
                return r;
249
            }
250
        }
251

  
252
        //  First run: construct, set params, init, process
253
        // Second run: construct, set params, init, reset, process
254
        // We expect these to produce the same results
255
        if (run == 1) p->reset();
256

  
257
        if (!data) data = createTestAudio(channels, _step, count);
258
        for (size_t i = 0; i < count; ++i) {
259
#ifdef __GNUC__
260
            float *ptr[channels];
261
#else
262
            float **ptr = (float **)alloca(channels * sizeof(float));
263
#endif
264
            size_t idx = i * _step;
265
            for (size_t c = 0; c < channels; ++c) ptr[c] = data[c] + idx;
266
            RealTime timestamp = RealTime::frame2RealTime(idx, rate);
267
            Plugin::FeatureSet fs = p->process(ptr, timestamp);
268
            appendFeatures(f[run], fs);
269
        }
270
        Plugin::FeatureSet fs = p->getRemainingFeatures();
271
        appendFeatures(f[run], fs);
272
    }
273
    if (data) destroyTestAudio(data, channels);
274

  
275
    if (!(f[0] == f[1])) {
276
        string message = "Call to reset after setting parameters, but before processing, changes the results (parameter values not retained through reset?)";
277
        Result res;
278
        if (options & NonDeterministic) res = note(message);
279
        else res = error(message);
280
        if (options & Verbose) dumpDiff(res, f[0], f[1]);
281
        r.push_back(res);
282
    } else {
283
        r.push_back(success());
284
    }
285

  
286
    return r;
287
}
TestDefaults.h
1
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
2

  
3
/*
4
    Vamp Plugin 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
#ifndef _TEST_DEFAULTS_H_
41
#define _TEST_DEFAULTS_H_
42

  
43
#include "Test.h"
44
#include "Tester.h"
45

  
46
class TestDefaultProgram : public Test
47
{
48
public:
49
    TestDefaultProgram() : Test() { }
50
    Results test(std::string key, Options options);
51
    
52
protected:
53
    static Tester::TestRegistrar<TestDefaultProgram> m_registrar;
54
};
55

  
56
class TestDefaultParameters : public Test
57
{
58
public:
59
    TestDefaultParameters() : Test() { }
60
    Results test(std::string key, Options options);
61
    
62
protected:
63
    static Tester::TestRegistrar<TestDefaultParameters> m_registrar;
64
};
65

  
66
class TestParametersOnReset : public Test
67
{
68
public:
69
    TestParametersOnReset() : Test() { }
70
    Results test(std::string key, Options options);
71
    
72
protected:
73
    static Tester::TestRegistrar<TestParametersOnReset> m_registrar;
74
};
75

  
76
#endif
TestInitialise.cpp
1
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
2

  
3
/*
4
    Vamp Plugin 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 "TestInitialise.h"
41

  
42
#include <vamp-hostsdk/Plugin.h>
43
#include <vamp-hostsdk/PluginLoader.h>
44
using namespace Vamp;
45
using namespace Vamp::HostExt;
46

  
47
#include <set>
48
#include <memory>
49
using namespace std;
50

  
51
#include <cmath>
52
#include <ctime>
53

  
54
#ifndef __GNUC__
55
#include <alloca.h>
56
#endif
57

  
58
Tester::TestRegistrar<TestSampleRates>
59
TestSampleRates::m_registrar("F1", "Different sample rates");
60

  
61
Tester::TestRegistrar<TestLengthyConstructor>
62
TestLengthyConstructor::m_registrar("F2", "Lengthy constructor");
63

  
64
Test::Results
65
TestSampleRates::test(string key, Options options)
66
{
67
    int rates[] =
68
        { 111, 800, 10099, 11024, 44100, 48000, 96000, 192000, 201011, 1094091 };
69

  
70
    Results r;
71

  
72
    if (options & Verbose) {
73
        cout << "    ";
74
    }
75

  
76
    for (int i = 0; i < int(sizeof(rates)/sizeof(rates[0])); ++i) {
77
    
78
        int rate = rates[i];
79

  
80
        if (options & Verbose) {
81
            cout << "[" << rate << "Hz] " << flush;
82
        }
83

  
84
        auto_ptr<Plugin> p(load(key, rate));
85
        Plugin::FeatureSet f;
86
        float **data = 0;
87
        size_t channels = 0;
88

  
89
        // Aim to feed the plugin a roughly fixed input duration in secs
90
        const float seconds = 10.f;
91
        size_t step = 1000;
92
        size_t count = (seconds * rate) / step;
93
        if (count < 1) count = 1;
94

  
95
        Results subr;
96
        if (!initAdapted(p.get(), channels, step, step, subr)) {
97
            // This is not an error; the plugin can legitimately
98
            // refuse to initialise at weird settings and that's often
99
            // the most acceptable result
100
            if (!subr.empty()) {
101
                r.push_back(note(subr.begin()->message()));
102
            }
103
            continue;
104
        }
105

  
106
        data = createTestAudio(channels, step, count);
107
        for (size_t j = 0; j < count; ++j) {
108
#ifdef __GNUC__
109
            float *ptr[channels];
110
#else
111
            float **ptr = (float **)alloca(channels * sizeof(float));
112
#endif
113
            size_t idx = j * step;
114
            for (size_t c = 0; c < channels; ++c) ptr[c] = data[c] + idx;
115
            RealTime timestamp = RealTime::frame2RealTime(idx, rate);
116
            Plugin::FeatureSet fs = p->process(ptr, timestamp);
117
            appendFeatures(f, fs);
118
        }
119
        Plugin::FeatureSet fs = p->getRemainingFeatures();
120
        appendFeatures(f, fs);
121
        destroyTestAudio(data, channels);
122
    }
123

  
124
    if (options & Verbose) cout << endl;
125

  
126
    // We can't actually do anything meaningful with our results.
127
    // We're really just testing to see whether the plugin crashes.  I
128
    // wonder whether it's possible to do any better?  If not, we
129
    // should probably report our limitations
130

  
131
    return r;
132
}
133

  
134
Test::Results
135
TestLengthyConstructor::test(string key, Options)
136
{
137
    time_t t0 = time(0);
138
    auto_ptr<Plugin> p(load(key));
139
    time_t t1 = time(0);
140
    Results r;
141
    if (t1 - t0 > 1) r.push_back(warning("Constructor takes some time to run: work should be deferred to initialise?"));
142
    return r;
143
}
144

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

  
3
/*
4
    Vamp Plugin 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
#ifndef _TEST_INITIALISE_H_
41
#define _TEST_INITIALISE_H_
42

  
43
#include "Test.h"
44
#include "Tester.h"
45

  
46
class TestSampleRates : public Test
47
{
48
public:
49
    TestSampleRates() : Test() { }
50
    Results test(std::string key, Options options);
51
    
52
protected:
53
    static Tester::TestRegistrar<TestSampleRates> m_registrar;
54
};
55

  
56
class TestLengthyConstructor : public Test
57
{
58
public:
59
    TestLengthyConstructor() : Test() { }
60
    Results test(std::string key, Options options);
61
    
62
protected:
63
    static Tester::TestRegistrar<TestLengthyConstructor> m_registrar;
64
};
65

  
66
#endif
TestInputExtremes.cpp
1
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
2

  
3
/*
4
    Vamp Plugin 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
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff