Informationen aus MP3-Dateien auslesen

Sonstiges (nicht kategorisierbar)

Moderator: Moderatoren

peternmb
1000 working lines a day
1000 working lines a day
Beiträge: 525
Registriert: Mi, 01. Feb 2006 16:22
Wohnort: 06618 Naumburg

Informationen aus MP3-Dateien auslesen

Beitrag von peternmb »

Hallo, vielleicht hat jemand einen Tipp für mich.
Ich möchte Informationen aus MP3-Dateien auslesen. Ich benötige die Spieldauer und die Sampling-Rate. Evtl. noch die Möglichkeit ID-Tags zu lesen oder zu ändern. Das MP3-Beispiel auf der Alaska-Website bringe ich leider nicht zum Laufen weil der angegebene Link für die mp3.dll nicht funktioniert. Auch mit anderen mp3.dll`s klappt nicht.
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9365
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 102 Mal
Danksagung erhalten: 361 Mal
Kontaktdaten:

Beitrag von Tom »

Hallo, Peter.

Diese MP3.DLL gibt's anscheinend nicht mehr als Freeware; ich bin eine Weile durch die spanischsprachigen Sites gestolpert und immer wieder auf einer PayPal-Site gelandet. :lol:

Aber MPEG/MP3 sind vergleichsweise simpel. MP3 mit ID-Tags basiert auf MP2. Beide Formatbeschreibungen findest Du u.a. hier:

http://audio.layer2.de/das_mp2format.php
http://audio.layer2.de/das_mp3format.php

Einfach byteweise auslesen.
Herzlich,
Tom
peternmb
1000 working lines a day
1000 working lines a day
Beiträge: 525
Registriert: Mi, 01. Feb 2006 16:22
Wohnort: 06618 Naumburg

klappt nicht so richtig

Beitrag von peternmb »

ja, klingt theoretisch ganz einfach - ich bekomms aber nicht gebacken.
Habe mir eine kleine Function geschrieben, um die Infos byteweise auszulesen und anzeigen zu lassen. Ich bekomme aber nichts angezeigt. Vielleicht findet einer den Fehler :)

Code: Alles auswählen

#include "fileio.ch"
proc say_header(cDatei)
LOCAL nHandle := 0, inhalt:=space(32)
//
nHandle := FOPEN(cDatei, FO_READ + FO_SHARED)
//
IF nHandle > 0
   FREAD(nHandle, inhalt,32)    //32 byte auslesen
ENDIF
//
FCLOSE(nHandle)
//
msgbox(inhalt)
//
return
Bin für jeden Hiwneis dankbar. Die Links waren super :) [/code]
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9365
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 102 Mal
Danksagung erhalten: 361 Mal
Kontaktdaten:

Beitrag von Tom »

Klammeraffen vergessen:

Code: Alles auswählen

FREAD(nHandle, @inhalt,32)
Herzlich,
Tom
peternmb
1000 working lines a day
1000 working lines a day
Beiträge: 525
Registriert: Mi, 01. Feb 2006 16:22
Wohnort: 06618 Naumburg

Beitrag von peternmb »

jetzt bekomme ich zumindest etwas angezeigt, aber nicht was ich erwartet habe. Es wird nur ID3 und ein seltsames Zeichen angezeigt. Leider bin ich mit Dateiheadern o.ä. nicht sehr vertraut. Vielleicht kannst du mir nochmal weiterhelfen :idea:
Siggi
Rookie
Rookie
Beiträge: 12
Registriert: Di, 07. Feb 2006 14:53
Wohnort: Limsdorf

Beitrag von Siggi »

Hallo Leute,

ich habe mal für einen Freund ein Tool geschrieben, daß den Titel, Interpret aus dem Dateiname in den ID3Tag schreibt.
Hier ohne Korrektur die Schreibroutine.

Code: Alles auswählen

********************
FUNCTION ID3PUT(cFZiel, Titel, Interpret, Album )
********************
LOCAL nWrite:=1, cT:="ID3"+chr(03)+chr(0)+chr(0)+chr(0)+chr(0)+chr(15)+"v", nNr, nH
LOCAL V1:="TAG", bV1:=.f., bV2:=.f., cBuffer:=space(127)

if nWrite >0
   * ID3V2 wird an den Dateianfang gestellt
   cT+="TIT2"+chr(0)+chr(0)+chr(0)+chr(len(Titel)+1)+chr(0)+chr(0)+chr(0)+Titel
   cT+="TPE1"+chr(0)+chr(0)+chr(0)+chr(len(Interpret)+1)+chr(0)+chr(0)+chr(0)+Interpret
   cT+="TALB"+chr(0)+chr(0)+chr(0)+chr(len(Album)+1)+chr(0)+chr(0)+chr(0)+Album
   cT+= Replicate(chr(0), 100)

   * ID3V1 kommt ans Dateiende
   V1+=padr(Titel    , 30, chr(0))
   V1+=padr(Interpret, 30, chr(0))
   V1+=padr(Album    , 30, chr(0))
   V1+=repl(chr(0), 34)+chr(255)


   if ( nH := FOpen(cFZiel, FO_READWRITE+FO_SHARED)) # 0 .and. FSEEK (nH, 0, FS_SET) # -1
        * ID3V2  wird geschrieben
         if (nNr:=FWrite(nH ,cT )) # 0 ; bV2:=.t.;  endif
        * ID3V1 erst prüfen ob schon vorhanden
         if (FSEEK (nH, -1, FS_END) # -1)
            FRead(nH, @cBuffer, 1)
            if substr(cBuffer,1,1) = chr(255)   // FF wenn vorhanden
               FSEEK (nH, -128, FS_END)
            endif
            if (nNr:=FWrite(nH ,V1 )) # 0 ; bV1:=.t.;  endif
         endif
         Fclose(nH)
         if ! bV2 ; StopBox("ID3V2 konnte nicht geschrieben werden !", cFZiel);  endif
         if ! bV1 ; StopBox("ID3V1 konnte nicht geschrieben werden !", cFZiel);  endif
      else; StopBOX("Die Datei ["+cFZiel+"] wurde nicht aktualisiert !;;Win-Fehlernummer: "+TTOC(FError() ),"ID3PUT()"); nWrite:=0
      endif
endif
return (nWrite)
peternmb
1000 working lines a day
1000 working lines a day
Beiträge: 525
Registriert: Mi, 01. Feb 2006 16:22
Wohnort: 06618 Naumburg

Byte & Bit

Beitrag von peternmb »

irgendwie hängst es an der Umwandlung von Bytes in Bits.
Ich kann mir zwar die Bytes anzeigen lassen - ich bräuchte aber die Bits.

Das mit den ID-Tags ist zwar hilfreich, trifft aber glaube ich nicht ganz den Kern der Sache.

Ich bräuchte einfach die ersten 32 Bit des Headers der Datei. Was ich bisher gefunden habe geht das nur mit C oder VB
Benutzeravatar
Martin Altmann
Foren-Administrator
Foren-Administrator
Beiträge: 16517
Registriert: Fr, 23. Sep 2005 4:58
Wohnort: Berlin
Hat sich bedankt: 111 Mal
Danksagung erhalten: 48 Mal
Kontaktdaten:

Re: Byte & Bit

Beitrag von Martin Altmann »

Hallo Peter,
peternmb hat geschrieben:Ich bräuchte einfach die ersten 32 Bit des Headers der Datei. Was ich bisher gefunden habe geht das nur mit C oder VB
soweit ich weiß, kann man mit den Array-Operatoren bitweise auslesen. Es sollte also so gehen:

Code: Alles auswählen

inhalt[1] // entspricht dem 1. Bit
inhalt[2] // entspricht dem 2. Bit
...
inhalt[32] // entspricht dem 32. Bit
Viele Grüße,
Martin
:grommit:
Webseite mit XB2.NET und ausschließlich statischem Content in Form von HTML-Dateien: https://www.altem.de/
Webseite mit XB2.NET und ausschließlich dynamischem Content in Form von in-memory-HTML: https://meldungen.altem.de/

Mitglied der XUG Osnabrück
Vorsitzender des Deutschsprachige Xbase-Entwickler e. V.
peternmb
1000 working lines a day
1000 working lines a day
Beiträge: 525
Registriert: Mi, 01. Feb 2006 16:22
Wohnort: 06618 Naumburg

Beitrag von peternmb »

nein, funktioniert leider nicht.
Es werden da auch nur die Bytes angezeigt.

Hat denn noch Keiner eine Function geschrieben, um den Datei-Header bitweise auszulesen - oder ist das einfach in xbase nicht möglich :cry:
Benutzeravatar
Martin Altmann
Foren-Administrator
Foren-Administrator
Beiträge: 16517
Registriert: Fr, 23. Sep 2005 4:58
Wohnort: Berlin
Hat sich bedankt: 111 Mal
Danksagung erhalten: 48 Mal
Kontaktdaten:

Beitrag von Martin Altmann »

Ach Mensch - Du wolltest ja 32 Byte bitweise ausgelesen haben, sorry!! Ich war davon ausgegangen, dass in der Vairablen inhalt genau ein Byte steht! ](*,)
Dann probiere es mal mit dem Konstrukt:

Code: Alles auswählen

inhalt[1][1] // entspricht dem 1. Bit des 1. Bytes
inhalt[1][2] // entspricht dem 2. Bit  des 1. Bytes
... 
inhalt[32][8] // entspricht dem 8. Bit des 32. Bytes
Klappt das denn dann wenigstens??

Viele Grüße,
Martin
:grommit:
Webseite mit XB2.NET und ausschließlich statischem Content in Form von HTML-Dateien: https://www.altem.de/
Webseite mit XB2.NET und ausschließlich dynamischem Content in Form von in-memory-HTML: https://meldungen.altem.de/

Mitglied der XUG Osnabrück
Vorsitzender des Deutschsprachige Xbase-Entwickler e. V.
peternmb
1000 working lines a day
1000 working lines a day
Beiträge: 525
Registriert: Mi, 01. Feb 2006 16:22
Wohnort: 06618 Naumburg

Beitrag von peternmb »

Nein, haut leider auch nicht hin - ich erhalte eine Fehlermeldung. So wie es aussieht ist die Variable inhalt nur ein 1-dimensionales Array :cry:
Benutzeravatar
Martin Altmann
Foren-Administrator
Foren-Administrator
Beiträge: 16517
Registriert: Fr, 23. Sep 2005 4:58
Wohnort: Berlin
Hat sich bedankt: 111 Mal
Danksagung erhalten: 48 Mal
Kontaktdaten:

Beitrag von Martin Altmann »

Hallo Peter,
peternmb hat geschrieben:So wie es aussieht ist die Variable inhalt nur ein 1-dimensionales Array :cry:
ja - das ist schon klar. Sonst wäre der Index ja auch [ 1, 2 ] gewesen.
Komisch - in der Alaska-Newsgroups gibt es mehrere Postings zu dem Thema. Und da wurde gesagt, dass ab Xbase++ Version 1.7 das bitweise aulsesen einer Variablen über die Array-Operanden funktioneren soll.
Ich selber habe das noch nie gemacht - darum hatte ich auch geschrieben:
Martin Altmann hat geschrieben:soweit ich weiß, kann man mit den Array-Operatoren bitweise auslesen. Es sollte also so gehen:
Tut mir wirklich leid, dass ich Dir scheinbar nicht helfen kann!
Du könntest höchstens noch mal den umständlichen Weg probieren - nur um sicher zu gehen:

Code: Alles auswählen

FOR i := 1 to 32
  byte := inhalt[ i ]
  FOR j := 1 to 8
    bit := byte[ j ]
    ...
  NEXT
NEXT
Viele Grüße,
Martin
:grommit:
Webseite mit XB2.NET und ausschließlich statischem Content in Form von HTML-Dateien: https://www.altem.de/
Webseite mit XB2.NET und ausschließlich dynamischem Content in Form von in-memory-HTML: https://meldungen.altem.de/

Mitglied der XUG Osnabrück
Vorsitzender des Deutschsprachige Xbase-Entwickler e. V.
peternmb
1000 working lines a day
1000 working lines a day
Beiträge: 525
Registriert: Mi, 01. Feb 2006 16:22
Wohnort: 06618 Naumburg

Beitrag von peternmb »

ich habe es fast auf die gleiche Art probiert - Fehlermeldung.

Muss ich mich halt dochmal in der englischsprachigen Newsgroup quälen. Gesucht habe ich dort schonmal aber nichts gefunden.

Verstehe ich nicht, dass ich der Erste bin der sowas machen will :?:

Erstmal vielen Dank.
thomas
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 116
Registriert: Fr, 23. Sep 2005 16:07
Wohnort: Bad Oldesloe
Kontaktdaten:

Beitrag von thomas »

Hallo Peter,

habe mal vor langer Zeit mit Bits setzen und abfragen eine Programm geschrieben.
Schau die doch mal diese Programmzeilen genauer an, ich denke es könnte helfen.

Gruß

Thomas

Code: Alles auswählen

#include "fileio.ch" 
proc say_header(cDatei) 
LOCAL nHandle := 0, inhalt:=space(4) 
nHandle := FOPEN(cDatei, FO_READ + FO_SHARED) 
IF nHandle > 0 
    FREAD(nHandle, @inhalt,4) //  4 byte a 8Bit = 32 Bit auslesen 
ENDIF 
// 
FCLOSE(nHandle) 

// Test die ersten 8 Bits
cByte := SUBSTR(inhalt,1,1)

IF 2 $ VAL(cByte)
     // Bit 1 ist gesetzt
ELSE
     // Bit ist nicht gesetzt
ENDIF

IF 4 $ VAL(cByte)
     // Bit 2 ist gesetzt
ENDIF

IF 2+8+32 $ VAL(cByte)
     // Bit 1 und 3 und 5 sind gesetzt
ENDIF

cBitString := s_bit(VAL(cByte))
MsgBox(cBitString)
return 



FUNCTION s_bit( nZahl )
LOCAL cStrg :=""
LOCAL nIx
FOR nIx = 7 TO 0 STEP -1
    IF nZahl >= 2 ** nIx
        nZahl := nZahl - 2 ** nIx
        cStrg += "1"
    ELSE
        cStrg += "0"
    ENDIF
NEXT nIx
RETURN( cStrg )
Benutzeravatar
Wolfgang Ciriack
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2935
Registriert: Sa, 24. Sep 2005 9:37
Wohnort: Berlin
Hat sich bedankt: 13 Mal
Danksagung erhalten: 34 Mal
Kontaktdaten:

Beitrag von Wolfgang Ciriack »

Ansonsten könnte man noch aus den XbToolsIII die Funktion IsBit() nutzen (wenn man diese ebenfalls besitzt).
Viele Grüße
Wolfgang
Benutzeravatar
Martin Altmann
Foren-Administrator
Foren-Administrator
Beiträge: 16517
Registriert: Fr, 23. Sep 2005 4:58
Wohnort: Berlin
Hat sich bedankt: 111 Mal
Danksagung erhalten: 48 Mal
Kontaktdaten:

Beitrag von Martin Altmann »

Hallo Peter,
ich kann es nicht lassen :-)
Ich habe mal gerade in der Doku von Xbase++ gestöbert. Der folgende Abschnitt ist interessant - die fett-Formatierung dient dem Hervorheben der wichtigen Dinge:
[] Operator hat geschrieben:Der Array-Operator ist nicht auf Werte vom Datentyp "Array" beschränkt, sondern kann auch auf Zeichenketten und numerische Werte angewandt werden. Hinweis: In der aktuellen Xbase++ Version ist der Operator bei Zuweisungen nur bei LOCAL oder STATIC Variablen, denen die Zeichenkette bzw. der numerischen Wert zugewiesen ist, anwendbar.

Zeichen Bei Zeichenketten gibt der Operator das Zeichen an der Position <nElement> aus der Zeichenkette zurück (siehe Beispiel unten). Das Ermitteln einzelner Zeichen aus einer Zeichenkette läuft mit dem Array-Operator sehr viel schneller ab als mit der Funktion SubStr().
Numerisch Wenn der Operand einen numerischen Wert hat, prüft der Operator, ob das Bit an der Position <nElement> gesetzt ist. Das Ergebnis der Operation ist .T. (wahr), falls das Bit gesetzt ist, andernfalls ist es .F. (falsch). Der Wert des Operanden kann auf Bit-Ebene verändert werden, indem der Wert .T. oder .F. für das Bit an der Position <nElement> zugewiesen wird. Der Wertebereich für <nElement> erstreckt sich bei numerischen Operanden von 1 bis 32.
Und hier mal das entsprechende Beispiel aus der Doku:

Code: Alles auswählen

// Array-Operator und numerische Werte
// Das Beispiel zeigt wie der Array-Operator mit
// Werten vom Datentyp Numerisch verwendet werden kann.
 
   PROCEDURE Main 
      LOCAL n 
 
      ? n := 6          // Ergebnis: 6 
 
      ? n[1]            // Ergebnis: .F. (Bit für 2^0 ist nicht gesetzt) 
      ? n[2]            // Ergebnis: .T. (Bit für 2^1 ist gesetzt) 
      ? n[3]            // Ergebnis: .T. (Bit für 2^2 ist gesetzt) 
 
      n[1] := .T.       // Bit für 2^0 setzen 

 
      ? n               // Ergebnis: 7 

   RETURN
Viele Grüße,
Martin
Zuletzt geändert von Martin Altmann am Do, 16. Mär 2006 8:18, insgesamt 2-mal geändert.
:grommit:
Webseite mit XB2.NET und ausschließlich statischem Content in Form von HTML-Dateien: https://www.altem.de/
Webseite mit XB2.NET und ausschließlich dynamischem Content in Form von in-memory-HTML: https://meldungen.altem.de/

Mitglied der XUG Osnabrück
Vorsitzender des Deutschsprachige Xbase-Entwickler e. V.
peternmb
1000 working lines a day
1000 working lines a day
Beiträge: 525
Registriert: Mi, 01. Feb 2006 16:22
Wohnort: 06618 Naumburg

Beitrag von peternmb »

muss ich mir nochmal in Ruhe ansehen, ich verstehe das bisher noch nicht so richtig :?:

Ich bräuchte einfach die ersten 32 Bit des Dateiheaders als Zeichenkette.
Die 32 Zeichen würden dann, wenn ich alles halbwegs verstanden habe nur aus 32x 0 oder 1 bestehen.

Aber ich glaube, mit den bisherigen Infos ist es zu schaffen :razz:
Benutzeravatar
andreas
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 1902
Registriert: Mi, 28. Sep 2005 10:53
Wohnort: Osnabrück
Hat sich bedankt: 4 Mal
Kontaktdaten:

Beitrag von andreas »

Hallo Martin,

ich habe schon lange die Abfrage bzw. Setzen einzelner Bits gesucht.
Jetzt habe ich das aus deinem letzten Posting ausprobiert und in eine vorhandene Anwendung eingebaut.
Komischerweise kann ich die Bits abfragen aber nicht setzen.
Wenn ich aber den Code aus der Hilfe (auch in deimen Posting) als eigene Anwendung kompiliere, funktioniert es.

Was kann das sein?
Gruß,

Andreas
VIP der XUG Osnabrück
peternmb
1000 working lines a day
1000 working lines a day
Beiträge: 525
Registriert: Mi, 01. Feb 2006 16:22
Wohnort: 06618 Naumburg

Beispielcode von Thomas

Beitrag von peternmb »

Hallo, ich habe den Beispielcode von Thomas mal so erweitert, dass die ersten 4 Byte à 8 Bit angezeigt werden, aber das Ergebniss verblüfft mich etwas. Es werden beim Einlesen von einer MP3-Datei nur die Bits 23 und 24 als gesetzt gezeigt. Der Rest sind alles Nullen. Das kann lt. der Header-Beschreibung aber nicht hinkommen. Ich glaube ich geb`s auf - ich kann mittlerweile keine Bits und Bytes mehr sehen :angryfire:
Benutzeravatar
Martin Altmann
Foren-Administrator
Foren-Administrator
Beiträge: 16517
Registriert: Fr, 23. Sep 2005 4:58
Wohnort: Berlin
Hat sich bedankt: 111 Mal
Danksagung erhalten: 48 Mal
Kontaktdaten:

Beitrag von Martin Altmann »

Hallo Andreas,
andreas hat geschrieben:Wenn ich aber den Code aus der Hilfe (auch in deimen Posting) als eigene Anwendung kompiliere, funktioniert es.

Was kann das sein?
keine Ahnung - außer dass Deine Variable vielleicht weder vom Typ local noch vom Typ static ist?

Viele Grüße,
Martin
:grommit:
Webseite mit XB2.NET und ausschließlich statischem Content in Form von HTML-Dateien: https://www.altem.de/
Webseite mit XB2.NET und ausschließlich dynamischem Content in Form von in-memory-HTML: https://meldungen.altem.de/

Mitglied der XUG Osnabrück
Vorsitzender des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
andreas
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 1902
Registriert: Mi, 28. Sep 2005 10:53
Wohnort: Osnabrück
Hat sich bedankt: 4 Mal
Kontaktdaten:

Beitrag von andreas »

Hallo Martin,

du hast recht. Die Variable muss deklariert sein, sonst funktioniert nur die Abfrage!
Gruß,

Andreas
VIP der XUG Osnabrück
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12909
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 46 Mal

re: MP3 TAG

Beitrag von AUGE_OHR »

moin,

da ich mich auch gerade mit den MP3 ID TAG beschäftige habe,
ein paar Anmerkungen :

a.) es gibt MP3 ID TAG v1.0 & v1.1 welche beide am ENDE der
Datei die letzten 128 Byte füllen.

{ID3-TAGv1 sind die letzten 128 Bytes
der Datei und sind so aufgeteilt:
Byte 1-3 = Kennung 'TAG' 3
Byte 4-33 = Titel 30
Byte 34-63 = Artist 30
Byte 64-93 = Album 30
Byte 94-97 = Jahr 4
Byte 98-127 = Kommentar 30 (28 Kommentar + 2 TrackNo.)
Byte 128 = Genre} 1 (0-79)

b.) die v2.0x MP3 ID TAG Version von der ihr hier sprecht ist "ein wenig"
komplizierter aufgebaut. siehe link

http://www.id3.org/develop.html

beim letzten war ich dran, bis ich feststellte das ich anders rankomme
da ich Xbase++ RC2 mit WMP.OCX benutze. Also kann ich aus der
WMP Playliste mit Hilfe des WMP Event "CurrentItemChange" von
jedem Item die "Property" auslesen und hab dann alle Informationen
die ich benötige.

gruss by OHR
Jimmy
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15697
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 66 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Beitrag von brandelh »

@petermb

> Ich bräuchte einfach die ersten 32 Bit des Dateiheaders
> als Zeichenkette.
> Die 32 Zeichen würden dann, wenn ich alles halbwegs verstanden
> habe nur aus 32x 0 oder 1 bestehen.

NEIN, so funktioniert das nicht.

'0101' sind keine 4 Bit, sondern 4 Byte und der WERT der Variable intern ist nicht 0 oder 1 sondern '0' = ASC('0') = 48 und '1' = ASC('1') = 49
Wenn du eine String-Variable mit einem Byte hast, dann kann man leicht die Bits zuordnen:

00000000 -> chr(0)
00000001 -> chr(1) oder neuerdings bei numerisch nVal[1] := 1
00000010 -> chr(2) oder neuerdings bei numerisch nVal[2] := 1
00000011 -> chr(3) oder neuerdings bei numerisch nVal[2] := 1 und nVal[1] := 1

bei den neuen nVal[] Funktionen bin ich mir jetzt nicht sicher, da ich diese so nie brauche.

Ein 32 Bit Wert mit 1 sieht also intern so aus:

00000000 00000000 00000000 00000001 aber die Reihenfolge der Speicherung muß nicht unserer Lesart entsprechen.

In deinem Beispiel ganz am Anfang ließt du 32 BYTE ein, denn jeder Befehl in Xbase++, welcher auf Festplatten, Strings etc. zugreift arbeitet immer BYTE-weise !

Um 32 Bit zu bekommen mußt du 4 Byte einlesen (da 4 Byte * 8 Bit = 32 Bit). Wenn du dies aber in eine Stringvariable einliest, kannst du mit dem Arrayoperator nur auf einzelne BYTE (Zeichen, String = array of Byte in C ) zugreifen. Um mit dem Arrayoperator auf BIT Zugreifen zu können müßtest du die 4 Byte in eine Zahl verwandeln (VAL hilft hier nicht !), welche genaue Reihenfolge weiß ich im Moment auch nicht, aber im Prinzip so

asc(cString[1])+ asc(cString[2])*256 + asc(cString[3])*256*256 + asc(cString[4])*256*256*256

Das Problem ist, zu erkennen, welche der einzelnen Zeichen jetzt welchen Multiplikator braucht. Vor Jahren habe ich mit PowerBasic den Dateiheader von DBF Dateien zerlegt, da war zuerst das niederwertige Byte gespeichert dann das höherwertige - bei 16 Bit Werten.

Dummerweise gibt es in Xbase++ keine 32 Bit - INTEGER / DWORD Variablen. Hast du die Tools ? Dort gibt es Funktionen zu BIT Operationen, wie gut die sind weiß ich aber nicht. Mit den nVal[] Operatoren sollte es aber auch gehen.

Wichtig, man kann zwar aus einer 4 Byte Variablen (Stringlänge 4 oder Integer) einen 32 Byte langen String mit 0 und 1 machen, dieser hat aber keine 32 Bit sondern 32 BYTE, auch wenn er eventuell für dich nützlich wäre.

Solltest du dies bereits gewußt haben, sorry, aber ich habe den Eindruck, dass du bei Bit und Byte etwas durcheinander gebracht hattest.
Forsche nun nochmals die Beispiele weiter oben durch, eventuell paßt es dann ja.
Gruß
Hubert
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15697
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 66 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Beitrag von brandelh »

Hi,

ich habe hier mal ein kleines Programm erstellt, welches die Bit und Byte einer 32 Bitzahl ausleuchtet:

Code: Alles auswählen

procedure main
   local cTxt, nWert, nSollWert

   set alternate to test.txt
   set alternate on

   cls
   ? "Start"
   for x := 1 to 32
       cTxt := replicate("0",32)  // immer löschen
       cTxt[33-x] := "1"  // wir lesen 1. Bit von rechts
       nWert := 0         // immer löschen
       nWert[x] := .t.    // .t. = 1
       nSollWert := int(2^(x-1))
       ? x,cTxt,nWert,nSollWert
   next
   ? "Ende"

   set alternate to

return
und nun noch das Ergebnis:

Code: Alles auswählen


Start
         1 00000000000000000000000000000001          1          1
         2 00000000000000000000000000000010          2          2
         3 00000000000000000000000000000100          4          4
         4 00000000000000000000000000001000          8          8
         5 00000000000000000000000000010000         16         16
         6 00000000000000000000000000100000         32         32
         7 00000000000000000000000001000000         64         64
         8 00000000000000000000000010000000        128        128
         9 00000000000000000000000100000000        256        256
        10 00000000000000000000001000000000        512        512
        11 00000000000000000000010000000000       1024       1024
        12 00000000000000000000100000000000       2048       2048
        13 00000000000000000001000000000000       4096       4096
        14 00000000000000000010000000000000       8192       8192
        15 00000000000000000100000000000000      16384      16384
        16 00000000000000001000000000000000      32768      32768
        17 00000000000000010000000000000000      65536      65536
        18 00000000000000100000000000000000     131072     131072
        19 00000000000001000000000000000000     262144     262144
        20 00000000000010000000000000000000     524288     524288
        21 00000000000100000000000000000000    1048576    1048576
        22 00000000001000000000000000000000    2097152    2097152
        23 00000000010000000000000000000000    4194304    4194304
        24 00000000100000000000000000000000    8388608    8388608
        25 00000001000000000000000000000000   16777216   16777216
        26 00000010000000000000000000000000   33554432   33554432
        27 00000100000000000000000000000000   67108864   67108864
        28 00001000000000000000000000000000  134217728  134217728
        29 00010000000000000000000000000000  268435456  268435456
        30 00100000000000000000000000000000  536870912  536870912
        31 01000000000000000000000000000000 1073741824 1073741824
        32 10000000000000000000000000000000 2147483648 2147483648
Ende
Im Speicher ist es also einfacher als ich dachte und laut Beschreibung des ID-Tag sollte es auch dort einfach abgelegt sein. Meine Erinnerung bezog sich auf gepackte Datumsfelder.
Gruß
Hubert
peternmb
1000 working lines a day
1000 working lines a day
Beiträge: 525
Registriert: Mi, 01. Feb 2006 16:22
Wohnort: 06618 Naumburg

Beitrag von peternmb »

Na, da werde ich mich doch nochmal mit den Bits & Byten befassen :? Ich glaube das Posting von Hubert bringt mich da jetzt eine Schritt weiter. Vielen Dank.

Das mit den ID3-Tags (wie weiter oben angesprochen) ist zwar auch interessant, liefert mir aber nicht die Informationen die ich eigentlich haben möchte (z.B. Samplingrate).
Antworten