Die ersten 32Bit einer File auslesen
-
Hi Peter Piksa
Dein Programmier(n)lehrer hat eigentlich Recht.
Der BCB, mit dem ich arbeite mag das aber nicht, der scheint 0xff zu erweitern (oder arbeitet mit Vorzeichen???) Mit OHNE typecast char(0xFF) klappt's im BCB nicht, k.a. warum.
Du kannst das theoretisch weglassen. Dein Compiler kann's dann vielleicht besser!
char(0xFF) erzwingt, dass ein EinByte- Wert kommt.(Wie gesagt, ist bei meinem BCB noetig, muesste eigentlich ohne gehen!!!)
Du musst dir den Inhalt von OneByte mal im Debugger anschauen!!!
Und mach den Typecast mal raus!!!
PS: Mit dem geposteten Code (etwas erweitert!) hab ich mehrere Header in MP3- Dateien gefunden!!! Genau wie das sein sollte!
[ Dieser Beitrag wurde am 30.03.2003 um 19:50 Uhr von DerAltenburger editiert. ]
-
Kann es vielleicht sein dass bei mir immer wieder "nicht gefunden" raus kommt, weil der FilePointer sich nicht weiterbewegt?
-
Neeeeee
Der Filepointer wird immer automatisch weitergeschoben um die gelesenen Bytes!
Wenn Du in der leseschleife nicht mit fseek(...) den Zeiger 'stoerst', mueste das klappen!
Probiermal die MP3- Datei die Du gelinkt hattest! Da ist der Header gleich am Anfang! Und dann mit dem Debuggerganz langsam durchgehen!
Haste den Typecast mal entfernt?
-
Hi
Euer Problem läst so lösen
const unsigned char FILLED_BITS = '\xFF';
Dann kannst du:
while (fread(&OneByte,1,1,FilePointer )==1) //Ein Byte lesen { if (OneByte==char(0xFF)) //alle Bits gesetzt? { cout << "8Bits Set gefunden"<<endl;
-
@DerAltenburger:
Ja ich habe den Typecast mal entfernt.
Das hat aber nichts gebracht.
Wenn ich dem FilePointer seine aktuelle Position gespeichert habe, muss ich die dann auch bei fread irgendwo angeben?
Ich bin die datei "Dreierbezeihung.mp3" mal durchgegangen und beim ersten durchlauf kam bei mir in der Variable (First4x8Bits) das rein -> 4657488. (ich weiss dass es First4x8Bits und nicht OneByte ist, aber das ist ja egal oder nicht?)while (fread(&OneByte,1,1,FilePointer )==1) //Ein Byte lesen { pos = ftell (datei); fseek (datei, pos+1, SEEK_SET); //pos+1 damit er ein byte weiter hüpft if (OneByte==0xFF) //alle Bits gesetzt? { cout << "8Bits Set gefunden"<<endl; break; } }
Die sache mitvon <DerAufDieSprüngeHelfer> hat übrigends gar nichts gebacht
[ Dieser Beitrag wurde am 30.03.2003 um 21:01 Uhr von Peter Piksa editiert. ]
-
Da haste 'n tollen Fehler drin!!!
Wenn in Variable (First4x8Bits) 4657488 steht, kanns net gehen!
Dann ist First4x8Bits keine 1 Byte Variable - 0..255 (-128 .. 127 erlaubt)
Wenn der Datentyp nicht stimmt, klappt der Vergleich nicht!!!
DU MUSST OneByte nehmen - und das muss ein 1 Byte Typ sein!!!
PS: DerAufDieSprüngeHelfer hat irgendwas weggelassen???
[ Dieser Beitrag wurde am 30.03.2003 um 21:09 Uhr von DerAltenburger editiert. ]
-
ich habe mal ne kurze zwischenfrage zu dem thema :).
wenn ich mir die ersten zwoelf bytes der datei (dreier....mp3) ausgeben
lasse, dann sind die bytes paarweise vertauscht.
ein hex dump liefert folgendes:
ff fa ....
mein program vertauscht die bits und liefert:
f f a f
1111 11111 0101 11111habt ihr das auch oder mach ich was falsch?!
-
WOAAAAH!!!! Ich geh kaputt!!! *freudensprungmach* !!!
Es Läuft!!!
int main () { long int First4x8Bit; //Speicher fuer 32 Bit=4 Byte short int Bits[32]; //Char- Vektor fuer Bit- Zustand short int Bits2[8]; char OneByte; long int pos; int count = 0; const unsigned char FILLED_BITS = '0xFF'; FILE * FilePointer = fopen("C:\\Emmanuel Top - Turkish Bazar 2002 (Radio MX).mp3", "rb"); while (fread(&OneByte,1,1,FilePointer )==1) //Ein Byte lesen { if (OneByte==char(0xFF)) //alle Bits gesetzt? { //cout << "8Bits Set gefunden"<<endl; break; } else //cout << "Bits nicht gefunden"<<endl; count++; } cout << "File Header located at Byte" << count << endl; fclose(FilePointer); FilePointer = fopen("C:\\Emmanuel Top - Turkish Bazar 2002 (Radio MX).mp3", "rb"); fseek (FilePointer, count, SEEK_SET); for (int j=0;j<4;j++) //4 Bytes { fread(&First4x8Bit,1,1,FilePointer ); //Block- Lesen!!!(Binaerdatei) for (int i=0 ; i<8 ; i++) //Alle 8 Bits durchgehen { if ((First4x8Bit&(1<<i)) > 0) Bits[i + 24 - 8 * j] = 1; //Charvektor belegen else Bits[i + 24 - 8 * j] = 0; } } fclose(FilePointer);
Ich raffs zwar nicht so ganz aber es geht *rofl*
-
@Peter Piksa
Na dann war die ganze Aufregung ja wenigstens nicht umsonst!
Das hatten wir auch! Die Bytes stehen so komisch drin.
Schau mal ca 2 Seiten weiter vorn nach, da haben wir das diskutiert!
-
Es wird ja gesagt dass wenn man das ff Byte gefunden hat, mann eigentlich noch die drauf folgenden drei Bits lesen sollte aber ich habe jetzt knapp 20 mp3s getestet und überall kam das richtige ergebnis raus
Meint ihr man sollte das trotzdem einbauen?
-
Ok, es ist geschen. *fg*
"Cannibal Corpse featuring Tori Amos - Stripped, Raped And Strangled .mp3" hat das Programm, so wie es jetzt ist an einen Fehler getrieben. Also werd ich wohl doch noch die Prüfung mit den drei bits hinzunehmen müssen. Ich hoffe ich schaff das...
-
@peter
mir ist grade was aufgefallen (was mir eigentlich haette
frueher auffallen sollen).
stichwort big und little endian.
das programm liesst zwar alles richtig ein, aber die
bytes werden intern anders dargestellt.
d.h. bei einer ausgabe der bytes sind die hoeherwertigen
bytes rechts, die niederen links.
in den mp3 dateien, ist es genau umgekehrt.
so wie es aussieht, muessen die bytes wohl erst gedreht werden.
-
@entelechie:
Gestern Abend hab ich mir genau darüber auch Gedanken gemacht *g*
weil ich lese ja erstmal ein Byte ein, prüfe auf 0xFF und dann noch ein Byte. (FrameSync). Die 11Bits für die FrameSync liegen aber am ende der 4Byte. Ich wollts nur nicht sagen weil ich mir dachte dass ihr das schon richtig gemacht habt...
Hmm muss ich eigentlich die einzelnen 4 Bytes einfach nur umdrehen wie hier:aus [1Byte] [2Byte] [3Byte] [4Byte]
wird [4Byte] [3Byte] [2Byte] [1Byte]oder muss ich die einzelnen Bits darum umdrehn wie hier:
aus [12345678] [12345678] [12345678] [12345678]
wird [87654321] [87654321] [87654321] [87654321]@DerAltenburger:
Wo ich schonmal dabei bin würd ich gern mal fragen ob das ganze hier korrekt ist. Es handelt sich um die Prüfung ob das nächte Byte (die drei einsen) nach dem 8x1Bits-Byte folgt.Bei mir läuft es eigentlich ganz gut, wie gesagt nur bei der einen Mp3 von Cannibal Corpse feat. Tori Amos macht er zicken...
const unsigned char FILLED_BITS = '0xFF'; const unsigned char FILLED_BITS2 = '0xE0'; FilePointer = fopen("C:\\Music\\d-12 - devil's night\\d12 - 06 - ain' t nuttin' but music.mp3", "rb"); while (fread(&OneByte,1,1,FilePointer )==1) //Ein Byte lesen { if (OneByte==char(0xFF)) //alle Bits gesetzt? { fread(&OneByte,1,1,FilePointer); count++; if (OneByte>=char(0xE0)) { cout << OneByte<<endl; cout << "8Bits Set gefunden"<<endl; break; } } count++; } count--; cout << "File Header located at Byte" << count << endl; fclose(FilePointer);
[ Dieser Beitrag wurde am 31.03.2003 um 15:16 Uhr von Peter Piksa editiert. ]
-
also peter meine antwort is nur mal unter vorbehalt.
nicht das du ein riesen programmieraufwand hast, weil
ich dir muell erzaehlt habe :).aber es sieht alles so aus als seien die hoeherwertigen
und niederwertigen bytes verdreht.
das einlesen, und testen der einzelnen bits funktioniert
auf jeden fall so wie ich es gepostet habe (den code von altenburger
hab ich nicht getestet).also zum beispiel deine mp3 datei:
die ersten 2 byte sind (als ascii-code) (255) (250).
als bitweise ausgabe kommt: (1111 1111) (0101 1111)
(in den klammern je ein byte).
wie du siehst am beispiel von 250 stehen die hoechstwertigen bits
innerhalb eines bytes rechts.
-
@peter
mir faellt noch was auf.
bei deiner pruefung fuer die 3 bits musst du natuerlich
die anderen 5 bits rausmaskieren, denn diese koennen beliebig
sein.
du suchst nach einer bitfolge: 1111 1111 111x xxxx
(jetzt mal unabhaengig von meinem post zu big/little endian,
also nicht irritiert sein :)).
also musst du, nachdem du die bitfolge 1111 1111 gefunden
hast, das naechste byte mit 224 verunden:eingelesenes bit: 111x xxxx maske: &1110 0000 (224) ---------------------------- 111000000 (224)
und testen, ob das ergebnis der bitweisen und verknuepfung 224 ergibt.
-
Mitlerweile bin ich ein wenig durcheinander gekommen was das das einlesen und abspeichern anbelangt. Ich denke ich sollte eine grundlegene sache klären. Was ist der Unterschied zwischen der Reihenfolge wie die 4Byte in meiner mp3 liegen und den 4Byte wie ich sie in meinem Programm abspeichere? Der momentane Code ist der hier:
#include <iostream> #include <conio.h> #include <fstream> using namespace std; int main () { long int First4x8Bit; //Speicher fuer 32 Bit=4 Byte short int Bits[32]; //Char- Vektor fuer Bit- Zustand short int Bits2[8]; char OneByte; int count = 0; const unsigned char FILLED_BITS = '0xFF'; const unsigned char FILLED_BITS2 = '0xE0'; FILE * FilePointer; //File Header erst einmal finden FilePointer = fopen("C:\\Music\\d-12 - devil's night\\d12 - 11 - fight music.mp3", "rb"); while (fread(&OneByte,1,1,FilePointer )==1) //Ein Byte lesen { if (OneByte==char(0xFF)) //alle Bits gesetzt? { fread(&OneByte,1,1,FilePointer); if (OneByte>=char(0xE0)) { cout << "8Bits Set gefunden"<<endl; break; } } count++; } cout << "File Header located at Byte" << count << endl; fclose(FilePointer); //4Bytes nach finden des Mp3 Headers einlesen FilePointer = fopen("C:\\Music\\d-12 - devil's night\\d12 - 11 - fight music.mp3", "rb"); fseek (FilePointer, count, SEEK_SET); for (int j=0;j<4;j++) //4 Bytes { fread(&First4x8Bit,1,1,FilePointer ); //Block- Lesen!!!(Binaerdatei) for (int i=0 ; i<8 ; i++) //Alle 8 Bits durchgehen { if ((First4x8Bit&(1<<i)) > 0) Bits[i + 24 - 8 * j] = 1; //Charvektor belegen else Bits[i + 24 - 8 * j] = 0; } } fclose(FilePointer); //Ausgeben der 32Bit for (int i=0 ; i<32; i++) { cout << "Bit " << i << ": " << Bits[i] << endl; } }
Nehmen wir mal an der Header in meiner Mp3 sieht so aus:
Byte1 Byte 2 Byte 3 Byte 4 00110011 00001111 01010111 1111111 |frame sync|
wenn ich es mit meinem code ausgebe, kommt es auch in dieser reihenfolge raus.
aber wie wird es abgespeichert? das ist doch anders rum oder nicht?[ Dieser Beitrag wurde am 31.03.2003 um 20:36 Uhr von Peter Piksa editiert. ]
-
peter.... lol ich hoffe ich hab dich nicht zusehr verwirrt .
also was deine einlesen-schleife angeht ... ui... sieht kompliziert
aus; und ich hab keine ahnung was du da machst...
ich poste dir unten mal einen programmteil, der dir die ersten
32 bits ausgibt, schau es dir mal an, es sollte einfacher
zu verstehen sein als dein bissheriger code.das programm liefert dir als ausgabe:
(1111 1111) (0101 1111) (0000 1001) (0000 0010)
die klammern sind wieder die bytegrenzen.wenn du jetzt den header suchen willst, musst du immer ein
byte einlesen. das eingelsenen byte vergleichst du mit 255
(-> alle bits 1, also if ( byte == 255 ) ).
hast du ein solches byte gefunden, musst du schauen, ob das
naechste byte die form 111x xxx hat.
also:
if ( (byte & 224) == 224 )
/* die ersten 3 byte sind 111 -> header gefunden */das funktioniert auf jeden fall; egal wie die bytes intern
angeordnet sind.hast du den header gefunden, und willst nun die einzelnen
bits abfragen taucht wahrscheinlich ein problem auf.
jetzt kann es sein das ich ein bisschen muell erzaehle :),
das musst du mal mit deinem programm nachpruefen.
es sieht so aus als seien in den mp3 dateien die einzelnen
bits wie folgt angeordnet:5 6 7 8 1 2 3 4 (bitnr) 1 1 1 1 0 1 0 1 (bits) (---EIN BYTE---) sollte das so sein, so musst du die beiden halbbytes zuerst vertauschen, bevor du abfragen kannst, ob z.b. das 1. bit gesetzt ist (weil das erste bit ja von links gesehen an 5. stelle steht).
so nun zum code
schau dir mal folgende zeilen an:
(der header BEGINNT mit den syn-bits und endet nicht
damit, schau nochmal in die definition der mp3s!)#define BITSET_BYTESIZE 8 /* Prueft, ob das bit an der Stelle bitnr * gesetzt ist oder nicht. * * Bit Nr. 1 steht links. */ int bitset_isset( const unsigned char* bytes, int bitnr ) { const short int MASKE = 1; while ( bitnr > BITSET_BYTESIZE ) { ++bytes; bitnr -= BITSET_BYTESIZE; } --bitnr; return ( (*bytes) & ( MASKE << bitnr ) ); } .... char puffer[4]; fread( puffer, 1, 4, mp3 ); for ( i = 1; i <= 32; ++i ) { if ( bitset_isset( puffer, i ) ) printf( "%d", 1 ); else printf( "%d", 0 ); if ( i % 4 == 0 ) printf( " " ); } printf( "\n" ); fclose( mp3 );
[ Dieser Beitrag wurde am 31.03.2003 um 19:17 Uhr von entelechie editiert. ]
-
@entelelchie:
Der Header beginnt nicht mit den 11Bits Frame Sync.
Er endet mit ihnen.
Schau mal hier: http://home.swipnet.se/grd/mp3info/frmheader/index.html
da stehts schwarz auf organge *g*
Position: 21-31.Könnte ich denn nicht auch wenn das hier stimmt,
5 6 7 8 1 2 3 4 (bitnr) 1 1 1 1 0 1 0 1 (bits) (---EIN BYTE---)
einfach den RechtsShiftOperator verwenden?
[ Dieser Beitrag wurde am 31.03.2003 um 20:56 Uhr von Peter Piksa editiert. ]
-
Hi alle zusammen
Irgendwas scheint mit der Bit / Byte- Anordnung nicht zu stimmen.
So wie ich das sehe (getestet hab):
Die Suche nach dem Header mueste so gehen, wie gepostet (Bei mir findet der die Header - z.T. mehrere in der Datei)
Die 2 zu testenden Byte stehen DIREKT hintereinander!!!
d.h.: wenn du das Byte 0xff gefunden hast, muss das FOLGENDE Byte 0xe0 oder groesser sein! Da das die 3 hoechsten Bit im Byte sind, geht das ohne Maskierung.(Jedes weitere Bit vergroessert den Wert)Das Auslesen des Headers muesste so gehen, wie wir das 3 Seiten vorher im Thema hatten! Dazu muss der Header komplett gelesen werden: Die 2 Testbyte gehoeren dazu!!! Deshalb Filepointer neu setzen - muss 2 Byte zurueck.
Die Auswertung der 4 Headerbytes war in 'verdrehter Reihenfolge'
Du sagst, mit dem Test (letzte variante) findet der die Header. Die Auswertung klappte wie Du sagst auch.
Also muesste das doch richtig sein! Wenn das klappt bis auf EINE EINZIGE Datei, wuerde ich sagen ok, die Datei hat ev. einen Fehler oder ein Neues Foermat?
-
Original erstellt von DerAltenburger:
**Hi alle zusammen
Die 2 zu testenden Byte stehen DIREKT hintereinander!!!
d.h.: wenn du das Byte 0xff gefunden hast, muss das FOLGENDE Byte 0xe0 oder groesser sein! Da das die 3 hoechsten Bit im Byte sind, geht das ohne Maskierung.(Jedes weitere Bit vergroessert den Wert)
**Die 11 Bits Frame Sync sind die letzen der 32Bits Header.
dass heisst mann muss wenn überhaupt dann erstmal ein Byte suchen bei dem die drei LowBits 1 sind und daraufhin testen ob das nächste byte 0xFF ist!Es sieht doch so aus:
(xxxx xxxx) (xxxx xxxx) (xxxx x111) (1111 1111)
Ich meine da steht doch auf der von mir verlinkten seite beschrieben dass die 11 Bits position 21-31 des Headers belegen...