3

VSTホストとして機能するDelphiプログラムでVSTプラグインを使用したい。tobybearの例を試し、delphiasiovst stufを使用して、その一部を機能させましたが、プラグインにMIDIメッセージを送信する方法がわかりません(ほとんどのプラグインがMIDIを処理しないことはわかっていますが、プラグインの例があります)。

具体的には、MIDIメッセージを送信するときは、VSTプラグインでいずれかの方法を使用するか、MIDI出力を再ルーティングする必要があると思います。方法がわかりません。

誰かがこれを行う方法に関するドキュメントやコードを教えてもらえますか?前もって感謝します。

アーノルド


私は2つのテストプラグインを使用しています。1つはDelphiAsioVstパッケージからコンパイルされたもので、もう1つは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 //

そのため、プラグインでイベントを取得しません。何が間違っているのでしょうか?

4

3 に答える 3

4

ミニホストコアの例(Delphi ASIOプロジェクト、v1.4)を実際に確認する必要があります。

MIDIイベントの使用があります。基本的に

  1. TVstEvents変数があります(たとえば、MyMidiEvents:TvstEvents)。
  2. ランタイム全体で、この変数にメモリを割り当てます(例のアプリコンストラクターで)
  3. MIDIコールバックにイベントがある場合は、それをTVstEventsスタックにコピーします。
  4. TVstHostでプロセスを呼び出す前に、MyVstHost.ProcessEvents(@MyMidiEvents)を呼び出します。

これは、前の各ステップの例(ミニホストコア)で行われる方法です。

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; 

使用した方法を分析できなかった場合、これは大いに役立つはずです。

于 2011-09-18T11:27:20.333 に答える
2

VST 2.xプラグインをホストしている場合は、AudioEffectX.ProcessEvents()を使用してMIDIイベントをプラグインに送信できます。

VSTドキュメントから。

  • イベントは常に現在のオーディオブロックに関連しています。

  • プロセスサイクルごとに、processEvents()がprocessReplacing()呼び出しの前に1回呼び出されます(新しいイベントが使用可能な場合)。

コード例はわかりません。DelphiAsioVSTに何かがある可能性があります。

于 2011-09-18T01:09:11.507 に答える
1

プログラミング言語を変更したい場合は、C#とVB.NETでプラグインとホストを記述できるVST.NETを試すことができます。

それが役に立てば幸い。

于 2011-09-18T08:32:34.523 に答える