Datei bestehend aus Hexadezimalzahlen...

Joshman

Mitglied
Hallo.

Ich bin Neuling, ich bitte um Nachsicht...

Ich kann eine Datei (*.syx) die ich aus dem Programm MIDI-OX erstellt habe binär einlesen.

Diese Datei ist ein MIDI Bulk Dump (Speicherabbild eines Harddisk-Recorders, als SysEx-Befehl).

Sie ist in etwa so aufgebaut:

F0 43 00 7E 02 60 4C .... 00 00 04 F7

Als erstes benutze ich den Replace Befehl um die Leerzeichen zu entfernen.

alltext = Replace(alltext, " ", "") --- "alltext" ist meine String Variable, alle Leerzeichen weg ---

Dann mache ich (für alle Fälle) mit UCase alle Buchstaben groß.

alltext = Ucase(alltext)

Die ersten beiden Zeichen "F0" sind der SysEx-Startbefehl.

Die letzten beiden Zeichen "F7" sind der SysEx-Endbefehl.

Nun zu meinem Problem:

Ich muss eine Prüfsumme Berechnen, das sind die beiden Vorletzten Zeichen "04".

Um das hinzu bekommen muss ich den String aus der Datei in Hexadezimal Werte bekommen, um damit zu Rechnen.

Code:
Public Sub checksum()

Dim sumarray(351) As String     'ist wohl falsch Dimensioniert 
Dim startch As Long
Dim endch As Long
Dim chksumloop As Long

startch = 13

endch = 715

For chksumloop = startch To endch Step 2

sumarray(chksumloop) = Mid$(main.dumpin2.Text, chksumloop, 2)

   'hier ist ja alles noch ein String und kein Hexadezimal Wert.

main.chksum2.Text = StringToHex(sumarray(chksumloop))
 'Achtung StringToHex ist eine Funktion, nicht von mir...

countersen = countersen + 1

Next chksumloop

End Sub


Ich komme nicht dahinter, wie ich aus einem 2stelligen String den Richtigen Wert bekomme.

Ich habe es mit der "StringToHex"-Funktion versucht, der gibt mir etwas wie "3443" statt "76" für "4C" raus.

Was mache ich Falsch ?

Ich weiss das ich die Umwandlung nicht schaffe, ich glaube ich stehe im Wald und sehe das Meer...... ;)

Danke im Voraus.

Joshi aus Hamburg.
 
Da Problem ist stringtohex ist genau die falsche Richtung du bräuchtest etwas wie hextostring, hextolong oder hextoint. Ich kenne leider nicht die ganzen convert methoden von .net sonst müsstest du dir die zahlen selber umrechnen.
Algorithmen für die Umrechnung aus dem Zahlensystem mit der Basis 16 in das dezimale System gibt es mit sicherheit schon irgendwo im netz. Ich habe das schon länger nicht mehr gemacht aber ich denke da findest du schon was

Gruß bb
 
Hallo,

1. ein kleiner Tip: Wenn die Hex-Zahlen in der Datei jeweils durch ein Space getrennt vorliegen, nutze die Split-Funktion. So bekommst du ein Array mit den einzelnen Byte-Strings.

Bsp.:
Code:
dim x as string
dim split_array as variant

x = "FF 3E 33"
split_array = split(x, " ")

2. Nun zum Umwandeln des Hex-Strings in eine nutzbare Zahlengröße:

Dazu muss man dem String einfach ein "&H" voransetzen.

Bsp:
Code:
public sub Byte_Wert (Byte_String as String) as long
   Byte_Wert = clng ("&H" & Byte_String)
end sub

Dadurch bekommst Du als Rückgabewert der Beispiel-Funktion den entsprechenden Dezimal-Zahlenwert.

3. Da du bestimmt die Checksumme nach der Berechnung in Hex-Form brauchst, auch hier ein Beispiel:

Code:
dim Hex_String as string
dim x as long

x = 128
Hex_String = hex(x)

Ich hoffe, das hilft Dir weiter
 
Danke, für die schnelle Antwort.

@brainbyte:

Jo, das ist mir jetzt auch klar, das die Werte die ich habe, Hex-Werte sind.
Habe versucht das mit Val(string) zu lösen, was ja nicht geht.
Dann habe ich an eine Lösung auf Basis von vergleichen gedacht.
z.B.: Wenn "4D" dann "76" oder "4C" dann "77" usw.
Geht auch nicht, keine umrechnung in Werten, sondern Erzeugung von neuen Strings.
Also werde ich das mit den "Basis-16er" Algorythmen versuchen.

Aber im folge Thread von RamonR hat er eine vielversprechende Lösung.

THX brainbyte.


@RamonR:

Das mit den Split an Leerstellen, habe ich vorher schon gelöst,
war aber bei den ersten Versuchen nicht das Richtige, habe es dann verworfen.
Ich werde wohl wieder darauf zurückgreifen.
Was ich bis jetzt mit Split gemacht habe ist, gemischte Dumps (mehrere F0...F7 folgen) in
ein Array aufsplitten, und das zu sortieren, damit alle Dumptypen immer an der gleichen
Variable im Array stehen.
Dann werde ich jetzt kein Replace benutzen und statt dessen ByteArray´s bilden.

THX RamonR

Mit Hex(string) habe ich das jetzt eine Summe aus dem Array gebildet, und als Hex-Wert ausgegeben.

Die betreffenden Bytes sind zusammen gezählt "8FC".

Jetzt muss ich laut Hersteller, eine Prüfsumme in etwa so berechnen.


CHECKSUM - 0eeeeeee - ee - ee=(INVERT('StartByte'...'EndByte')+1) AND 7Fh


Also habe ich bis hierhin, die Summe von 'StartByte'...'EndByte'


Code:
'Variablen Initialisieren

Dim startch As Long          'StartByte
Dim endch As Long            'EndByte
Dim chksumloop As Long       'Schleife um Array zu bilden für die Byte´s
Dim countersen As Long       'Zähler für die Arrayindexe
Dim summer As Long           'Summenbildungs Variable
Dim sumarray(351) As Integer 'Array mit 352 Variablen, die Byte Anzahl die, die Summe bildet

'Variablenparameter setzen

countersen = 0
startch = 13
endch = 715

For chksumloop = startch To endch Step 2 'Da der String ohne Leezeichen ist nehme ich immer zwei zeichen

sumarray(countersen) = CInt("&H" & Mid$(main.dumpin2.Text, chksumloop, 2)) 'mein.dumpin2.Text ist die Quelle des Strings

summer = summer + (sumarray(countersen)) 'Summe bilden

main.chksum2.Text = hex(summer) 'Summe darstellen = "8FC"

Verzoegerung                    'kurze Zeitschleife

countersen = countersen + 1     'Arrayindex Inkrementell, gibt es eine andere schreibweise ?

Next chksumloop      'schleifen ende


Und wie ich die oben gemeinte Formel deute, soll die Summe eine Bitumkehr (2er Komplement ?) werden.

Denn muss ich wohl eine Bitverschiebung machen, und dann 'AND &H7F' ?

Ich bin mit den Technischen Support soweit gekommen, das er sagte sie Berechnen das mit "1/Summe * 128".

Ich glaube ich hab ihn nicht Richtig verstanden...

Ich habe beim Suchen für eine Bitumkehr, etwas in C++ gefunden,

den "~" Bitoperator. Gibt es sowas auch in Visual Basic 6 ?

Wer kann mir das mal bitte Erklären. Weil, das ist ja Mathematik, und ich dachte ich kann das..... ,)

Danke für eure geduld...
 
Hallo,

der Operator zum Invertieren eines Wertes müsste 'not' sein.

Bsp.:
Code:
x = not x     'der Wert in X wird invertiert

Zum bilden des 2er Komplements müsstest Du dann noch 1 addieren:

Bsp.:
Code:
private sub Bilde_Komplement (x as byte) as byte
  if x = 0 then
    x = not x
  else
    x = not x
    x = x +1
  endif
  Bilde_Komplement = x
end sub
 
Juhuuuuuuuu.......

IHR SEID DIE BESTEN DER BESTEN; DER BESTEN, DER...... :-) :-) :-)

Also zum Aktuellen stand der Dinge.

Ich habe die Prüfsumme berechnen können. Super, das mit dem - not - geht.

Jetzt habe ich das Programm fast ganz von Vorne geschrieben, weil ich bei einem Problem stecken geblieben bin.

Was ich zu beginn immer gemacht habe, war das ich die Datei in einzelne SysEx-Befehle gesplittet habe.
Damit hatte ich einen String-Array.
Der wurde dann Sortiert, in die Einzelnen Dumps und In einen vordimensionierten Array.
Dann fand ich heraus, das die Dumps mehrerer Typen, wiederum mehrere, einzelne SysEx-Befehle sind.

Beispiel: Szenen sind Schnappschüsse der Reglerpositionen, die in einer 96 langen Tabelle abgelegt werden.
Die aber nur mit den abgelegten Szenen dann belegt ist. Szene 1 belegt. Szene 2 nicht belegt. Szenen 40-45 belegt etc.

F0 Szene01 bla bla F7 F0 Szene02 bla bla F7 F0 Szene03 bla bla F7.....

Nun hatte ich mit dem " & " die Strings im Szenen-Array-Feld aneinander gehängt, um sie dann in neue Arrays zu packen.

Die sollten dann aber nun, mit dem Split-Befehl, in ein Byte-Array.

Das bekomme ich ja auch hin, aber eigentlich wollte ich die Arrays erst bei bedarf dimensionieren (Laufzeiterstellung von Arrays),
um den Speicher nicht vorab zu reservieren.

Info: Jede Szene hat 5104 bytes, wenn also nur z.B. 12 vorhanden sind, wäre das doch logisch,
nicht alle Arrays auf einmal zu dimensionieren.

Also hatte ich die Idee Arrays zur Laufzeit in einer Funktion mit einschlägigen Namen zu erstellen.

Habe ich nicht hinbekommen, weil ich nicht Verstehe, wie Variablennamen zur Laufzeit erstellet werden können.

Beispiel eines Fehlversuchs:


Code:
for i = 0 to Ubound(SceneArray())
SceneArray & str(i) = Split(SceneArray(i))   ' hier die misslungene Namensvergabe 
Redim Preserve SceneArray & Str(i) +1 
next i

Folge: Neuanfang

Habe dann gedacht, wenn ich die Datei gleich in ein Byte-Array lese komme ich drumherum. NIXDA

Habe mich aber entschlossen, bei der Byte-Array Variante zu bleiben, wegen der Arbeitsgeschwindigkeit des Programms.

Jetzt, habe ich aber erst recht das Problem.

1. Konsequenz: Büffeln. Tutorial von Highli gepaukt.

1. Schlußfolgerung: Ich könnte doch ein Parameter-Array benutzen.

2. Konsequenz: Nicht richtig begriffen, weil ja wieder keine Namen erstellet werden.

2 Schlußfolgerung: Frage doch mal "die Allerbesten" helfer hier im Forum.


Wenn ich dann schon einmal am fragen bin, mach ich doch mal weiter...

Wenn ich wie von "brainbyte" das Array erstelle, benutzt er ein Variant (habe als erstes ein String-Array benutzt).
Dann durchlaufe ich die Variant-Datei mit eine Schleife, um ein Byte-Array daraus zu machen.
Code:
Public Sub filein1()

Dim alltext As Variant

  ' dateien einlesen
  ' wird im "CommonDialog" auf "Abbrechen" geklickt,
  ' wird (wenn CancelError = True ist) ein Laufzeitfehler ausgelöst.
  
    On Error Resume Next
  With CommonDialog1
    .CancelError = True
    
    ' Filter setzen - hier wird festgelegt, mit welchem Format
    ' eine Datei geöffnet wird.
 .Filter = "Dump Dateien (*.syx)|*.syx|Text Dateien (*.txt)|*.txt|Alle Dateien (*.*)|*.*"
    ' Dialogfeld Öffnen anzeigen
    .ShowOpen
    If .FileName <> "" Then
      f = FreeFile
   Open .FileName For Binary As #f
      ' binär(alles auf einmal) aus Textdatei einlesen und in Variable alltext speichern

Dumper.dumpinname.Caption = Right(.FileName, 24)   
' Nur den Dateinamen anzeigen, noch nicht fertig...

Line Input #f, LineOfText
alltext = LineOfText ' Übergabe der Datei in Variant-Variable
    End If

  End With
  
  alltext = Trim(alltext)
  alltext = UCase(alltext) ' alles in großbuchstaben wandeln
  
  
arraysyx() = Split(alltext, " ") 
' Jetzt wird das ein String-Array -VarType(arraysyx()) = 8200- -VarType(arraysyx(0)) = 8-


Dim btInputAll() As Byte


ProgressBar1.Value = 20


For i = 0 To UBound(arraysyx())

ReDim Preserve btInputAll(UBound(arraysyx()))

btInputAll(i) = "&H" & arraysyx(i) 
'-VarType(btInputAll(0)) = 17- -VarType(btInputAll()) = 8209


Next i


Erase arraysyx()


Frage: Ist es möglich die Schleife zu umgehen? Wenn nein auch o.K. weil dauert halt nicht lange ?

Frage: Wenn ich nun das große Array habe, sollte ich die einzelnen SysEx-Befehle von hinten im array abschneiden ?

ála :
gehe bis zum letzten Arrayfeld mit den inhalt "F0" respektive "&HF0"
kopiere alles in das dazugehörige "neuerstellte" Array
Redim bis letzte "F0" Position, und mach bis array leer, dann am besten Array löschen...

Guter Ansatz?

Hoffe das geht dann auch wenn,
ich das mit der MIDI Schnittstelle in Echtzeit mache......
In ca. 35000 Jahren... HIHI


Danke abermals für euer Verständniss, und THX.

Joshi aus HH, mit Suuuper Wetter, aber was geht mich das an, will doch Progger werden....
 
Zurück