Creating VST Host - Output sound from plugin is missing half it's effect

Topics: Audio, Getting Started, Host Development, Host Processing, Newbie
Apr 23, 2011 at 3:40 PM

Hello,

I've started writing a program which will host VST Plugins, currently I'm testing using the Ambience VST Plugin http://www.smartelectronix.com/~magnus/

The program is using ASIO for audio input and output and I have managed to successfully run the audio through the VST plugin using VST.NET and all seems to sort of work, however while I can hear what I'm playing fine, most of the effect created by Ambience has gone, it's as if I'm mainly hearing the dry audio output and none of the wet output. If I load the same preset/program under Samplitude then all is fine.

Does anyone know what might be causing this problem?

Thanks,

Grant

 

Here is the main processing code:

   class VSTComponent
   {

        public VstPluginContext PluginContext { get; private set; }

        public Connection InputChannel { get; set; }
        public Connection OutputChannel { get; set; }

        int inputCount, outputCount, blockSize;
        VstAudioBufferManager inputMgr, outputMgr;
        VstAudioBuffer[] inputBuffers;
        VstAudioBuffer[] outputBuffers;

        bool initialised = false;

        public VSTComponent(VstPluginContext pluginContext)
        {
            this.PluginContext = pluginContext;

            this.inputCount = PluginContext.PluginInfo.AudioInputCount;
            this.outputCount = PluginContext.PluginInfo.AudioOutputCount;
        }

        public void Initialise()
        {
            this.blockSize = InputChannel.BufferSize;

            this.inputMgr = new VstAudioBufferManager(inputCount, blockSize);
            this.outputMgr = new VstAudioBufferManager(outputCount, blockSize);

            this.inputBuffers = inputMgr.ToArray();
            this.outputBuffers = outputMgr.ToArray();

            PluginContext.PluginCommandStub.SetBlockSize(blockSize);
            PluginContext.PluginCommandStub.SetSampleRate(44.100f);

        }

        public void ProcessAudioCycle()
        {
            int channel = 0;
            foreach (VstAudioBuffer buffer in this.inputMgr.ToArray())
            {
                for (int i = 0; i < blockSize; i++)
                {
                    buffer[i] = InputChannel.inputBuffer[channel, i];
                }
                channel++;
            }

            if (initialised == false)
            {
                PluginContext.PluginCommandStub.MainsChanged(true);
                initialised = true;
            }

            PluginContext.PluginCommandStub.ProcessReplacing(inputBuffers, outputBuffers);

            for (int i = 0; i < outputBuffers.Length; i++)
            {
                for (int j = 0; j < blockSize; j++)
                {
                    OutputChannel.inputBuffer[i, j] = outputBuffers[i][j];
                }
            }
        }

}

Coordinator
Apr 23, 2011 at 5:51 PM

Your code looks fine (for a test).  Things that come to mind:

- Does the ASIO buffer format is the same as VST uses? My guess is they are (both coming from Steinberg), but I'm not sure. Make sure you have that right.

- What VST version does the plugin support? Perhaps it expects other calls (named deprecated in VST.NET) to be made that you don't call.

- Does it support processReplacing (our normal Audio Processor Process call) or processAccumilating (See Deprecated in Core)? Ties in with previous point.

- How do other plugins do with your host? Do all suffer from this or can it be narrowed down to a few specific plugins. For instance, try the delay sample plugin.

- You could try to turn on tracing (see Host sample). That way you can track all the calls you make to the plugin and all the calls the plugin makes to your host. Perhaps you respond differently to one of the calls the plugin performs on your host? You could use the WrapperPlugin sample to trace any (3rd party) plugin in any host. Just enter the path to the wrapped plugin in the config.

Hope it helps.
Marc

Apr 26, 2011 at 9:12 AM

Hi Marc,

Thanks for the reply, you've certainly raised a few things I will have to look into, although sadly I won't have time to do so today, hopefully tomorrow though. The buffer format does seem to be the same between VST.NET and ASIO.NET (which I'm using for ASIO output), both are using floating point between -1 and 1. From a comment the ASIO.NET developer wrote I think that he's exposing float in the buffers for developers to use but then is converting it to 32bit int for the native ASIO drivers.

I will check the various points you've mentioned as well as checking some other VST plugins as well.

Thank you,

Grant

Apr 29, 2011 at 12:34 AM

Hi Marc,

I've had a chance to do some more testing, although sadly I've not managed to make much progress. The Ambience plugin states that it uses VST 2.3 according to the VST.NET Host sample, and the sample delay plugin is reporting 2.4. I've tried the delay sample and that is having issues too - you don't end up hearing a delay, but from looking at the code I really can't see any anything that would indicate I'm accedently bypassing the plugin, and given that the ambience plugin does change the audio to some extent I'm guessing the audio is actually being partially processed by the plugin and not completely bypassing it.

I've looked into turning on tracing, I've build my host and also the VST.NET host with "Define TRACE constant" turned on, but on the basis that I've not had reason in the past to use tracing in .NET despite doing a lot of development using it, I haven't managed to actually find out how it works, or if I need to add more code to make use of it. Any tips on how to actually see what is being called and when would be great. The Visual Studio debugger doesn't report anything in the output apart from telling you which modules have been loaded. I fully admit I'm probably missing the obvious here. I've got the wrapper plugin working, but once again I have no idea how to actually see the trace, it will be very useful to see what another host is calling in comparison to my one.

Thanks,

Grant

Apr 29, 2011 at 3:24 PM

Hi Marc,

I've done some more investigating with turning on tracing and realised that the sample host's app.config file actually has settings in there to turn it on, so that's good. However the one things I've not managed to do is get any tracing output from the wrapper plugin, I've added my own Trace.WriteLine calls to some of the methods and that certainly seems to output text to when running through the sample host, but not when running through another native host when I attach Visual Studio's debugger to the host. Any ideas? or is is just better for me to modify the wrapper plugin so that it will just output text to a text file?

Thanks,

Grant

Coordinator
Apr 29, 2011 at 5:49 PM

Hi Grant,

You should be able to also let the wrapper plugin trace. You have to set the config file name to the host's exe name and append ,config (like Cubase.exe.config) and place it next to the host's exe file. Tracing settings work using the standard System.Diagnostics (as you could see in the host sample app.config file) which are read from the global config file. Note this is NOT the same config file the wrapper plugin uses to load the wrapped plugin - so there are two .config files.

To trace any plugin copy the 4 lines of config (2 x sources and 2 x switches) that contain the [PluginName] replacement token and replace that token with the name of the plugin dll (without the .dll extension). Set the switches for tracing the specific plugin to 'All'. That should do it.

If I remember correctly you can use DebugView (by SysInternals/Microsoft) to view the trace output without attaching to the process.

If you want to you can email me (obiwanjacobi at hotmail dot com) your code and I will try to look at it to reproduce the problem.

Hope it helps,
Marc