0

I have the following code working great with VST Effects, passing a sinewave in and receiving a result without any glitches. However, I need to pass in a custom created MIDI Event (using either VST.NET or NAudio MIDI Helpers), and am having no luck. Is it because the absolute and deltaframes are zero? I don't know where else to turn, and have been banging my head against the keyboard for a while now.

In monitoring the debug window, I can see that the VST Events are being picked up by the plugin. I also went ahead and created a custom plugin to make sure that I was receiving the Event info, and it is being passed through properly. I just don't get any audio output!

In the code example, all you will have to do to make this work is: A. place a VSTi dll (which has two Audio Output channels, and accepts VST MIDI Input) in the bin\debug folder when you debug this B. change the name of the VSTi dll from cobalt.dll to whatever the name is of the VST you are using to test.

It is a Windows Universal XML Page with one button, btnTest

Imports NAudio.Wave
Imports NAudio.Midi
Imports Jacobi.Vst.Core
Imports Jacobi.Vst.Interop.Host

Class MidiTestPage
Private waveOut As WaveOut
Private ctx As VstPluginContext

Private Sub btnTest_Click(sender As Object, e As EventArgs) Handles btnTest.Click
    Dim pluginPath As String = System.AppDomain.CurrentDomain.BaseDirectory & "VSTPlugins\" & "cobalt.dll"
    ctx = InitPlugin(pluginPath, 1)
    Dim midiWaveProvider As New MidiSampleProvider(ctx)
    If waveOut Is Nothing Then
        waveOut = New WaveOut(WaveCallbackInfo.FunctionCallback())
        waveOut.Init(midiWaveProvider)
        waveOut.Volume = 1.0
        waveOut.Play()
    End If
End Sub

Private Sub HostCmdStub_PluginCalled(sender As Object, e As PluginCalledEventArgs)
    Dim hostCmdStub As HostCommandStub = DirectCast(sender, HostCommandStub)
    Try
        ' can be null when called from inside the plugin main entry point.
        If hostCmdStub.PluginContext.PluginInfo IsNot Nothing Then
            Debug.WriteLine("Plugin " & hostCmdStub.PluginContext.PluginInfo.PluginID & " called:" & e.Message)
        Else
            Debug.WriteLine("The loading Plugin called:" & e.Message)
        End If
    Catch ex As Exception
        Debug.WriteLine("The loading Plugin called:" & e.Message)
    End Try

End Sub

Private Function InitPlugin(pluginPath As String, programIndex As Integer) As VstPluginContext
    Dim hostCmdStub As New HostCommandStub()
    AddHandler hostCmdStub.PluginCalled, AddressOf HostCmdStub_PluginCalled
    Dim ctx As VstPluginContext = VstPluginContext.Create(pluginPath, hostCmdStub)
    'plugins.Add(ctx)
    ' add custom data to the context
    ctx.Set(Of String)("PluginPath", pluginPath)
    ctx.Set(Of HostCommandStub)("HostCmdStub", hostCmdStub)
    '' actually open the plugin itself
    ctx.PluginCommandStub.Open()
    ctx.PluginCommandStub.MainsChanged(True)
    ctx.PluginCommandStub.BeginSetProgram()
    ctx.PluginCommandStub.SetProgram(programIndex)
    ctx.PluginCommandStub.EndSetProgram()
    ctx.PluginCommandStub.StartProcess()
    Return ctx
End Function
End Class

Public Class MidiSampleProvider
Implements ISampleProvider
Private pluginContext As VstPluginContext

Public Shadows ReadOnly Property WaveFormat As WaveFormat Implements ISampleProvider.WaveFormat
    Get
        Return WaveFormat.CreateIeeeFloatWaveFormat(44100, 2)
    End Get
End Property
Private BlockSize As Integer = 0
Private inputBuffers As VstAudioBuffer()
Private outputBuffers As VstAudioBuffer()
Dim vEvents As List(Of VstEvent)

Public Sub New(ctx As VstPluginContext)
    pluginContext = ctx
    vEvents = New List(Of VstEvent)
    CreateMidiEvent(pluginContext)
End Sub


Private Sub UpdateBlockSize(blockSize__1 As Integer)
    BlockSize = blockSize__1

    Dim inputCount As Integer = pluginContext.PluginInfo.AudioInputCount
    Dim outputCount As Integer = pluginContext.PluginInfo.AudioOutputCount

    Dim inputMgr = New VstAudioBufferManager(inputCount, blockSize__1)
    Dim outputMgr = New VstAudioBufferManager(outputCount, blockSize__1)

    pluginContext.PluginCommandStub.SetBlockSize(blockSize__1)
    pluginContext.PluginCommandStub.SetSampleRate(WaveFormat.SampleRate)
    pluginContext.PluginCommandStub.SetProcessPrecision(VstProcessPrecision.Process32)

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

End Sub

Public Function Read(buffer() As Single, offset As Integer, count As Integer) As Integer Implements ISampleProvider.Read
    Dim samplesRequired As Double = count / 2
    If samplesRequired <> BlockSize Then
        UpdateBlockSize(samplesRequired)
    End If
    Dim samplesRead As Double = 0
    If vEvents.Count > 0 Then
        pluginContext.PluginCommandStub.ProcessEvents(vEvents.ToArray)
        pluginContext.HostCommandStub.ProcessEvents(vEvents.ToArray)
        pluginContext.PluginCommandStub.ProcessReplacing(inputBuffers, outputBuffers)
        'vEvents.Clear()
    End If
    For j As Integer = 0 To BlockSize - 1
        buffer(samplesRead + offset) = outputBuffers(0)(j)
        samplesRead += 2
    Next
    Return samplesRead
End Function

Public Sub CreateMidiEvent(ctx As VstPluginContext)
    Dim noteOffset As Integer = 0
    Dim detune As Short = 0
    Dim Velocity As Integer = 127

    'Dim noteOn As New NAudio.Midi.NoteEvent(AbsoluteTime, note.MidiChannel, NAudio.Midi.MidiCommandCode.NoteOn, note.Note.BaseNote, Velocity)
    Dim noteOnStream As New System.IO.MemoryStream()
    Dim noteOnData As New System.IO.BinaryWriter(noteOnStream)
    'noteOn.Export(AbsoluteTime, noteOnData)
    noteOnData.Write(MidiMessage.StartNote(60, Velocity, 1).RawData)
    Dim noteOnEvent As New VstMidiEvent(0, 400, 0, noteOnStream.ToArray, detune, Velocity, True)
    vEvents.Add(noteOnEvent)

End Sub

End Class
  • I see a couple of problems with your code, but first make sure you actually construct a valid NoteOn midi event. I am not sure what the result is of the method you use because of endianness of the stream and ToArray method. Simply allocate an array yourself and put in the midi bytes at the correct positions in the array. Lookup what Midi bytes make up a NoteOn message on channel 1 for a given note with maximum velocity. – obiwanjacobi Jul 12 '17 at 08:21
  • This looks like the MIDI VST Plugin is receiving the proper information, based on my research of the MIDI Spec, I am sending a note on to channel 3 (value is 2) note 3, velocity 127... From my debugger, Midi VST Plugin Receiving Midi Event on Channel3: 91-02-7F-00 which narrows it down. – Sunsing Jul 16 '17 at 22:12

0 Answers0