IAudioProcessor::setProcessing fails in many plugins

Hi all,
I’ve been working on developing a basic VST3 host and succeeded in implementing both audio and GUI functionality. It’s working correctly with several plugins, but unfortunately with many others (such as Oril River and most of the iZotope plugins) IAudioProcessor::setProcessing returns false after setting everything up. When this happens, the plugin simply does no processing and I hear silence. I’ll post the code below in case it helps anyone, I did my best to remove some of the unnecessary parts and focus on the VST-specific sections but it’s still kind of lengthy (if this isn’t the appropriate place for code snippets then moderators feel free to edit the post and remove or relocate it)…

VST3::Hosting::Module::Ptr _module = nullptr;
Steinberg::IPtr<Steinberg::Vst::PlugProvider> _plugProvider = nullptr;
Steinberg::OPtr<Steinberg::Vst::IComponent> _component = nullptr;
Steinberg::OPtr<Steinberg::Vst::IAudioProcessor> _processor = nullptr;
Steinberg::OPtr<Steinberg::Vst::IEditController> _controller = nullptr;
Steinberg::IPtr<Steinberg::IPlugView> _view = nullptr;

Steinberg::Vst::AudioBusBuffers _input, _output;
Steinberg::Vst::ProcessData _processData;
bool _processingIsSet = false;

float **inBufs = nullptr, **outBufs = nullptr;

namespace Steinberg {
Steinberg::FUnknown *gStandardPluginContext = nullptr;
}

static int audioCallback(const void *input, void *voidOutput, unsigned long numFrames, const PaStreamCallbackTimeInfo *timeInfo, PaStreamCallbackFlags statusFlags, void *voidUserData)
{
	auto output = static_cast<float *>(voidOutput);

	//
	// Clear output to zero
	// Read audio file data into inBufs[0] and inBufs[1]
	//

	if (!_processingIsSet) {
		if (_processor->setProcessing(true) != Steinberg::kResultOk) {
			std::cerr << "Failed to set VST processing to true" << std::endl;
			return false;
		}

		_processingIsSet = true;
	}

	_input.silenceFlags = 0;
	_input.channelBuffers32 = inBufs;

	_output.silenceFlags = 0;
	_output.channelBuffers32 = outBufs;

	if (_processor->process(_processData) == Steinberg::kResultOk) {
		for (ma_uint64 i = 0; i < numFrames; ++i) {
			output[i * 2 + 0] = outBufs[0][i];
			output[i * 2 + 1] = outBufs[1][i];
		}
	} else {
		std::cerr << "VST processing failed" << std::endl;
	}

	return 0;
}

// Usage: app [plugin filename].vst3 [audio file name].(wav|flac|mp3)
int main(int argc, char *argv[])
{
	const int BLOCK_SIZE = 4096;
	const int SAMPLE_RATE = 44100;

	if (!Steinberg::gStandardPluginContext) {
		Steinberg::gStandardPluginContext = new Steinberg::Vst::HostApplication();
		Steinberg::Vst::PluginContextFactory::instance().setPluginContext(Steinberg::gStandardPluginContext);
	}

	std::string err;
	_module = VST3::Hosting::Module::create(argv[1], err);
	if (!_module) {
		_logError(err);
		return -1;
	}

	auto &factory = _module->getFactory();
	for (auto &classInfo : factory.classInfos()) {
		if (classInfo.category() == kVstAudioEffectClass) {
			_plugProvider = Steinberg::owned(NEW Steinberg::Vst::PlugProvider(factory, classInfo, true));
			break;
		}
	}
	if (!_plugProvider) {
		_logError("No audio module class found");
		return -1;
	}

	_component = _plugProvider->getComponent();
	if (!_component) {
		_logError("No component found");
		return -1;
	}

	if (_component->queryInterface(Steinberg::Vst::IAudioProcessor::iid, reinterpret_cast<void **>(&_processor)) != Steinberg::kResultOk || !_processor) {
		_logError("Component does not implement IAudioProcessor");
		return -1;
	}

	Steinberg::Vst::SpeakerArrangement stereoArrangement = Steinberg::Vst::SpeakerArr::kStereo;
	if (_processor->setBusArrangements(&stereoArrangement, 1, &stereoArrangement, 1) != Steinberg::kResultOk) {
		_logError("Failed to set bus arrangements");
		return -1;
	}

	Steinberg::Vst::ProcessSetup setup = {};
	setup.processMode = Steinberg::Vst::kRealtime;
	setup.symbolicSampleSize = Steinberg::Vst::kSample32;
	setup.maxSamplesPerBlock = BLOCK_SIZE;
	setup.sampleRate = SAMPLE_RATE;

	if (_processor->setupProcessing(setup) != Steinberg::kResultOk) {
		_logError("Failed to set up processing");
		return -1;
	}

	if (_component->setActive(true) != Steinberg::kResultOk) {
		_logError("Failed to set component active");
		return -1;
	}

	_input.numChannels = 2;
	_output.numChannels = 2;

	_processData.processMode = Steinberg::Vst::ProcessModes::kRealtime;
	_processData.symbolicSampleSize = Steinberg::Vst::kSample32;
	_processData.numSamples = BLOCK_SIZE;
	_processData.numInputs = 1;
	_processData.numOutputs = 1;
	_processData.inputs = &_input;
	_processData.outputs = &_output;

	_controller = _plugProvider->getController();
	if (!_controller) {
		_logError("No edit controller found");
		return -1;
	}

	_view = Steinberg::owned(_controller->createView(Steinberg::Vst::ViewType::kEditor));
	if (!_view) {
		_logError("EditController does not provide its own view");
		return -1;
	}

	Steinberg::ViewRect viewRect = {};
	if (_view->getSize(&viewRect) != Steinberg::kResultOk) {
		_logError("Failed to get editor view size");
		return -1;
	}

	if (_view->isPlatformTypeSupported(Steinberg::kPlatformTypeHWND) != Steinberg::kResultTrue) {
		_logError("Editor view does not support HWND");
		return -1;
	}

	//
	// Create a window using SDL
	// wmInfo.info.win.window stores the HWND of the window
	//

	if (_view->attached(wmInfo.info.win.window, Steinberg::kPlatformTypeHWND) != Steinberg::kResultOk) {
		_logError("Failed to attach editor view to HWND");
		return -1;
	}

	inBufs = new float *[2];
	inBufs[0] = new float[BLOCK_SIZE];
	inBufs[1] = new float[BLOCK_SIZE];
	outBufs = new float *[2];
	outBufs[0] = new float[BLOCK_SIZE];
	outBufs[1] = new float[BLOCK_SIZE];

	//
	// Start PortAudio stream
	//
	
	//
	// GUI Main Loop
	//

	//
	// Destroy everything
	//

	return 0;
}

Hey TinyDaw I really want to help but I face the exact same problem. Maybe someone of the Dev Team could give a hint what to do?

Have you checked that these plug-ins pass all validator checks? If they do, you can debug step by step which calls the validator does and see where you differ.

I tested Oril River with the validator and it passed all checks, but as far as I can tell, none of the validator tests check the return value of setProcessing at any point (for example, https://github.com/steinbergmedia/vst3_public_sdk/blob/master/source/vst/testsuite/processing/process.cpp#L89=), so they don’t catch when this issue occurs.

When I added additional logging to report the output of setProcessing, it reported that setProcessing does not return kResultOk in that test.

I changed the process.cpp line linked above to the following block of code:

if (audioEffect->setProcessing(true) != Steinberg::kResultOk) {
	addErrorMessage(testResult, STR("IAudioProcessor::setProcessing failed."));
} else {
	addMessage(testResult, STR("IAudioProcessor::setProcessing succeeded."));
}

Then running the validator displays ERROR: IAudioProcessor::setProcessing failed.
When testing with TAL-Reverb-4 (which works with my VST code), the validator displays Info: IAudioProcessor::setProcessing succeeded.

Sorry, no idea then. You may get in contact with the developers of the plug-ins and ask them why they don’t work in your context.

Understandable. I guess my concern was that these plugins seem to work in commercial DAWs but not in this stand-alone host, leading me to think that something is wrong with my implementation and not the plugin. I’ll see if I can contact a developer. Thanks for taking a look.