Einzelnen Beitrag anzeigen

wolfmusic

Registriert seit: 19. Feb 2012
Ort: Tschechische Republik
1 Beiträge
 
#82

AW: TMIDIPlayer2 SysEx

  Alt 30. Mai 2015, 17: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;
Angehängte Dateien
Dateityp: txt TMidiDriver.DoOnMidiTimer.txt (5,8 KB, 14x aufgerufen)

Geändert von wolfmusic (31. Mai 2015 um 09:54 Uhr)
  Mit Zitat antworten Zitat