Registriert seit: 19. Feb 2012
Ort: Tschechische Republik
1 Beiträge
|
AW: TMIDIPlayer2 SysEx
30. Mai 2015, 18:48
Hallo, sorry für mein Deutsch übersetzt mit Google Trans.
Ich hatte auch Probleme mit den SysEx und ich schaffte es, durch Änderung der Code TMidiPlayer2.pas beheben. Ich bin kein professioneller Programmierer, aber jetzt SysEx-Funktion.
Ich lege Bearbeitungsverfahren TMidiDriver.DoOnMidiTimer.
Ich habe Änderungen in Version 0.9.5.1 durchgeführt. Sicher wird es auch in den folgenden Versionen.
Änderungen werden durch (****** JV *****) hervorgehoben.
Einen schönen Tag noch.
wolfmusic
Modifizierten Code:
Delphi-Quellcode:
procedure TMidiDriver.DoOnMidiTimer;
var
(****************************JV ******************************************)
i, n: Integer;
(****************************JV ******************************************)
TickTime: LongWord;
DeltaTime: LongWord;
AMidiTrack: TMidiTrack;
pEvent: pMidiEvent;
EventCode: byte;
ChannelNo: byte;
ActiveNoteRemains: boolean;
OutNote: byte;
EventPositon: LongWord;
(****************************JV ******************************************)
SysExJv: array of Byte; (*Word*)
(****************************JV ******************************************)
begin
if not Assigned(MidiFile) then Exit;
TickTime := GetTickCount;
if LastOutputTime = 0 then
begin
DeltaTime := TickTime - FStartTime;
FCurrentTime := round(DeltaTime * FSpeed);
end else
begin
DeltaTime := TickTime - LastOutputTime;
FCurrentTime := FCurrentTime + round(DeltaTime * FSpeed);
end;
LastOutputTime := TickTime;
FCurrentPos := MidiFile.Time2TickPos(FCurrentTime);
// I have found a MIDI file which does not have the end of track mark.
// Following sentences are for the case to stop playing forcibly.
if FCurrentTime > (MidiFile.Duration + 300) then
begin
Suspend := true; // to prohibit calling DoOnMidiTimer in PlayThread
if FStepMode then
SendMessage(FPlayerHandle, WM_MIDI_EndOfTrack, 0, 1)
else
PostMessage(FPlayerHandle, WM_MIDI_EndOfTrack, 0, 1);
exit;
end;
for i := 0 to MidiFile.TrackCount - 1 do
begin
AMidiTrack := MidiFile.GetTrack(i);
if not AMidiTrack.EndOfTrack then
with AMidiTrack do
begin
while (AMidiTrack.PlayPos < AMidiTrack.EventCount) do
begin
pEvent := GetEvent(PlayPos);
EventPositon := pEvent^.Positon;
if (Round(FCurrentPos) <= EventPositon) then
break;
if PEvent.Event = $FF then
ProcessEvent(i, pEvent)
else if AMidiTrack.Active then
begin
EventCode := pEvent^.Event and $F0;
ChannelNo := pEvent^.Event and $0F;
if pEvent^.Msg = '' then // Not a System Exclusive Message ?
begin
ActiveNoteRemains := IsActiveNote(ChannelNo);
// The note number for drum channel defines the different percussion instruments,
// So, we should not change that.
if ChannelNo = DrumChannel then // Drum channel ?
OutNote := pEvent^.Data1
// Output the adjusted note number for the Note On, Note Off and Note Aftertouch Events
// by FPitch value.
else if (EventCode = $80) or (EventCode = $90) or (EventCode = $A0) then
begin
OutNote := pEvent^.Data1 + FPitch;
if (EventCode = $80) or ((EventCode = $90) and (pEvent^.Data2 = 0)) then
begin
if FChannelState[ChannelNo] then
DeleteConvRecord(pEvent^.Event and $0F, pEvent^.Data1, OutNote)
end else if FChannelState[ChannelNo] then
AddConvRecord(pEvent^.Event and $0F, pEvent^.Data1, OutNote);
end else
OutNote := pEvent^.Data1;
if FChannelState[ChannelNo] then
MidiOut.PutShort(pEvent^.Event, OutNote, pEvent^.Data2)
else begin
if ActiveNoteRemains then
begin
// $B0 + ChannelNo : Control change, 123 : All Notes Off
MidiOut.PutShort($B0 + ChannelNo, 123, pEvent^.Data2);
ClearChannelRecord(ChannelNo);
end;
// Activate following 2 lines if we want to process Control change messages and
// Program change messages regardless of channel's On/Off state.
if (EventCode = $B0) or (EventCode = $C0) then
MidiOut.PutShort(pEvent^.Event, pEvent^.Data1, pEvent^.Data2);
end;
end else if (not NoExclusiveMsg) then
// if FChannelState[ChannelNo] then
(********************************************JV ******************************************)
// original MidiOut.PutLong(pAnsiChar(pEvent^.Msg), Length(pEvent^.Msg));
if (EventCode = $F0) and (pEvent^.Msg <> '') then
{if pEvent^.Msg <> '' then}
begin
SetLength(SysExJv, 0);
SetLength(SysExJv, Length(pEvent^.Msg) + 1);
SysExJv[0]:= $F0;
for n:= 0 to Length(pEvent^.Msg) - 1 do
begin
SysExJv[N + 1]:= Byte(pEvent^.Msg[N + 1]);
end;
MidiOut.PutLong(@SysExJv[0], Length(SysExJv));
end;
(********************************************JV ******************************************)
// if FChannelState[ChannelNo] then
if FChannelState[ChannelNo] or (pEvent^.Msg <> '') or (EventCode = $B0)
or (EventCode = $C0) then
if FStepMode then
SendMessage(FPlayerHandle, WM_MIDI_Event, i, integer(pEvent))
else
PostMessage(FPlayerHandle, WM_MIDI_Event, i, integer(pEvent));
end;
// Messages for meta event are posted in the procedure ProcessEvent.
{ if FStepMode then
SendMessage(FPlayerHandle, WM_MIDI_Event, i, integer(pEvent))
else
PostMessage(FPlayerHandle, WM_MIDI_Event, i, integer(pEvent)); }
PlayPos := PlayPos + 1;
end;
end;
end;
if FStepMode then
SendMessage(FPlayerHandle, WM_MIDI_PosUpdate, FCurrentTime, FCurrentPos)
else
PostMessage(FPlayerHandle, WM_MIDI_PosUpdate, FCurrentTime, FCurrentPos);
end;
Geändert von wolfmusic (31. Mai 2015 um 10:54 Uhr)
|