cannam@10: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ cannam@10: cannam@10: /* cannam@10: Vamp Plugin Tester cannam@10: Chris Cannam, cannam@all-day-breakfast.com cannam@10: Centre for Digital Music, Queen Mary, University of London. Chris@42: Copyright 2009-2014 QMUL. cannam@10: cannam@10: This program loads a Vamp plugin and tests its susceptibility to a cannam@10: number of common pitfalls, including handling of extremes of input cannam@10: data. If you can think of any additional useful tests that are cannam@10: easily added, please send them to me. cannam@10: cannam@10: Permission is hereby granted, free of charge, to any person cannam@10: obtaining a copy of this software and associated documentation cannam@10: files (the "Software"), to deal in the Software without cannam@10: restriction, including without limitation the rights to use, copy, cannam@10: modify, merge, publish, distribute, sublicense, and/or sell copies cannam@10: of the Software, and to permit persons to whom the Software is cannam@10: furnished to do so, subject to the following conditions: cannam@10: cannam@10: The above copyright notice and this permission notice shall be cannam@10: included in all copies or substantial portions of the Software. cannam@10: cannam@10: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, cannam@10: EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF cannam@10: MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND cannam@10: NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR cannam@10: ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF cannam@10: CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION cannam@10: WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. cannam@10: cannam@10: Except as contained in this notice, the names of the Centre for cannam@10: Digital Music; Queen Mary, University of London; and Chris Cannam cannam@10: shall not be used in advertising or otherwise to promote the sale, cannam@10: use or other dealings in this Software without prior written cannam@10: authorization. cannam@10: */ cannam@10: cannam@10: #include "TestInitialise.h" cannam@10: cannam@10: #include cannam@10: #include cannam@10: using namespace Vamp; cannam@10: using namespace Vamp::HostExt; cannam@10: cannam@10: #include cannam@10: #include cannam@10: using namespace std; cannam@10: cannam@10: #include Chris@45: #include cannam@10: cannam@10: Tester::TestRegistrar Chris@39: TestSampleRates::m_registrar("F1", "Different sample rates"); cannam@10: cannam@10: Tester::TestRegistrar Chris@39: TestLengthyConstructor::m_registrar("F2", "Lengthy constructor"); cannam@10: cannam@10: Test::Results cannam@23: TestSampleRates::test(string key, Options options) cannam@10: { cannam@10: int rates[] = Chris@43: { 111, 800, 10099, 11024, 44100, 48000, 96000, 192000, 201011, 1094091 }; cannam@10: cannam@10: Results r; cannam@10: cannam@23: if (options & Verbose) { cannam@23: cout << " "; cannam@23: } cannam@23: cannam@14: for (int i = 0; i < int(sizeof(rates)/sizeof(rates[0])); ++i) { cannam@10: cannam@10: int rate = rates[i]; cannam@23: cannam@23: if (options & Verbose) { cannam@23: cout << "[" << rate << "Hz] " << flush; cannam@23: } cannam@23: cannam@10: auto_ptr p(load(key, rate)); cannam@10: Plugin::FeatureSet f; cannam@10: float **data = 0; cannam@10: size_t channels = 0; Chris@43: Chris@43: // Aim to feed the plugin a roughly fixed input duration in secs Chris@43: const float seconds = 10.f; Chris@43: size_t step = 1000; Chris@43: size_t count = (seconds * rate) / step; Chris@43: if (count < 1) count = 1; cannam@10: cannam@23: Results subr; Chris@43: if (!initAdapted(p.get(), channels, step, step, subr)) { cannam@23: // This is not an error; the plugin can legitimately cannam@23: // refuse to initialise at weird settings and that's often cannam@23: // the most acceptable result cannam@23: if (!subr.empty()) { cannam@23: r.push_back(note(subr.begin()->message())); cannam@23: } cannam@23: continue; cannam@23: } cannam@10: Chris@43: data = createTestAudio(channels, step, count); Chris@43: for (size_t j = 0; j < count; ++j) { Chris@67: float **ptr = new float *[channels]; Chris@43: size_t idx = j * step; cannam@10: for (size_t c = 0; c < channels; ++c) ptr[c] = data[c] + idx; cannam@10: RealTime timestamp = RealTime::frame2RealTime(idx, rate); cannam@10: Plugin::FeatureSet fs = p->process(ptr, timestamp); Chris@67: delete[] ptr; cannam@10: appendFeatures(f, fs); cannam@10: } cannam@10: Plugin::FeatureSet fs = p->getRemainingFeatures(); cannam@10: appendFeatures(f, fs); cannam@10: destroyTestAudio(data, channels); cannam@10: } cannam@10: cannam@23: if (options & Verbose) cout << endl; cannam@23: cannam@10: // We can't actually do anything meaningful with our results. cannam@10: // We're really just testing to see whether the plugin crashes. I cannam@10: // wonder whether it's possible to do any better? If not, we cannam@10: // should probably report our limitations cannam@10: cannam@10: return r; cannam@10: } cannam@10: cannam@10: Test::Results cannam@14: TestLengthyConstructor::test(string key, Options) cannam@10: { cannam@10: time_t t0 = time(0); cannam@10: auto_ptr p(load(key)); cannam@10: time_t t1 = time(0); cannam@10: Results r; cannam@10: if (t1 - t0 > 1) r.push_back(warning("Constructor takes some time to run: work should be deferred to initialise?")); cannam@10: return r; cannam@10: } cannam@10: