Audio Plugin VST host

alienoiz

New member
Joined
Oct 22, 2025
Messages
1
Programming Experience
Beginner
Hi everyone..im new here and a bit lame with coding...anyway ...ive been trying to create a minimal VSThost with C# and VST.NET pack....
The code returns no errors but i cannot produce sound...just UI...any idea? Thanks (PS: im posting the full code cause im not sure what is buggins....

C#:
Expand Collapse Copy
using Jacobi.Vst.Core;
using Jacobi.Vst.Core.Host;
using Jacobi.Vst.Host.Interop;
using Microsoft.VisualBasic;
using NAudio.Midi;
using NAudio.Wave;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Windows.Forms;

namespace Jacobi.Vst.Samples.Host;


partial class MainForm : Form
{
    private List<VstPluginContext> _plugins = new List<VstPluginContext>();

    public MainForm()
    {
        InitializeComponent();
        Text = "VST HOST";
    }

    private VstPluginContext OpenPlugin(string pluginPath)
    {
        try
        {


            var hostCmdStub = new DummyHostCommandStub();
            hostCmdStub.PluginCalled += new EventHandler<PluginCalledEventArgs>(HostCmdStub_PluginCalled);


            var ctx = VstPluginContext.Create(pluginPath, hostCmdStub);


            // actually open the plugin itself
            ctx.PluginCommandStub.Commands.Open();


            var plugin = ctx.PluginCommandStub;
            var commands = plugin.Commands;

            if (commands.EditorGetRect(out var rect))
            {
                int width = rect.Right - rect.Left;
                int height = rect.Bottom - rect.Top;

                using (Form editorForm = new Form())
                {
                    editorForm.Text = commands.GetEffectName();
                    editorForm.ClientSize = new System.Drawing.Size(width, height);
                    editorForm.StartPosition = FormStartPosition.CenterParent;

                    commands.EditorOpen(editorForm.Handle);

                    // Keep GUI updating
                    var timer = new Timer { Interval = 30 };
                    timer.Tick += (s, ev) => commands.EditorIdle();
                    timer.Start();

                    editorForm.ShowDialog(this);

                    commands.EditorClose();
                }
            }
            else
            {
                MessageBox.Show("This plugin does not provide a GUI.");
            }

            return ctx;
        }
        catch (Exception e)
        {
            MessageBox.Show(this, e.ToString(), Text, MessageBoxButtons.OK, MessageBoxIcon.Error);
        }

        return null;

    }

    private void ReleaseAllPlugins()
    {

        _plugins.Clear();
    }


    public object PluginContext { get; private set; }

    private void HostCmdStub_PluginCalled(object sender, PluginCalledEventArgs e)
    {
        var hostCmdStub = (DummyHostCommandStub)sender;

        // can be null when called from inside the plugin main entry point.
        if (hostCmdStub.PluginContext.PluginInfo != null)
        {
            Debug.WriteLine("Plugin " + hostCmdStub.PluginContext.PluginInfo.PluginID + " called:" + e.Message);
        }
        else
        {
            Debug.WriteLine("The loading Plugin called:" + e.Message);
        }
    }


    private IWavePlayer _waveOut;
    private VstAudioProcessor _vstProcessor;

    private void MainForm_FormClosed(object sender, FormClosedEventArgs e)
    {
        ReleaseAllPlugins();
    }

    public class HostCommandStub : IVstHostCommandStub
    {
        IVstPluginContext IVstHostCommandStub.PluginContext { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }

        IVstHostCommands20 IVstHostCommandStub.Commands => throw new NotImplementedException();

        public int GetSampleRate() => 44100;
        public int GetBlockSize() => 512;
        public VstTimeInfo GetTimeInfo(VstTimeInfoFlags filterFlags) => new VstTimeInfo { SampleRate = 44100 };
        public void ProcessIdle() { }
        public void UpdateDisplay() { }
        public void SetParameterAutomated(int index, float value) { }
        public int GetCurrentPluginID() => 1234;
        public int GetVersion() => 1000;
        public bool SizeWindow(int width, int height) => true;
    }



    // Compatible with both VST.NET 1.x and 2.x
    private static VstAudioBuffer[] GetBuffersCompat(VstAudioBufferManager mgr)
    {
        var type = mgr.GetType();
        var prop = type.GetProperty("Buffers");
        if (prop != null)
        {
            var value = prop.GetValue(mgr);
            if (value is System.Collections.IEnumerable enumerable)
                return enumerable.Cast<VstAudioBuffer>().ToArray();
        }

        var method = type.GetMethod("GetBuffers");
        if (method != null)
        {
            var result = method.Invoke(mgr, null);
            if (result is System.Collections.IEnumerable enumerable)
                return enumerable.Cast<VstAudioBuffer>().ToArray();
        }

        // fallback for older API
        var countProp = type.GetProperty("BufferCount");
        int count = (int)(countProp?.GetValue(mgr) ?? 0);
        return Enumerable.Range(0, count)
                         .Select(i => (VstAudioBuffer)type.GetMethod("get_Item")?.Invoke(mgr, new object[] { i }))
                         .ToArray();
    }

    public class VstAudioProcessor : ISampleProvider
    {
        private readonly VstPluginContext _plugin;
        private readonly WaveFormat _waveFormat;
        private readonly int _blockSize = 512;
        private readonly VstAudioBufferManager _inputMgr;
        private readonly VstAudioBufferManager _outputMgr;
        private readonly VstAudioBuffer[] _inputs;
        private readonly VstAudioBuffer[] _outputs;
        private double _phase;

        public WaveFormat WaveFormat => _waveFormat;

        public VstAudioProcessor(VstPluginContext plugin)
        {
            _plugin = plugin;
            _waveFormat = WaveFormat.CreateIeeeFloatWaveFormat(44100, 2);

            _inputMgr = new VstAudioBufferManager(2, _blockSize);
            _outputMgr = new VstAudioBufferManager(2, _blockSize);

            _inputs = _inputMgr.Buffers.ToArray();
            _outputs = _outputMgr.Buffers.ToArray();

            var cmds = _plugin.PluginCommandStub.Commands;
            cmds.SetSampleRate(44100);
            cmds.SetBlockSize(_blockSize);
            cmds.MainsChanged(true);
        }

        public int Read(float[] buffer, int offset, int count)
        {
            int frames = Math.Min(count / 2, _blockSize);
            double freq = 440.0;
            double phaseStep = 2.0 * Math.PI * freq / WaveFormat.SampleRate;

            for (int i = 0; i < frames; i++)
            {
                float sample = (float)Math.Sin(_phase);
                _phase += phaseStep;
                if (_phase > 2 * Math.PI) _phase -= 2 * Math.PI;

                _inputs[0][i] = sample;
                _inputs[1][i] = sample;
            }

            _plugin.PluginCommandStub.Commands.ProcessReplacing(_inputs, _outputs);

            int index = offset;
            for (int i = 0; i < frames; i++)
            {
                buffer[index++] = _outputs[0][i];
                buffer[index++] = _outputs[1][i];
            }

            return frames * 2;
        }
    }





    private VstPluginContext _plugin;



    private void ViewPluginBtn_Click(object sender, EventArgs e)
    {
        var path = "C:\\ATMOS\\ATMOS.dll";
        InitAudio(path);
        OpenPlugin(path);
    }

    private void InitAudio(string pluginPath)
    {
        // 1?? Create VST host
        var hostStub = new DummyHostCommandStub();
        _plugin = VstPluginContext.Create(pluginPath, hostStub);

        // 2?? Open the plugin
        _plugin.PluginCommandStub.Commands.Open();
        _plugin.PluginCommandStub.Commands.MainsChanged(true);

        // 3?? Create the audio processor (this handles plugin processing)
        _vstProcessor = new VstAudioProcessor(_plugin);

        // 4?? Initialize the audio output (WaveOut)
        _waveOut = new WaveOutEvent();
        _waveOut.Init(_vstProcessor);

        // 5?? Start playback
        _waveOut.Play();

        MessageBox.Show("Audio engine initialized and started!");
    }
}
 
Back
Top Bottom