cannam@1: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ cannam@1: cannam@1: /* cannam@1: Vamp Plugin Tester cannam@1: Chris Cannam, cannam@all-day-breakfast.com cannam@1: Centre for Digital Music, Queen Mary, University of London. cannam@1: Copyright 2009 QMUL. cannam@1: cannam@1: This program loads a Vamp plugin and tests its susceptibility to a cannam@1: number of common pitfalls, including handling of extremes of input cannam@1: data. If you can think of any additional useful tests that are cannam@1: easily added, please send them to me. cannam@1: cannam@1: Permission is hereby granted, free of charge, to any person cannam@1: obtaining a copy of this software and associated documentation cannam@1: files (the "Software"), to deal in the Software without cannam@1: restriction, including without limitation the rights to use, copy, cannam@1: modify, merge, publish, distribute, sublicense, and/or sell copies cannam@1: of the Software, and to permit persons to whom the Software is cannam@1: furnished to do so, subject to the following conditions: cannam@1: cannam@1: The above copyright notice and this permission notice shall be cannam@1: included in all copies or substantial portions of the Software. cannam@1: cannam@1: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, cannam@1: EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF cannam@1: MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND cannam@1: NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR cannam@1: ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF cannam@1: CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION cannam@1: WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. cannam@1: cannam@1: Except as contained in this notice, the names of the Centre for cannam@1: Digital Music; Queen Mary, University of London; and Chris Cannam cannam@1: shall not be used in advertising or otherwise to promote the sale, cannam@1: use or other dealings in this Software without prior written cannam@1: authorization. cannam@1: */ cannam@1: cannam@1: #include "TestInputExtremes.h" cannam@1: cannam@1: #include cannam@1: using namespace Vamp; cannam@1: cannam@1: #include cannam@1: using namespace std; cannam@1: cannam@2: #include cannam@1: #include cannam@1: cannam@1: Tester::TestRegistrar cannam@4: TestNormalInput::m_registrar("C1 Normal input"); cannam@1: cannam@1: Tester::TestRegistrar cannam@4: TestNoInput::m_registrar("C2 Empty input"); cannam@1: cannam@1: Tester::TestRegistrar cannam@4: TestShortInput::m_registrar("C3 Short input"); cannam@1: cannam@1: Tester::TestRegistrar cannam@4: TestSilentInput::m_registrar("C4 Absolutely silent input"); cannam@1: cannam@1: Tester::TestRegistrar cannam@14: TestTooLoudInput::m_registrar("C5 Input beyond traditional +/-1 range"); cannam@1: cannam@1: Tester::TestRegistrar cannam@4: TestRandomInput::m_registrar("C6 Random input"); cannam@1: cannam@1: Test::Results cannam@8: TestNormalInput::test(string key, Options options) cannam@1: { cannam@2: Plugin::FeatureSet f; cannam@1: int rate = 44100; cannam@1: auto_ptr p(load(key, rate)); cannam@1: Results r; cannam@1: size_t channels, step, blocksize; cannam@1: if (!initDefaults(p.get(), channels, step, blocksize, r)) return r; cannam@1: float **block = createBlock(channels, blocksize); cannam@1: int idx = 0; cannam@1: for (int i = 0; i < 200; ++i) { cannam@1: for (size_t j = 0; j < blocksize; ++j) { cannam@1: for (size_t c = 0; c < channels; ++c) { cannam@1: block[c][j] = sinf(float(idx) / 10.f); cannam@1: } cannam@1: ++idx; cannam@1: } cannam@1: RealTime timestamp = RealTime::frame2RealTime(idx, rate); cannam@2: Plugin::FeatureSet fs = p->process(block, timestamp); cannam@2: appendFeatures(f, fs); cannam@1: } cannam@1: destroyBlock(block, channels); cannam@1: Plugin::FeatureSet fs = p->getRemainingFeatures(); cannam@2: appendFeatures(f, fs); cannam@2: if (allFeaturesValid(f)) { cannam@1: r.push_back(success()); cannam@1: } else { cannam@17: r.push_back(warning("Plugin returned one or more NaN/inf values")); cannam@8: if (options & Verbose) dump(f); cannam@1: } cannam@1: return r; cannam@1: } cannam@1: cannam@1: Test::Results cannam@16: TestNoInput::test(string key, Options) cannam@1: { cannam@1: auto_ptr p(load(key)); cannam@1: Results r; cannam@1: size_t channels, step, block; cannam@1: if (!initDefaults(p.get(), channels, step, block, r)) return r; cannam@1: Plugin::FeatureSet fs = p->getRemainingFeatures(); cannam@1: if (allFeaturesValid(fs)) { cannam@1: r.push_back(success()); cannam@1: } else { cannam@17: r.push_back(warning("Plugin returned one or more NaN/inf values")); cannam@1: } cannam@1: return r; cannam@1: } cannam@1: cannam@1: Test::Results cannam@8: TestShortInput::test(string key, Options options) cannam@1: { cannam@2: Plugin::FeatureSet f; cannam@1: int rate = 44100; cannam@1: auto_ptr p(load(key, rate)); cannam@1: Results r; cannam@1: size_t channels, step, blocksize; cannam@1: if (!initDefaults(p.get(), channels, step, blocksize, r)) return r; cannam@1: float **block = createBlock(channels, blocksize); cannam@1: int idx = 0; cannam@1: for (size_t j = 0; j < blocksize; ++j) { cannam@1: for (size_t c = 0; c < channels; ++c) { cannam@1: block[c][j] = sinf(float(idx) / 10.f); cannam@1: } cannam@1: ++idx; cannam@1: } cannam@2: Plugin::FeatureSet fs = p->process(block, RealTime::zeroTime); cannam@2: appendFeatures(f, fs); cannam@1: destroyBlock(block, channels); cannam@2: fs = p->getRemainingFeatures(); cannam@2: appendFeatures(f, fs); cannam@2: if (allFeaturesValid(f)) { cannam@1: r.push_back(success()); cannam@1: } else { cannam@17: r.push_back(warning("Plugin returned one or more NaN/inf values")); cannam@8: if (options & Verbose) dump(f); cannam@1: } cannam@1: return r; cannam@1: } cannam@1: cannam@1: Test::Results cannam@8: TestSilentInput::test(string key, Options options) cannam@1: { cannam@2: Plugin::FeatureSet f; cannam@1: int rate = 44100; cannam@1: auto_ptr p(load(key, rate)); cannam@1: Results r; cannam@1: size_t channels, step, blocksize; cannam@1: if (!initDefaults(p.get(), channels, step, blocksize, r)) return r; cannam@1: float **block = createBlock(channels, blocksize); cannam@1: for (size_t j = 0; j < blocksize; ++j) { cannam@1: for (size_t c = 0; c < channels; ++c) { cannam@1: block[c][j] = 0.f; cannam@1: } cannam@1: } cannam@1: for (int i = 0; i < 200; ++i) { cannam@1: RealTime timestamp = RealTime::frame2RealTime(i * blocksize, rate); cannam@2: Plugin::FeatureSet fs = p->process(block, timestamp); cannam@2: appendFeatures(f, fs); cannam@1: } cannam@1: destroyBlock(block, channels); cannam@1: Plugin::FeatureSet fs = p->getRemainingFeatures(); cannam@2: appendFeatures(f, fs); cannam@2: if (allFeaturesValid(f)) { cannam@1: r.push_back(success()); cannam@1: } else { cannam@17: r.push_back(warning("Plugin returned one or more NaN/inf values")); cannam@8: if (options & Verbose) dump(f); cannam@1: } cannam@1: return r; cannam@1: } cannam@1: cannam@1: Test::Results cannam@8: TestTooLoudInput::test(string key, Options options) cannam@1: { cannam@2: Plugin::FeatureSet f; cannam@1: int rate = 44100; cannam@1: auto_ptr p(load(key, rate)); cannam@1: Results r; cannam@1: size_t channels, step, blocksize; cannam@1: if (!initDefaults(p.get(), channels, step, blocksize, r)) return r; cannam@1: float **block = createBlock(channels, blocksize); cannam@1: int idx = 0; cannam@1: for (int i = 0; i < 200; ++i) { cannam@1: for (size_t j = 0; j < blocksize; ++j) { cannam@1: for (size_t c = 0; c < channels; ++c) { cannam@1: block[c][j] = 1000.f * sinf(float(idx) / 10.f); cannam@1: } cannam@1: ++idx; cannam@1: } cannam@1: RealTime timestamp = RealTime::frame2RealTime(idx, rate); cannam@2: Plugin::FeatureSet fs = p->process(block, timestamp); cannam@2: appendFeatures(f, fs); cannam@1: } cannam@1: destroyBlock(block, channels); cannam@1: Plugin::FeatureSet fs = p->getRemainingFeatures(); cannam@2: appendFeatures(f, fs); cannam@2: if (allFeaturesValid(f)) { cannam@1: r.push_back(success()); cannam@1: } else { cannam@17: r.push_back(warning("Plugin returned one or more NaN/inf values")); cannam@8: if (options & Verbose) dump(f); cannam@1: } cannam@1: return r; cannam@1: } cannam@1: cannam@1: Test::Results cannam@8: TestRandomInput::test(string key, Options options) cannam@1: { cannam@2: Plugin::FeatureSet f; cannam@1: int rate = 44100; cannam@1: auto_ptr p(load(key, rate)); cannam@1: Results r; cannam@1: size_t channels, step, blocksize; cannam@1: if (!initDefaults(p.get(), channels, step, blocksize, r)) return r; cannam@1: float **block = createBlock(channels, blocksize); cannam@1: int idx = 0; cannam@1: for (int i = 0; i < 100; ++i) { cannam@1: for (size_t j = 0; j < blocksize; ++j) { cannam@1: for (size_t c = 0; c < channels; ++c) { cannam@21: block[c][j] = (float(rand()) / RAND_MAX) * 2.0 - 1.0; cannam@1: } cannam@1: ++idx; cannam@1: } cannam@1: RealTime timestamp = RealTime::frame2RealTime(idx, rate); cannam@2: Plugin::FeatureSet fs = p->process(block, timestamp); cannam@2: appendFeatures(f, fs); cannam@1: } cannam@1: destroyBlock(block, channels); cannam@1: Plugin::FeatureSet fs = p->getRemainingFeatures(); cannam@2: appendFeatures(f, fs); cannam@2: if (allFeaturesValid(f)) { cannam@1: r.push_back(success()); cannam@1: } else { cannam@17: r.push_back(warning("Plugin returned one or more NaN/inf values")); cannam@8: if (options & Verbose) dump(f); cannam@1: } cannam@1: return r; cannam@1: } cannam@1: