dev@190: #include "catch/catch.hpp" dev@191: #include "vamp-client/Loader.h" dev@191: #include "vamp-client/PluginClient.h" cannam@213: #include "vamp-client/PiperVampPlugin.h" dev@191: #include "vamp-support/RequestResponse.h" dev@191: #include dev@190: dev@191: using namespace piper_vamp; dev@191: using namespace piper_vamp::client; dev@191: using AudioBuffer = std::vector>; dev@190: dev@196: // This stub fakes the interaction with a Piper server dev@191: // Here we only need to implement the configure method cannam@213: // due to testing only the initialise implemention of PiperVampPlugin dev@191: class StubClient : public PluginClient dev@191: { dev@191: public: dev@191: StubClient(PluginStaticData staticData) : m_staticData(staticData) {} dev@191: dev@191: ConfigurationResponse cannam@213: configure(PiperVampPlugin* plugin, dev@191: PluginConfiguration config) override dev@191: { dev@191: const float scale = plugin->getParameter("framing-scale"); dev@191: ConfigurationResponse cr; dev@191: cr.plugin = plugin; dev@191: dev@194: // we want to return different framing sizes than config provides dev@191: // there isn't really any need to be doing this with a plugin param dev@194: cr.framing.blockSize = config.framing.blockSize * scale; dev@194: cr.framing.stepSize = config.framing.stepSize * scale; dev@191: dev@191: // just return some outputs anyway dev@191: // to avoid a failure case we are not testing here. dev@191: Vamp::Plugin::OutputDescriptor output; dev@191: const auto basic = m_staticData.basicOutputInfo[0]; dev@191: output.identifier = basic.identifier; dev@191: output.name = basic.name; dev@191: output.description = basic.description; dev@191: cr.outputs = {output}; dev@191: return cr; dev@191: } dev@191: dev@191: Vamp::Plugin::FeatureSet cannam@213: process(PiperVampPlugin* /*plugin*/, dev@191: AudioBuffer /*channels*/, dev@191: Vamp::RealTime /*timestamp*/) override dev@191: { dev@191: return {}; dev@191: } dev@191: dev@191: Vamp::Plugin::FeatureSet cannam@213: finish(PiperVampPlugin* /*plugin*/) override dev@191: { dev@191: return {}; dev@191: } dev@191: dev@191: void cannam@213: reset(PiperVampPlugin* /*plugin*/, PluginConfiguration /*config*/) override dev@191: {} dev@191: private: dev@191: PluginStaticData m_staticData; dev@191: }; dev@191: dev@191: dev@191: TEST_CASE("Init plugin with parameter dependent preferred framing sizes") { dev@194: const std::size_t initialBlockSize = 1024; dev@194: const std::size_t initialStepSize = 512; dev@191: PluginConfiguration defaultConfig; dev@191: defaultConfig.channelCount = 1; dev@194: defaultConfig.framing.blockSize = initialBlockSize; dev@194: defaultConfig.framing.stepSize = initialStepSize; dev@191: defaultConfig.parameterValues = {{"framing-scale", 1.0}}; dev@191: dev@191: Vamp::PluginBase::ParameterDescriptor stubParam; dev@191: stubParam.identifier = "framing-scale"; dev@191: stubParam.name = "Framing Scale Factor"; dev@191: stubParam.description = "Scales the preferred framing sizes"; dev@191: stubParam.maxValue = 2.0; dev@191: dev@191: PluginStaticData staticData; dev@191: staticData.pluginKey = "stub"; dev@202: staticData.basic = {"param-init", "Stub", "Testing init"}; dev@191: staticData.maker = "Lucas Thompson"; dev@191: staticData.copyright = "GPL"; dev@191: staticData.pluginVersion = 1; dev@191: staticData.category = {"Test"}; dev@191: staticData.minChannelCount = 1; dev@191: staticData.maxChannelCount = 1; dev@191: staticData.parameters = {stubParam}; dev@191: staticData.inputDomain = Vamp::Plugin::InputDomain::TimeDomain; dev@191: staticData.basicOutputInfo = {{"output", "NA", "Not real"}}; dev@191: cannam@287: PluginProgramParameters programParameters; cannam@287: // none cannam@287: dev@191: StubClient stub {staticData}; dev@191: cannam@213: PiperVampPlugin vampPiperAdapter { dev@191: &stub, dev@191: "stub", // plugin key dev@191: 44100.0, // sample rate dev@191: 0, // adapter flags, don't care here dev@191: staticData, cannam@287: defaultConfig, cannam@287: programParameters dev@191: }; dev@191: dev@194: const auto initWithPreferredFraming = [&]() -> bool { dev@194: return vampPiperAdapter.initialise( dev@191: 1, dev@191: vampPiperAdapter.getPreferredStepSize(), dev@191: vampPiperAdapter.getPreferredBlockSize() dev@194: ); dev@194: }; dev@194: dev@202: const AudioBuffer monoAudio { dev@202: std::vector(vampPiperAdapter.getPreferredBlockSize()) dev@202: }; dev@202: const std::vector channelPtrs { dev@202: monoAudio[0].data() dev@202: }; dev@202: dev@194: SECTION("Initialises with default parameters") dev@194: { dev@194: REQUIRE( initWithPreferredFraming() ); dev@194: } dev@194: dev@194: SECTION("Fails to init when changing framing influencing parameter") dev@194: { dev@194: const float scalingFactor = 2.0; dev@194: vampPiperAdapter.setParameter("framing-scale", scalingFactor); dev@194: REQUIRE( initWithPreferredFraming() == false ); dev@194: const float configuredStepSize = vampPiperAdapter.getPreferredStepSize(); dev@194: const float configuredBlockSize = vampPiperAdapter.getPreferredBlockSize(); dev@194: REQUIRE( configuredStepSize == initialStepSize * scalingFactor ); dev@194: REQUIRE( configuredBlockSize == initialBlockSize * scalingFactor ); dev@194: } dev@194: dev@194: SECTION("Cannot process after a failed init call (due to framing)") dev@194: { dev@194: const float scalingFactor = 2.0; dev@194: vampPiperAdapter.setParameter("framing-scale", scalingFactor); dev@194: REQUIRE( initWithPreferredFraming() == false ); dev@202: REQUIRE_THROWS( vampPiperAdapter.process(channelPtrs.data(), {}) ); dev@199: REQUIRE_THROWS( initWithPreferredFraming() ); dev@194: } dev@194: dev@194: SECTION("Can process after correctly initialising framing") dev@194: { dev@194: const float scalingFactor = 2.0; dev@194: vampPiperAdapter.setParameter("framing-scale", scalingFactor); dev@194: REQUIRE( initWithPreferredFraming() == false ); dev@194: REQUIRE( initWithPreferredFraming() ); dev@194: REQUIRE( vampPiperAdapter.process(channelPtrs.data(), {}).empty() ); dev@194: } dev@190: }