Вам действительно стоит взглянуть на пример ядра minihost (проект Delphi ASIO, версия 1.4).
Существует использование событий миди.В основном
- у вас есть переменная TVstEvents (скажем, MyMidiEvents: TvstEvents).
- для всей среды выполнения, которую вы выделяете память для этой переменной (в конструкторе приложения, например)
- Когда у вас есть событие в вашем обратном вызове MIDI, вы копируете его в стек TVstEvents.
- Перед вызовом процесса в 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;
, это должно вам очень помочь, если вы не смоглипроанализировать используемый метод.