cannam@150: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ cannam@150: /* cannam@150: Piper C++ cannam@150: cannam@150: An API for audio analysis and feature extraction plugins. cannam@150: cannam@150: Centre for Digital Music, Queen Mary, University of London. cannam@150: Copyright 2006-2016 Chris Cannam and QMUL. cannam@150: cannam@150: Permission is hereby granted, free of charge, to any person cannam@150: obtaining a copy of this software and associated documentation cannam@150: files (the "Software"), to deal in the Software without cannam@150: restriction, including without limitation the rights to use, copy, cannam@150: modify, merge, publish, distribute, sublicense, and/or sell copies cannam@150: of the Software, and to permit persons to whom the Software is cannam@150: furnished to do so, subject to the following conditions: cannam@150: cannam@150: The above copyright notice and this permission notice shall be cannam@150: included in all copies or substantial portions of the Software. cannam@150: cannam@150: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, cannam@150: EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF cannam@150: MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND cannam@150: NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR cannam@150: ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF cannam@150: CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION cannam@150: WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. cannam@150: cannam@150: Except as contained in this notice, the names of the Centre for cannam@150: Digital Music; Queen Mary, University of London; and Chris Cannam cannam@150: shall not be used in advertising or otherwise to promote the sale, cannam@150: use or other dealings in this Software without prior written cannam@150: authorization. cannam@150: */ cannam@150: cannam@150: #include "ProcessQtTransport.h" cannam@150: #include "CapnpRRClient.h" cannam@208: #include "PiperAutoPlugin.h" cannam@150: cannam@270: #include cannam@270: cannam@150: #include cannam@150: cannam@150: using std::cerr; cannam@150: using std::endl; cannam@150: using std::exception; cannam@150: using std::vector; cannam@270: using std::string; cannam@150: cannam@150: int main(int argc, char **argv) cannam@150: { cannam@150: if (argc != 2) { cannam@150: cerr << "Usage: " << argv[0] << " " << endl; cannam@150: return 2; cannam@150: } cannam@150: cannam@270: string server = argv[1]; cannam@270: string format = "capnp"; cannam@270: string zeroCrossing = "vamp-example-plugins:zerocrossing"; cannam@270: string powerSpectrum = "vamp-example-plugins:powerspectrum"; cannam@270: piper_vamp::client::LogCallback *logger = nullptr; cannam@270: cannam@150: try { cannam@270: cerr << endl << "*** Test: starting transport" << endl; cannam@270: piper_vamp::client::ProcessQtTransport transport(server, format, logger); cannam@150: if (!transport.isOK()) { cannam@274: cerr << "--- ERROR: Transport failed to start" << endl; cannam@150: return 1; cannam@150: } cannam@274: cerr << "+++ OK" << endl; cannam@150: cannam@270: cerr << endl << "*** Test: constructing client" << endl; cannam@270: piper_vamp::client::CapnpRRClient client(&transport, logger); cannam@274: cerr << "+++ OK" << endl; cannam@270: cannam@270: cerr << endl << "*** Test: listing plugins" << endl; cannam@207: piper_vamp::ListResponse lr = client.list({}); cannam@274: cerr << "+++ OK; plugins are:" << endl; cannam@150: int i = 1; cannam@150: for (const auto &p: lr.available) { cannam@150: cerr << i++ << ". [" << p.pluginKey << "] " << p.basic.name << endl; cannam@150: } cannam@270: cannam@270: enum { cannam@270: explicitServer = 1, cannam@270: autoServer = 2 cannam@270: }; cannam@270: enum { cannam@270: timeDomain = 1, cannam@270: frequencyDomainServerSide = 2, cannam@270: frequencyDomainClientSide = 3 cannam@270: }; cannam@270: cannam@270: for (int domain = timeDomain; cannam@270: domain <= frequencyDomainClientSide; cannam@270: ++domain) { cannam@270: cannam@270: for (int serverSort = explicitServer; cannam@270: serverSort <= autoServer; cannam@270: ++serverSort) { cannam@270: cannam@270: string id = zeroCrossing; cannam@270: if (domain == frequencyDomainServerSide || cannam@270: domain == frequencyDomainClientSide) { cannam@270: id = powerSpectrum; cannam@270: } cannam@270: cannam@270: Vamp::Plugin *plugin = nullptr; cannam@270: cannam@270: int adapterFlags = 0; cannam@270: if (domain == frequencyDomainServerSide) { cannam@270: adapterFlags = (int) cannam@270: Vamp::HostExt::PluginLoader::ADAPT_INPUT_DOMAIN; cannam@270: } cannam@270: cannam@270: if (serverSort == explicitServer) { cannam@270: cannam@270: cerr << endl << "*** Test: loading \"" << id cannam@270: << "\" with explicit server" << endl; cannam@270: cannam@270: piper_vamp::LoadRequest req; cannam@270: req.pluginKey = id; cannam@270: req.inputSampleRate = 16; cannam@270: req.adapterFlags = adapterFlags; cannam@270: piper_vamp::LoadResponse resp = client.load(req); cannam@270: plugin = resp.plugin; cannam@270: if (!plugin) { cannam@274: cerr << "--- ERROR: plugin is null" << endl; cannam@270: return 1; cannam@270: } cannam@274: cerr << "+++ OK" << endl; cannam@270: cannam@270: } else { cannam@270: cannam@270: cerr << endl << "*** Test: loading \"" << id cannam@270: << "\" with auto-plugin" << endl; cannam@270: cannam@270: piper_vamp::client::PiperAutoPlugin *ap = cannam@270: new piper_vamp::client::PiperAutoPlugin cannam@270: (server, id, 16, adapterFlags, logger); cannam@270: if (!ap->isOK()) { cannam@274: cerr << "--- ERROR: PiperAutoPlugin creation failed" << endl; cannam@270: return 1; cannam@270: } cannam@274: cerr << "+++ OK" << endl; cannam@270: cannam@270: plugin = ap; cannam@270: } cannam@270: cannam@270: if (domain == frequencyDomainClientSide) { cannam@270: cerr << "*** Test: creating input-domain adapter" << endl; cannam@270: plugin = new Vamp::HostExt::PluginInputDomainAdapter(plugin); cannam@274: cerr << "+++ OK" << endl; cannam@270: } cannam@270: cannam@270: cerr << endl << "*** Test: initialising plugin" << endl; cannam@270: if (!plugin->initialise(1, 4, 4)) { cannam@274: cerr << "--- ERROR: initialisation failed" << endl; cannam@270: return 1; cannam@270: } cannam@274: cerr << "+++ OK" << endl; cannam@270: cannam@270: for (int round = 1; round <= 2; ++round) { cannam@270: cerr << endl << "*** Test: processing" cannam@270: << " (domain " << domain cannam@270: << ", sort " << serverSort cannam@270: << ", round " << round << ")" << endl; cannam@270: cannam@270: vector buf = { 1.0, -1.0, 1.0, -1.0 }; cannam@270: float *bd = buf.data(); cannam@270: Vamp::Plugin::FeatureSet features = plugin->process cannam@270: (&bd, Vamp::RealTime::zeroTime); cannam@274: cerr << "+++ OK, process succeeded" << endl; cannam@270: if (features[0].size() != 1) { cannam@274: cerr << "--- ERROR: wrong number of features on output 0" cannam@270: << " (expected 1, obtained " << features[0].size() << ")" cannam@270: << endl; cannam@270: return 1; cannam@270: } cannam@270: vector expected; cannam@270: if (domain == timeDomain) { cannam@270: expected.push_back(4); cannam@270: } else { cannam@270: // these would be 0, 0, 16 if we were cannam@270: // calculating the power spectrum without cannam@270: // windowing - but the input domain adapter cannam@270: // does window, and an asymmetrical Hann cannam@270: // window gives these results cannam@270: expected.push_back(0); cannam@270: expected.push_back(1); cannam@270: expected.push_back(4); cannam@270: } cannam@270: cannam@270: if (features[0][0].values.size() != expected.size()) { cannam@274: cerr << "--- ERROR: wrong size for feature on output 0" cannam@270: << " (expected " << expected.size() cannam@270: << ", obtained " cannam@270: << features[0][0].values.size() << ")" << endl; cannam@270: return 1; cannam@270: } cannam@270: for (size_t i = 0; i < expected.size(); ++i) { cannam@270: if (features[0][0].values[i] != expected[i]) { cannam@274: cerr << "--- ERROR: wrong value for index " << i cannam@270: << " of feature on output 0" cannam@270: << " (expected " << expected[i] cannam@270: << ", obtained " cannam@270: << features[0][0].values[i] << ")" << endl; cannam@270: cerr << "(All obtained values are:"; cannam@270: for (size_t j = 0; j < expected.size(); ++j) { cannam@270: cerr << " " << features[0][0].values[j]; cannam@270: } cannam@270: cerr << ")" << endl; cannam@270: return 1; cannam@270: } cannam@270: } cannam@274: cerr << "+++ OK, results are correct" << endl; cannam@270: cannam@270: (void)plugin->getRemainingFeatures(); cannam@270: cannam@270: if (round == 1) { cannam@270: cerr << endl << "*** Test: resetting plugin for round 2" << endl; cannam@270: plugin->reset(); cannam@274: cerr << "+++ OK" << endl; cannam@270: } cannam@270: } cannam@270: cannam@270: cerr << endl << "*** Test: deleting plugin" << endl; cannam@270: delete plugin; cannam@274: cerr << "+++ OK" << endl; cannam@150: } cannam@150: } cannam@150: cannam@150: } catch (const exception &e) { cannam@274: cerr << "--- ERROR: Exception caught: " << e.what() << endl; cannam@150: return 1; cannam@150: } cannam@150: cannam@270: cerr << endl << "*** All tests succeeded" << endl; cannam@270: cannam@150: return 0; cannam@150: } cannam@150: