使用NAudio和VST.NET进行实时MIDI事件

时间:2017-07-11 16:04:26

标签: vb.net midi naudio vst

我有以下代码与VST效果一起工作,传入正弦波并接收结果而没有任何故障。但是,我需要传递一个自定义创建的MIDI事件(使用VST.NET或NAudio MIDI助手),并且没有运气。是因为绝对帧和deltaframe是零吗?我不知道还有什么地方可以转动,并且已经把头撞到了键盘上一段时间了。

在监视调试窗口时,我可以看到插件正在拾取VST事件。我还继续创建了一个自定义插件,以确保我收到了事件信息,并且正在正确传递。我只是没有得到任何音频输出!

在代码示例中,您需要做的就是: A.调试时,在bin \ debug文件夹中放置一个VSTi dll(有两个音频输出通道,并接受VST MIDI输入) B.将来自cobalt.dll的VSTi dll的名称更改为您要测试的VST的名称。

这是一个带有一个按钮的Windows Universal XML页面,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

0 个答案:

没有答案