The result rendered through vst2 sounds weird

hi,sorry to disturb.I’m a new user of JUCE.
I need to render audio file through vst2 and vst3 plugins.vst3 just works fine,but the result of vst2 sounds very weird,I’ve tried several vst2 plugins,all weird.
Is there any wrong with my codes?
thanks a lot.

// scan plugin
juce::AudioFormatManager formatManager;
formatManager.registerBasicFormats();
juce::AudioPluginFormatManager pluginFormatManager;
pluginFormatManager.addDefaultFormats();
juce::PluginDescription foundPluginDescription;
juce::KnownPluginList pluginList;
juce::OwnedArray<juce::PluginDescription> typesFound;
juce::AudioPluginFormat* vst2Format = pluginFormatManager.getFormat(0);
juce::AudioPluginFormat* vst3Format = pluginFormatManager.getFormat(1);
juce::String vst2PluginPath = "D:/Program Files/VSTPlugins/SoundToys/Crystallizer.dll";
juce::String vst3PluginPath = "C:/Program Files/Common Files/VST3/kiloHearts/kHs Bitcrush.vst3";
pluginList.scanAndAddFile(vst2PluginPath, false, typesFound, *vst2Format);
juce::Logger::writeToLog("Found " + juce::String(typesFound.size()) + " plugins in " + vst2PluginPath);
foundPluginDescription = *typesFound[0];
// read audio file
juce::String inputFilePath("F:/Projects/python/VSTRender/resources/mono.wav");
juce::File inputFile(inputFilePath);
std::unique_ptr<juce::AudioFormatReader> reader(formatManager.createReaderFor(inputFile));
if (reader.get() == nullptr)
{
    juce::Logger::writeToLog("Failed to open input file: " + inputFilePath);
    return;
}
// create buffer
juce::AudioBuffer<float> buffer(reader->numChannels, static_cast<int>(reader->lengthInSamples));
reader->read(&buffer, 0, static_cast<int>(reader->lengthInSamples), 0, true, true);

// load a vst2 or vst3 plugin
std::unique_ptr<juce::AudioPluginInstance> pluginInstance = 
    vst2Format->createInstanceFromDescription(foundPluginDescription, reader->sampleRate, 
        512);
/*std::unique_ptr<juce::AudioPluginInstance> pluginInstance =
    vst3Format->createInstanceFromDescription(foundPluginDescription, reader->sampleRate,
        512);*/
juce::Logger::writeToLog("Plugin instance created " + juce::String(pluginInstance->getName()));

// set plugin channel layout
if (pluginInstance == nullptr)
{
    juce::Logger::writeToLog("Failed to load plugin: " + juce::String(pluginInstance->getName()));
}
if (reader->numChannels == 1)
{
    pluginInstance->setChannelLayoutOfBus(false, 0, juce::AudioChannelSet::mono());
}
else if (reader->numChannels == 2)
{
	pluginInstance->setChannelLayoutOfBus(false, 0, juce::AudioChannelSet::stereo());
}
else
{
	juce::Logger::writeToLog("Unsupported number of channels: " + juce::String(reader->numChannels));
	return;
}
pluginInstance->setNonRealtime(true);
pluginInstance->prepareToPlay(reader->sampleRate, 512);
// process audio
pluginInstance->processBlock(buffer, juce::MidiBuffer());
// write output file
juce::String outputFilePath("F:/Projects/python/VSTRender/resources/output.wav");
juce::File outputFile(outputFilePath);
if (outputFile.exists())
{
    outputFile.deleteFile();
}
outputFile.create();
std::unique_ptr<juce::FileOutputStream> outputStream(outputFile.createOutputStream());
if (outputStream.get() == nullptr)
{
    juce::Logger::writeToLog("Failed to open output file: " + outputFilePath);
    return;
}
std::unique_ptr<juce::AudioFormatWriter> writer(formatManager.findFormatForFileExtension(inputFile.getFileExtension())
    ->createWriterFor(outputStream.get(), reader->sampleRate, buffer.getNumChannels(), reader->bitsPerSample, {}, 0));
outputStream.release();
writer->writeFromAudioSampleBuffer(buffer, 0, buffer.getNumSamples());
pluginInstance->releaseResources();
juce::Logger::writeToLog("Finished processing audio file: " + inputFilePath);

The code is a bit hard to read, but two issues I see right away:

  • You only set channel layouts on the output bus, but not on the input. So there may be some mismatch. You should set the same channel layout on both (I guess that’s what you expect anyway).
  • You initialize the plugin to a max buffer size of 512 samples, but give it the whole buffer to process. You should read and process (and also write) the file in chunks of (up to) 512 samples instead.

Thanks man,you’re right,problem solved.
For vst3,pass the whole buffer into process seems fine,but for vst2,need to split into smaller buffers based on buffer size before process.
The input channel bus layout doesn’t matter in this case.

Cool, I’m glad it works now! However, spend a minute thinking about if “seems fine” is the standard you’re aiming for.

You are feeding the plugins input, so the input channel layout does matter, even if it accidentally works now. So it’s better to be explicit.

The same goes for the buffer size. With prepareToPlay() you tell the plugin the maximum buffer size it can expect. If you give it a larger one, you are violating that expectation, and while the plugin you tested with seems do deal with it just fine, others may not and simply crash.

You want your software to work by design, not by accident!

Yes,you’re right.I must be more careful and write code properly to avoid exceptions.
Thanks.