Delphi如何将MIDI信号精确无误地传输至托管VST插件实现实时音频处理?

2026-04-10 20:562阅读0评论SEO资源
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计845个文字,预计阅读时间需要4分钟。

Delphi如何将MIDI信号精确无误地传输至托管VST插件实现实时音频处理?

我想在我的Delphi程序中使用VST插件,程序应直接充当VST主机。我已经尝试过tobybear示例,使用了DelphiASIOVST+STUF,得到了一些令人满意的工作效果,但问题是……我不知道如何将MIDI消息发送到插件。我知道大多数插件都支持MIDI,但我不知道如何操作。

我想在我的Delphi程序中使用VST插件,该程序充当VST主机.我已经尝试过tobybear示例,使用了delphiasiovst stuf,得到了一些甚至工作,但是…我不知道如何将MIDI消息发送到插件(我知道大多数插件都不会处理MIDI,但我有一个示例插件().

更具体一点:我希望当我发送MIDI信息时,我必须在VST插件中使用一种或其他方法或重新路由MIDI输出.我只是不知道如何.

任何人都可以指向我如何做到的文档或代码?提前致谢.

阿诺德

我使用两个测试插件:从DelphiAsioVst包和PolyIblit编译的插件.两者都在Finale和LMMS中工作.加载到我的测试程序中都会显示他们的VST编辑器.

我插入了TvstEvent记录并初始化它,我插入了MIDIData和AddMIDIData过程以及一个定时器来提供测试数据并执行插件的ProcessEvents例程. ProcessEvents获取正确的测试数据,但没有听到声音.当我将它直接发送到midi输出端口时,我听到了什么.

在下面的代码中,PropcessEvents应该足够了,附加代码是测试MIDI信息是否正确发送的测试. VstHost [0]是第一个插件,可以是PolyIblit或VSTPlugin,具体取决于测试.

procedure TMain_VST_Demo.TimerTimer (Sender: TObject); var i: Int32; begin // MIDIOutput.PutShort ($90, 60, 127); MIDIData (0, $90, 60, 127); if FMDataCnt > 0 then begin FMyEvents.numEvents := FMDataCnt; VSTHost[0].ProcessEvents(@FMyEvents); // if (FCurrentMIDIOut > 0) and MIMidiThru.Checked then // begin for i := 0 to FMDataCnt - 1 do MIDIOutput.PutShort (PVstMidiEvent (FMyEvents.events[i])^.midiData[0], PVstMidiEvent (FMyEvents.events[i])^.midiData[1], PVstMidiEvent (FMyEvents.events[i])^.midiData[2]); // FMidiOutput.Send(//FCurrentMIDIOut - 1, // PVstMidiEvent(FMyEvents.events[i])^.midiData[0], // PVstMidiEvent(FMyEvents.events[i])^.midiData[1], // PVstMidiEvent(FMyEvents.events[i])^.midiData[2]); // end; FMDataCnt := 0; end; end; // TimerTimer //

所以我没有在插件中获取事件.知道我错了什么?

您应该看看minihost核心示例(Delphi ASIO项目,v1.4).

有midi事件的使用.基本上

>你有一个TVstEvents变量(比方说MyMidiEvents:TvstEvents).
>对于整个运行时,您为此变量分配内存(在exmaple的app构造函数中)
>当您在MIDI回调中有一个事件时,将其复制到TVstEvents堆栈上.
>在TVstHost中调用进程之前,调用MyVstHost.ProcessEvents(@MyMidiEvents).

这是在示例(minihost核心)中完成的,对于每个先前的步骤:

Delphi如何将MIDI信号精确无误地传输至托管VST插件实现实时音频处理?

1 /在第215行,声明

FMyEvents: TVstEvents;

2 /在第376行,分配:

for i := 0 to 2047 do begin GetMem(FMyEvents.Events[i], SizeOf(TVSTMidiEvent)); FillChar(FMyEvents.Events[i]^, SizeOf(TVSTMidiEvent), 0); with PVstMidiEvent(FMyEvents.Events[i])^ do begin EventType := etMidi; ByteSize := 24; end; end;

3 /在第986行然后在第1782行,从回调中复制midi事件:

回调

procedure TFmMiniHost.MidiData(const aDeviceIndex: Integer; const aStatus, aData1, aData2: Byte); begin if aStatus = $FE then exit; // ignore active sensing if (not Player.CbOnlyChannel1.Checked) or ((aStatus and $0F) = 0) then begin if (aStatus and $F0) = $90 then NoteOn(aStatus, aData1, aData2) //ok else if (aStatus and $F0) = $80 then NoteOff(aStatus, aData1) else AddMidiData(aStatus, aData1, aData2); end; end;

事件副本

procedure TFmMiniHost.AddMIDIData(d1, d2, d3: byte; pos: Integer = 0); begin FDataSection.Acquire; try if FMDataCnt > 2046 then exit; inc(FMDataCnt); with PVstMidiEvent(FMyEvents.events[FMDataCnt - 1])^ do begin EventType := etMidi; deltaFrames := pos; midiData[0] := d1; midiData[1] := d2; midiData[2] := d3; end; finally FDataSection.Release; end; end;

4 /在第2322行,在TAsioHost.Bufferswitch中,调用TVstHost.ProcessEvents

FDataSection.Acquire; try if FMDataCnt > 0 then begin FMyEvents.numEvents := FMDataCnt; VSTHost[0].ProcessEvents(FMyEvents); if (FCurrentMIDIOut > 0) and MIMidiThru.Checked then begin for i := 0 to FMDataCnt - 1 do FMidiOutput.Send(FCurrentMIDIOut - 1, PVstMidiEvent(FMyEvents.events[i])^.midiData[0], PVstMidiEvent(FMyEvents.events[i])^.midiData[1], PVstMidiEvent(FMyEvents.events[i])^.midiData[2]); end; FMDataCnt := 0; end; finally FDataSection.Release; end;

如果您无法分析所使用的方法,这应该会对您有所帮助.

标签:VST

本文共计845个文字,预计阅读时间需要4分钟。

Delphi如何将MIDI信号精确无误地传输至托管VST插件实现实时音频处理?

我想在我的Delphi程序中使用VST插件,程序应直接充当VST主机。我已经尝试过tobybear示例,使用了DelphiASIOVST+STUF,得到了一些令人满意的工作效果,但问题是……我不知道如何将MIDI消息发送到插件。我知道大多数插件都支持MIDI,但我不知道如何操作。

我想在我的Delphi程序中使用VST插件,该程序充当VST主机.我已经尝试过tobybear示例,使用了delphiasiovst stuf,得到了一些甚至工作,但是…我不知道如何将MIDI消息发送到插件(我知道大多数插件都不会处理MIDI,但我有一个示例插件().

更具体一点:我希望当我发送MIDI信息时,我必须在VST插件中使用一种或其他方法或重新路由MIDI输出.我只是不知道如何.

任何人都可以指向我如何做到的文档或代码?提前致谢.

阿诺德

我使用两个测试插件:从DelphiAsioVst包和PolyIblit编译的插件.两者都在Finale和LMMS中工作.加载到我的测试程序中都会显示他们的VST编辑器.

我插入了TvstEvent记录并初始化它,我插入了MIDIData和AddMIDIData过程以及一个定时器来提供测试数据并执行插件的ProcessEvents例程. ProcessEvents获取正确的测试数据,但没有听到声音.当我将它直接发送到midi输出端口时,我听到了什么.

在下面的代码中,PropcessEvents应该足够了,附加代码是测试MIDI信息是否正确发送的测试. VstHost [0]是第一个插件,可以是PolyIblit或VSTPlugin,具体取决于测试.

procedure TMain_VST_Demo.TimerTimer (Sender: TObject); var i: Int32; begin // MIDIOutput.PutShort ($90, 60, 127); MIDIData (0, $90, 60, 127); if FMDataCnt > 0 then begin FMyEvents.numEvents := FMDataCnt; VSTHost[0].ProcessEvents(@FMyEvents); // if (FCurrentMIDIOut > 0) and MIMidiThru.Checked then // begin for i := 0 to FMDataCnt - 1 do MIDIOutput.PutShort (PVstMidiEvent (FMyEvents.events[i])^.midiData[0], PVstMidiEvent (FMyEvents.events[i])^.midiData[1], PVstMidiEvent (FMyEvents.events[i])^.midiData[2]); // FMidiOutput.Send(//FCurrentMIDIOut - 1, // PVstMidiEvent(FMyEvents.events[i])^.midiData[0], // PVstMidiEvent(FMyEvents.events[i])^.midiData[1], // PVstMidiEvent(FMyEvents.events[i])^.midiData[2]); // end; FMDataCnt := 0; end; end; // TimerTimer //

所以我没有在插件中获取事件.知道我错了什么?

您应该看看minihost核心示例(Delphi ASIO项目,v1.4).

有midi事件的使用.基本上

>你有一个TVstEvents变量(比方说MyMidiEvents:TvstEvents).
>对于整个运行时,您为此变量分配内存(在exmaple的app构造函数中)
>当您在MIDI回调中有一个事件时,将其复制到TVstEvents堆栈上.
>在TVstHost中调用进程之前,调用MyVstHost.ProcessEvents(@MyMidiEvents).

这是在示例(minihost核心)中完成的,对于每个先前的步骤:

Delphi如何将MIDI信号精确无误地传输至托管VST插件实现实时音频处理?

1 /在第215行,声明

FMyEvents: TVstEvents;

2 /在第376行,分配:

for i := 0 to 2047 do begin GetMem(FMyEvents.Events[i], SizeOf(TVSTMidiEvent)); FillChar(FMyEvents.Events[i]^, SizeOf(TVSTMidiEvent), 0); with PVstMidiEvent(FMyEvents.Events[i])^ do begin EventType := etMidi; ByteSize := 24; end; end;

3 /在第986行然后在第1782行,从回调中复制midi事件:

回调

procedure TFmMiniHost.MidiData(const aDeviceIndex: Integer; const aStatus, aData1, aData2: Byte); begin if aStatus = $FE then exit; // ignore active sensing if (not Player.CbOnlyChannel1.Checked) or ((aStatus and $0F) = 0) then begin if (aStatus and $F0) = $90 then NoteOn(aStatus, aData1, aData2) //ok else if (aStatus and $F0) = $80 then NoteOff(aStatus, aData1) else AddMidiData(aStatus, aData1, aData2); end; end;

事件副本

procedure TFmMiniHost.AddMIDIData(d1, d2, d3: byte; pos: Integer = 0); begin FDataSection.Acquire; try if FMDataCnt > 2046 then exit; inc(FMDataCnt); with PVstMidiEvent(FMyEvents.events[FMDataCnt - 1])^ do begin EventType := etMidi; deltaFrames := pos; midiData[0] := d1; midiData[1] := d2; midiData[2] := d3; end; finally FDataSection.Release; end; end;

4 /在第2322行,在TAsioHost.Bufferswitch中,调用TVstHost.ProcessEvents

FDataSection.Acquire; try if FMDataCnt > 0 then begin FMyEvents.numEvents := FMDataCnt; VSTHost[0].ProcessEvents(FMyEvents); if (FCurrentMIDIOut > 0) and MIMidiThru.Checked then begin for i := 0 to FMDataCnt - 1 do FMidiOutput.Send(FCurrentMIDIOut - 1, PVstMidiEvent(FMyEvents.events[i])^.midiData[0], PVstMidiEvent(FMyEvents.events[i])^.midiData[1], PVstMidiEvent(FMyEvents.events[i])^.midiData[2]); end; FMDataCnt := 0; end; finally FDataSection.Release; end;

如果您无法分析所使用的方法,这应该会对您有所帮助.

标签:VST