Ich brauche Hilfe bei dem midiOutLongMsg Befehl

Windowsspezifisches Forum , API ,..
Beiträge, die plattformübergreifend sind, gehören ins 'Allgemein'-Forum.
Benutzeravatar
mpz
Beiträge: 505
Registriert: 14.06.2005 15:53
Computerausstattung: Win 11 Pro, 48 GB Ram, Intel I7 CPU und RX4070 Grafikkarte, PB (4/5) 6.12LT
Wohnort: Berlin, Tempelhof

Ich brauche Hilfe bei dem midiOutLongMsg Befehl

Beitrag von mpz »

Hallo Leute,

ich habe ein Problem mit der Wiedergabe von Sysex Daten bei der MIDI wiedergabe. Für diesen Zweck gibt es einen WINAPI Befehl, midiOutLongMsg_
Man übergibt einer Structur MIDIHDR einen Pointer auf einen String. In dem String befinden sich die SYSEX Daten. Die SYSEX Daten können pro Byte $00-$FF betragen. Der String muss damit auch $00 enthalten, was aber im Normalfall String Ende bedeutet und ich die Länge des Strings damit nicht über den Len Befehl erhalten kann. Was tun sprach Zeus... Der midiOutLongMsg_ Befehl gibt bei mir nichts raus und ich weiß nicht warum. Ich hoffe Ihr könnt mir helfen.

Als Grundlage habe ich das MIDICONECTOR.PB Programm aus dem Purebasic Archive benutzt. Ich mache sicherlich Fehler bei den Pointern und Structuren und bin vor lauter @ und * verwirrt...
Ich hoffe Ihr könnt helfen :D ...

Ein Visual Basic Programm als funktionierendes Beispiel liegt bei.

Gruß Michael

Visual Basic code:

Code: Alles auswählen

' 
'My MIDIHDR Structure.. declared in a module 
' 
Structure MIDIHDR 
Dim lpData As String 
Dim dwBufferLength As Integer 
Dim dwBytesRecorded As Integer 
Dim dwUser As Integer 
Dim dwFlags As Integer 
Dim lpNext As Integer 
Dim Reserved As Integer 
End Structure 

' 
' This occurs in a click event 
' 
Dim myhdr As MIDIHDR 
Dim sysex As String 
sysex = chr$(&HF0) & chr$(&H56) & chr(&H64) & chr$(&H4F) & chr$(&H6C) & chr$(&HF7)

With myhdr 
.lpData = sysex 
.dwBufferLength = Len(sysex) 
.dwBytesRecorded = Len(sysex) 
End With 

midiOutPrepareHeader(myhandle, hdr, Len(hdr)) 
midiOutLongMsg(myhandle, hdr, Len(hdr)) 
midiOutUnprepareHeader(myhandle, hdr, Len(hdr)) 

Ende Visual Basic code



Mein nicht funktionierender PureBasic Befehl:

Code: Alles auswählen

;Structure MIDIHDR ; Structur in Purebasic schon definiert
;  lpData.s
;  dwBufferLength.l
;  dwBytesRecorded.l
;  dwUser.l
;  dwFlags.l
;  lpNext.l
;  Reserved.l 
;EndStructure

Procedure Notesysex () 

*MemoryID = AllocateMemory(19)
PokeS(*MemoryID, Chr( $f0 )+Chr($00)+Chr($01)+Chr($40)+Chr($10)+Chr($00)+Chr($14)+Chr($48)+Chr($65)+Chr($6c)+Chr($6c)+Chr($6f)+Chr($20)+Chr($57)+Chr($6f)+Chr($72)+Chr($6c)+Chr($64)+Chr($f7))

test.s = Chr( $f0 )+Chr($00)+Chr($01)+Chr($40)+Chr($10)+Chr($00)+Chr($14)+Chr($48)+Chr($65)+Chr($6c)+Chr($6c)+Chr($6f)+Chr($20)+Chr($57)+Chr($6f)+Chr($72)+Chr($6c)+Chr($64)+Chr($f7)

  Shared HandleOut
  Protected Notensys.MIDIHDR, NoteDat.MIDIData, Notens.MIDIHDR
;  Notensys\lpData = @*MemoryID ! not working
  Notensys\lpData = @test ; not working

  Notensys\dwBufferLength = 19 ; Len (test)
  Notensys\dwBytesRecorded = 19 ; Len (test)
  Notensys\dwFlags = 0

 midiOutPrepareHeader_(HandleOut,Notensys,SizeOf(Notensys))
 midiOutLongMsg_(HandleOut,Notensys,SizeOf(Notensys)) 
 midiOutUnprepareHeader_(HandleOut,Notensys,SizeOf(Notensys))
EndProcedure
Edit by NicTheQuick: Code-Tags gesetzt
Working on :lol: - LibSGD - MP3D Engine - 8)
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8809
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Beitrag von NicTheQuick »

Ich habe deinen Code mal so abgeändert:

Code: Alles auswählen

Procedure NoteSysEx(*SysEx, HandleOut.l) 
  Protected Notensys.MIDIHDR, NoteDat.MIDIData, Notens.MIDIHDR 
  
  Notensys\lpData = *SysEx + 4
  
  Notensys\dwBufferLength = PeekL(*SysEx)
  Notensys\dwBytesRecorded = PeekL(*SysEx)
  
  midiOutPrepareHeader_(HandleOut, Notensys, SizeOf(MIDIHDR)) 
  midiOutLongMsg_(HandleOut, Notensys, SizeOf(MIDIHDR)) 
  midiOutUnprepareHeader_(HandleOut, Notensys, SizeOf(MIDIHDR)) 
EndProcedure

NoteSysEx(?SysEx1, HandleOut)

DataSection
  SysEx1:
    Data.l 19 ; Gibt die Länge an
    Data.b $F0, $00, $01, $40, $10, $00, $14, $4, $65, $6C, $6C, $6F, $20, $57, $6F, $72, $6C, $64, $F7
EndDataSection
Jetzt ist er auch etwas übersichtlicher.

Gleichzeitig sieht der umgesetzte VB-Code jetzt so aus:

Code: Alles auswählen

Structure MIDIHDR
  *lpData.STRING
  dwBufferLength.l
  dwBytesRecorded.l
  dwUser.l
  dwFlags.l
  lpNext.l
  Reserved.l
EndStructure

myhdr.MIDIHDR
sysex.s


sysex = Chr($F0) + Chr($56) + Chr($64) + Chr($4F) + Chr($6C) + Chr($F7)
myhdr\lpData = @sysex
myhdr\dwBufferLength = Len(sysex)
dwBytesRecorded = Len(sysex)

;myhandle -> Handle to the MIDI output device
midiOutPrepareHeader_(myhandle, @myhdr, SizeOf(MIDIHDR))
midiOutLongMsg_(myhandle, @myhdr, SizeOf(MIDIHDR))
midiOutUnprepareHeader_(myhandle, @myhdr, SizeOf(MIDIHDR))
Ich habe das jetzt noch nicht ausprobiert, weil ich sowieso nicht weiß, welche SysEx-Message das jetzt ist.

Aber wenn wir schonmal dabei sind: Weißt du, wo man SysEx-Messages herbekommt, die z.B. auf meiner YAMAHA-Soundkarte irgendwas bewirken?
Benutzeravatar
mpz
Beiträge: 505
Registriert: 14.06.2005 15:53
Computerausstattung: Win 11 Pro, 48 GB Ram, Intel I7 CPU und RX4070 Grafikkarte, PB (4/5) 6.12LT
Wohnort: Berlin, Tempelhof

Beitrag von mpz »

Hallo Nick,

Du hast mir sehr weitergeholfen. Ich habe einen Fehler gemacht. Ich habe aus dem Programm MIDICONECTOR.PB einen MIDI Debugger gebastelt und mit einem virtuellen MIDI Treiber eine Loop erzeugt. Mein Programm hat dann immer die SYSEX Daten gesendet, der MIDICONECTOR.PB konnte diese aber nicht anzeigen. Das Programm geht wohl nur für Noteninformationen, nicht für SYSEX Daten. Daher habe nichts gesehen und mich gewundert. Jetzt habe ich eine Prozedur programnmiert um z.B. Texte auf einem Tranzport Controller zu senden. Es ist damit auch möglich andere SYSEX Daten z.B. zu einer Yamaha Soundkarte zu senden. Ich werde einmal ein Beispiel programmieren und dann hier ins Netz stellen. Die SYSEX Datenbefehle gibt es zu Hauf im Internet.

Gruß Michael

P.S. Ich habe den PokeS() Befehl benutzt, da man auch $00 Werte übergeben muss. Für Purebasic ist dann aber der String zuende. Ich wusste nicht wie ich das Problem anders lösen kann...

Code: Alles auswählen


; Prozedur um einen Text auf das Tranzport von Frontier Design zu senden

Procedure SysExText (string_.s) 

  Protected Notensys.MIDIHDR 
  Shared HandleOut

  *MemoryID = AllocateMemory(8 + Len(string_))
    PokeS(*MemoryID, Chr($f0))
    PokeS(*MemoryID+1,Chr($00))
    PokeS(*MemoryID+2,Chr($01))
    PokeS(*MemoryID+3,Chr($40))
    PokeS(*MemoryID+4,Chr($10))
    PokeS(*MemoryID+5,Chr($00))
    PokeS(*MemoryID+6,Chr($00))
    PokeS(*MemoryID+7, string_.s)
    PokeS(*MemoryID+7+Len(string_), Chr($f7))

  Notensys\lpData = *MemoryID 
  Notensys\dwBufferLength = 8 + Len(string_)
     
  Debug midiOutPrepareHeader_(HandleOut, Notensys, SizeOf(Notensys)) 
  Debug midiOutLongMsg_(HandleOut, Notensys, SizeOf(Notensys)) 
  Debug midiOutUnprepareHeader_(HandleOut, Notensys, SizeOf(Notensys)) 
  FreeMemory(*MemoryID)
EndProcedure 

Procedure SetNativemode () 

  Protected Notensys.MIDIHDR 
  Shared HandleOut

  *MemoryID = AllocateMemory(8)
    PokeS(*MemoryID, Chr($f0))
    PokeS(*MemoryID+1,Chr($00))
    PokeS(*MemoryID+2,Chr($01))
    PokeS(*MemoryID+3,Chr($40))
    PokeS(*MemoryID+4,Chr($10))
    PokeS(*MemoryID+5,Chr($01))
    PokeS(*MemoryID+6,Chr($00))
    PokeS(*MemoryID+7, Chr($f7))

  Notensys\lpData = *MemoryID 
  Notensys\dwBufferLength = 8 
     
  midiOutPrepareHeader_(HandleOut, Notensys, SizeOf(Notensys)) 
  midiOutLongMsg_(HandleOut, Notensys, SizeOf(Notensys)) 
  midiOutUnprepareHeader_(HandleOut, Notensys, SizeOf(Notensys)) 
  FreeMemory(*MemoryID)
EndProcedure 

; Hier geht es los 

SetNativemode () ; Setzt das Tranzport in den Native Modus

test.s ="Das ist ein Text mit Sysex eingebunden"
SysExText(test) 

HandleOut siehe z.B. MIDICONECTOR.PB
Working on :lol: - LibSGD - MP3D Engine - 8)
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8809
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Beitrag von NicTheQuick »

Das mit dem [c]PokeS()[/c] ist doch Schwachsinn. Wenn du eh nur ein Byte in den Speicher kopierst, reicht dir auch [c]PokeB()[/c]. Oder mach es so wie ich mit einer [c]DataSection[/c]. Wenn es sowieso fest einprogrammiert wird, ist das wohl der einfachste und übersichtlichste Weg.

In meiner [c]DataSection[/c] steht immer zu erst die Länge in einem Long und dann die einzelnen Bytes. So kannst du das ganze einfach immer wieder nachträglich ändern ohne viel mit den [c]Poke()[/c]-Befehlen rumzuhantieren und andauernd [c]+1[/c], [c]+2[/c], [c]+3[/c], usw. zu schreiben.

Und wegen den SysEx-Messages im Internet.
Entweder bin ich zu blöd zum suchen, oder man muss nach bestimmten Begriffen suchen, die ich nicht kenne. Kannst du mir nicht ein paar Links geben? Ich habe z.B. eine YAMAHA DS-XG, von der ich gerne wüsste, was man da noch alles mit den SysEx-Messages anstellen kann.
Benutzeravatar
mpz
Beiträge: 505
Registriert: 14.06.2005 15:53
Computerausstattung: Win 11 Pro, 48 GB Ram, Intel I7 CPU und RX4070 Grafikkarte, PB (4/5) 6.12LT
Wohnort: Berlin, Tempelhof

Beitrag von mpz »

Ja statt PokeS() kann man ruhig PokeB() benutzen. Da ich aber kein Fan von Data's bin, behalte ich lieber alle in einem Befehl im Überblick und kann dann einfacher eingreifen und leichter Parameter ändern ( man hat ja auch seine Vorlieben :mrgreen: ) .

Ein gutes Tutorial für SYSEX Daten für Yamaha Karten (XG) findest Du unter:

http://www.studio4all.de/htmlg/frameset090.html

Modernere XG Sounderzeuger besitzen dann nur erweiterte Befehlssätze und mehr Möglichkeiten...

Gruß Michael
Working on :lol: - LibSGD - MP3D Engine - 8)
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8809
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Beitrag von NicTheQuick »

@mpz: Geile Seite.

Damit hab ich schon neue Pläne für ein geeignetes Programm um mit meinem billigen YAMAHA-Keyboard über meine YAMAHA-Soundkarte spielen zu können und trotzdem alle Effekte ausnutzen zu können.
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8809
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Beitrag von NicTheQuick »

Ich bin schon eifrig an der Umsetzung.

Es funktioniert auch schon alles, ich muss nur noch fertig alle Befehle
integrieren.
flanby
Beiträge: 3
Registriert: 06.10.2006 14:34

Beitrag von flanby »

Hallo zusammen!

Ich versuche gerade den Code von euch mit Visual Basic 2005 Express umzusetzten. Ich möchte damit Sysex senden und empfangen können. Leider gehts nicht.
Kann von euch bitte mal jemand den ganzen Code posten? Bin ziemlich genau das, was mal allgemein als blutiger Anfänger bezeichnet.

Danke und Grüße, flanby.
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8809
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Beitrag von NicTheQuick »

Ich kann kein Visual Basic und das mit dem SysEx-Zeugs hab ich grad nicht
hier. Das müsstest du aber sowieso erst einmal von PureBasic nach Visual
Basic übersetzen.
flanby
Beiträge: 3
Registriert: 06.10.2006 14:34

Beitrag von flanby »

[c]Ok, trotzdem danke!
Da gibt für Visual Basic auch nichts. Für c find ich recht viel, aber das kann ich wirklich nicht und ich wills auch garnicht verwenden...

Gruss, Flanby[/c]
Antworten