Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Problem mit SysEx (MIDI) (https://www.delphipraxis.net/159280-problem-mit-sysex-midi.html)

Bääääär 21. Mär 2011 18:32

Problem mit SysEx (MIDI)
 
Hallo Community!

Hab schon lange nix mehr mit Delphi gemacht, jetzt bin ich aber wieder hier gelandet und zwar mit folgendem problem: Ich möchte mit der midi-bibliothek von hier SysEx Daten verschicken. Allerdings erhalte ich bei folgendem Aufruf
Code:
if not MIDIOutput.IsOpen(MidiOutputDevices.ItemIndex) then
     begin
       showmessage('Device not opened!');
       exit;
     end;
   str := 'f0 00 00 7e 32 00 00 01 f7';
   MidiOutput.SendSysEx(MidiOutputDevices.ItemIndex, str );
einen Fehler vom Typus "MMSYSERR_INVALPARAM". Gemäß dieser Seite bedeutet das, dass der vorzubereitende MIDIheader bzw. dessen Adresse nicht korrekt ist.
Die aufgerufene Funktion tut folgendes:
Code:
procedure TMidiOutput.SendSysEx(const aDeviceIndex: integer;
  const aStream: TMemoryStream);
var
  lSysExHeader: TMidiHdr;
begin
  aStream.Position := 0;
  lSysExHeader.dwBufferLength := aStream.Size;
  lSysExheader.lpData := aStream.Memory;
  lSysExHeader.dwFlags := 0;

  MidiResult := midiOutPrepareHeader(GetHandle(aDeviceIndex), @lSysExHeader, SizeOf(TMidiHdr));
  MidiResult := midiOutLongMsg( GetHandle(aDeviceIndex), @lSysExHeader, SizeOf(TMidiHdr));
  MidiResult := midiOutUnprepareHeader(GetHandle(aDeviceIndex), @lSysExHeader, SizeOf(TMidiHdr));
end;
Ich weiß nicht genau, was ich da falsch mache, vielleicht könnt ihr mir helfen. Ich arbeite mit Lazarus, aber ich glaube, das sollte hier nicht ausschlaggebend sein.

Danke,
Bääääär

[Edit:] Noch etwas zur Klärung: Im Beispiel übergebe ich einen String an eine Funktion, die einen Stream erwartet. Es exisieren jedoch zwei Versionen dieser Funktion, wovon eine den übergebenen String umwandelt und dann die abgebildete Variante aufruft. Das hat also seine Richtigkeit

shmia 21. Mär 2011 18:39

AW: Problem mit SysEx (MIDI)
 
Fehlt da nicht noch ein
Delphi-Quellcode:
lSysExHeader.dwBytesRecorded := lSysExHeader.dwBufferLength;
?

Bääääär 21. Mär 2011 20:21

AW: Problem mit SysEx (MIDI)
 
Das habe ich bereits probiert, scheint aber nichts zu ändern...

Mir ist eben aufgefallen: MIDI-Empfang geht auch nicht. (Ausnahmefehler, sobald das Programm was empfängt). Klingt für mich ein wenig so, als sei der MIDI-Header bei Lazarus irgendwo falsch definiert.

shmia 22. Mär 2011 18:02

AW: Problem mit SysEx (MIDI)
 
Dieses 3-malige
Delphi-Quellcode:
GetHandle(aDeviceIndex)
ist natürlich auch etwas fahrlässig.
Das Handle muss eigentlich direkt als Membervariable in der Klasse gespeichert sein.
Und natürlich muss schon beim Öffnen sichergestellt werden, dass das Handle gültig ist.
Das ist jetzt nicht unbedingt die Fehlerursache, aber doch ein bisschen unsauber.

Bääääär 23. Mär 2011 08:18

AW: Problem mit SysEx (MIDI)
 
Ich muss gestehen, ich verstehe diesen Code eh nicht so recht. Er schien aber so mal funktioniert zu haben, sonst wöre er ja nicht als funktionierend veröffentlich wordern. Vielleicht hat er unter älteren Windows Versionen funktioniert (und in seiner Funktion sozusagen eine "gedultete Ungültigkeit" gehabt, die von Widnows 7 jetzt nicht mehr akzeptiert wird)

aDeviceIndex ist ja ein Integer. Was genau jetzt der Sinn ist, das Handle eines Integers zu übergeben - ... Ich glaube, genauso wurde es auch beim Öffnen des Midi-Gerätes gemacht...

Ich werde mir das nochmal anschauen, sobald ich wieder Zugriff auf den Code habe.

Bääääär

Bääääär 23. Mär 2011 08:57

AW: Problem mit SysEx (MIDI)
 
Kleines Update dazu:
GetHandle ist wie folgt definiert:

Delphi-Quellcode:
function TMidiDevices.GetHandle(const aDeviceIndex: integer): THandle;
begin
try
  if not InRange(aDeviceIndex, 0, fDevices.Count - 1) then
    raise EMidiDevices.CreateFmt('%s: Device index out of bounds! (%d)', [ClassName,aDeviceIndex]);

  Result:= THandle(fDevices.Objects[ aDeviceIndex ]);
except
  Result:= 0;
end;
end;
Wobei TMidiOutput/TMidiInput und TMidiDevices so definiert ist:
Delphi-Quellcode:
// base class for MIDI devices
  TMidiDevices = class
  private
    fDevices: TStringList;
    fMidiResult: MMResult;
    procedure SetMidiResult(const Value: MMResult);
  protected
    property MidiResult: MMResult read fMidiResult write SetMidiResult;
    function GetHandle(const aDeviceIndex: integer): THandle;
  public
    // create the MIDI devices
    constructor Create; virtual;
    // whack the devices
    destructor Destroy; override;
    // open a specific device
    procedure Open(const aDeviceIndex: integer); virtual; abstract;
    // close a specific device
    procedure Close(const aDeviceIndex: integer); virtual; abstract;
    // close all devices
    procedure CloseAll;
    // THE devices
    function IsOpen(ADeviceIndex: Integer): Boolean;                           // check if open
    property Devices: TStringList read fDevices;
  end;

  // MIDI input devices
  TMidiInput = class(TMidiDevices)
  private
    fOnMidiData: TOnMidiInData;
    fOnSysExData: TOnSysExData;
    fSysExData: TObjectList;
  protected
    procedure DoSysExData(const aDeviceIndex: integer);
  public
    // create an input device
    constructor Create; override;
    // what the input devices
    destructor Destroy; override;
    // open a specific input device
    procedure Open(const aDeviceIndex: integer); override;
    // close a specific device
    procedure Close(const aDeviceIndex: integer); override;
    // Rescan device list
    procedure Rescan;
    // midi data event
    property OnMidiData: TOnMidiInData read fOnMidiData write fOnMidiData;
    // midi system exclusive is received
    property OnSysExData: TOnSysExData read fOnSysExData write fOnSysExData;
  end;

  // MIDI output devices
  TMidiOutput = class(TMidiDevices)
    constructor Create; override;
    // open a specific input device
    procedure Open(const aDeviceIndex: integer); override;
    // close a specific device
    procedure Close(const aDeviceIndex: integer); override;
    // send some midi data to the indexed device
    procedure Send(const aDeviceINdex: integer; const aStatus, aData1, aData2: byte);
    procedure SendSystemReset( const aDeviceIndex: integer);
    procedure SendAllSoundOff(const aDeviceIndex: integer; const channel: byte);
    // Rescan device list
    procedure Rescan;
    // send system exclusive data to a device
    procedure SendSysEx(const aDeviceIndex: integer; const aStream: TMemoryStream); overload;
    procedure SendSysEx(const aDeviceIndex: integer; const aString: string); overload;
  end;
GetHandle ist also Teil der Klasse, das war mir so noch nicht klar. Ich habe das für eine Delphi-eigene Funktion gehalten... Damit ergibt die Sache mit dem GetHandle ja erstmal wieder Sinn.

Bääääär

NickNameX 10. Apr 2015 10:06

AW: Problem mit SysEx (MIDI)
 
A bisserl spät, der Thread ist alt .. aber dennoch :
Delphi-Quellcode:
if not MIDIOutput.IsOpen(MidiOutputDevices.ItemIndex) then
     begin
       showmessage('Device not opened!');
       exit;
     end;
   str := 'f0 00 00 7e 32 00 00 01 f7';
   MidiOutput.SendSysEx(MidiOutputDevices.ItemIndex, str );

Was machen denn die Leerzeichen da zwischen den HEX-Werten ?
Kann die aufgerufene Funktion damit umgehen ?
Oder interpretiert sie die Leerzeichen als HEX-Zahlen
(was ja zu keinem sinnvollen Ergebnis führen würde ..)

hathor 10. Apr 2015 10:58

AW: Problem mit SysEx (MIDI)
 
Guckst Du hier:
http://www.midimountain.com/delphi_midi.html

In der procedure StrToSysExStream werden die Leerzeichen entfernt.


Alle Zeitangaben in WEZ +1. Es ist jetzt 06:05 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz